Przewodnik dla programistów interfejsu Attribution Reporting API

.

Podczas czytania informacji z Piaskownicy prywatności na urządzeniu z Androidem dokumentacji, kliknij przycisk Podgląd dla programistów lub Beta, aby wybrać używanej wersji programu, ponieważ instrukcje mogą się różnić.


Prześlij opinię

Interfejs Attribution Reporting API ma zapewniać lepszą ochronę prywatności użytkowników wyeliminowanie polegania na identyfikatorach użytkowników w różnych firmach i kluczowych przypadków użycia. do atrybucji i pomiaru konwersji w aplikacjach. Ten przewodnik dla programistów opisuje, jak skonfigurować i przetestować interfejsy Attribution Reporting API w celu rejestracji. kliknięć, wyświetleń i konwersji za pomocą metod połączeń, które rejestrują odpowiednie czynników i źródeł takich zdarzeń.

Z tego przewodnika dowiesz się, jak skonfigurować punkty końcowe serwera i utworzyć aplikację kliencką który sygnalizuje te usługi. Więcej informacji o ogólnym wyglądzie atrybucji Interfejs API do raportowania w propozycji projektu.

Hasła kluczowe

  • Źródła atrybucji odnoszą się do kliknięć lub wyświetleń.
  • Reguły to zdarzenia, które można przypisać do konwersji.
  • Raporty zawierają dane o regułach i odpowiadających im atrybucjach źródła. Raporty są wysyłane w odpowiedzi na zdarzenia wywołujące. Interfejs Attribution Reporting API obsługuje raporty na poziomie zdarzenia oraz raportów zbiorczych.

Zanim zaczniesz

Aby korzystać z interfejsu Attribution Reporting API, uzupełnij dane po stronie serwera i klienta. zadania wymienione w poniższych sekcjach.

Konfigurowanie punktów końcowych Attribution Reporting API

Interfejs Attribution Reporting API wymaga zestawu punktów końcowych, do których masz dostęp z urządzenia testowego lub emulatora. Utwórz po jednym punkcie końcowym dla każdego z poniższych zadania po stronie serwera:

Wymagane punkty końcowe można skonfigurować na kilka sposobów:

  • Najszybszym sposobem na rozpoczęcie jest wdrożenie Definicje usług OpenAPI w wersji 3 z przykładowego kodu na przykładową platformę mikroserwisów. Za pomocą Postman, Prism lub dowolny inny serwer pozorowany platformy, która akceptuje ten format. Wdróż każdy punkt końcowy i śledź identyfikatory URI używane w aplikacji. Aby sprawdzić dostarczenie raportu, zapoznaj się z informacjami o połączeniach które były wcześniej wprowadzane na pozorną lub bezserwerową platformę.
  • Uruchom własny, samodzielny serwer oparty na modelu Spring Boot Przykład z Kotlin. Wdróż ten serwer u dostawcy chmury lub wewnętrzny i infrastrukturze.
  • Użyj definicji usług jako przykładów, aby zintegrować punkty końcowe z istniejącego systemu.
.

Zaakceptuj rejestrację źródła

Ten punkt końcowy powinien być adresowalny z użyciem identyfikatora URI podobnego do tego:

https://adtech.example/attribution_source

Gdy aplikacja kliencka rejestruje źródło atrybucji, podaje identyfikator URI dla: tego punktu końcowego serwera. Interfejs Attribution Reporting API wysyła następnie żądanie, zawiera jeden z następujących nagłówków:

  • W przypadku zdarzeń kliknięcia:

    Attribution-Reporting-Source-Info: navigation
    
  • W przypadku zdarzeń wyświetlania:

    Attribution-Reporting-Source-Info: event
    

Skonfiguruj punkt końcowy serwera tak, aby odpowiadał w ten sposób:

// Metadata associated with attribution source.
Attribution-Reporting-Register-Source: {
  "destination": "[app package name]",
  "web_destination": "[eTLD+1]",
  "source_event_id": "[64 bit unsigned integer]",
  "expiry": "[64 bit signed integer]",
  "event_report_window": "[64-bit signed integer]",
  "aggregatable_report_window": "[64-bit signed integer]",
  "priority": "[64 bit signed integer]",
  "filter_data": {
    "[key name 1]": ["key1 value 1", "key1 value 2"],
    "[key name 2]": ["key2 value 1", "key2 value 2"],
    // Note: "source_type" key will be automatically generated as
    // one of {"navigation", "event"}.
  },
  // Attribution source metadata specifying histogram contributions in aggregate
  // report.
  "aggregation_keys": {
    "[key1 name]": "[key1 value]",
    "[key2 name]": "[key2 value]",
  },

    "debug_key": "[64-bit unsigned integer]",
    "debug_reporting": [boolean]
}
// Specify additional ad tech URLs to register this source with.
Attribution-Reporting-Redirect: <Ad Tech Partner URI 1>
Attribution-Reporting-Redirect: <Ad Tech Partner URI 2>

Oto przykład z dodanymi przykładowymi wartościami:

Attribution-Reporting-Register-Source: {
  "destination": "android-app://com.example.advertiser",
  "source_event_id": "234",
  "expiry": "259200",
  "event_report_window": "172800",
  "aggregatable_report_window": "172800",
  "priority": "5",
  "filter_data": {
    "product_id": ["1234"]
  },
  "aggregation_keys": {
  // Generates a "0x159" key piece named (low order bits of the key) for the key
  // named "campaignCounts".
  // User saw an ad from campaign 345 (out of 511).
    "campaignCounts": "0x159",

  // Generates a "0x5" key piece (low order bits of the key) for the key named
  // "geoValue".
  // Source-side geo region = 5 (US), out of a possible ~100 regions.
    "geoValue": "0x5",
  },
  // Opts in to receiving verbose debug reports
  "debug_reporting": true
}

Attribution-Reporting-Redirect:
https://adtechpartner1.example?their_ad_click_id=567
Attribution-Reporting-Redirect:
https://adtechpartner2.example?their_ad_click_id=890

Jeśli Attribution-Reporting-Redirects zawiera identyfikatory URI partnerów oferujących technologie reklamowe, w parametrze Interfejs Attribution Reporting API wysyła następnie żądanie podobne do każdego identyfikatora URI. Każda technologia reklamowa partner musi skonfigurować serwer, który odpowiada przy użyciu tych nagłówków:

Attribution-Reporting-Register-Source: {
  "destination": "[app package name]",
  "web_destination": "[eTLD+1]",
  "source_event_id": "[64 bit unsigned integer]",
  "expiry": "[64 bit signed integer]",
  "event_report_window": "[64-bit signed integer]",
  "aggregatable_report_window": "[64-bit signed integer]",
  "priority": "[64 bit signed integer]",
  "filter_data": {
    "[key name 1]": ["key1 value 1", "key1 value 2"],
    "[key name 2]": ["key2 value 1", "key2 value 2"],
    // Note: "source_type" key will be automatically generated as
    // one of {"navigation", "event"}.
  },
  "aggregation_keys": {
    "[key1 name]": "[key1 value]",
    "[key2 name]": "[key2 value]",
  }
}
// The Attribution-Reporting-Redirect header is ignored for ad tech partners.

Zaakceptuj rejestrację reguły konwersji

Ten punkt końcowy powinien być adresowalny z użyciem identyfikatora URI podobnego do tego:

https://adtech.example/attribution_trigger

Gdy aplikacja kliencka rejestruje zdarzenie aktywujące, udostępnia identyfikator URI obiektu punktu końcowego serwera. Interfejs Attribution Reporting API wysyła żądanie, które zawiera parametr jeden z następujących nagłówków:

Skonfiguruj punkt końcowy serwera tak, aby odpowiadał w ten sposób:

// Metadata associated with trigger.
Attribution-Reporting-Register-Trigger: {
  "event_trigger_data": [{
    // "trigger_data returned" in event reports is truncated to
    // the last 1 or 3 bits, based on conversion type.
    "trigger_data": "[unsigned 64-bit integer]",
    "priority": "[signed 64-bit integer]",
    "deduplication_key": "[signed 64-bit integer]",
    // "filter" and "not_filters" are optional fields which allow configuring
    // event trigger data based on source's filter_data. They consist of a
    // filter set, which is a list of filter maps. An event_trigger_data object
    // is ignored if none of the filter maps in the set match the source's
    // filter data.
    // Note: "source_type" can be used as a key in a filter map to filter based
    // on the source's "navigation" or "event" type. The first
    // Event-Trigger that matches (based on the filters/not_filters) will be
    // used for report generation. If none of the event-triggers match, no
    // event report will be generated.
    "filters": [{
      "[key name 1]": ["key1 value 1", "key1 value 2"],
      // If a key is missing from filters or source's filter_data, it won't be
      // used during matching.
      "[key name 2]": ["key2 value 1", "key2 value 2"],
    }],
    "not_filters":  [{
      "[key name 1]": ["key1 value 1", "key1 value 2"],
      // If a key is missing from not_filters or source's filter_data, it won't
      // be used during matching.
      "[key name 2]": ["key2 value 1", "key2 value 2"],
    }]
  }],
  // Specify a list of dictionaries that generates aggregation keys.
  "aggregatable_trigger_data": [
    // Each dictionary entry independently adds pieces to multiple source keys.
    {
      "key_piece": "[key piece value]",
      "source_keys": ["[key name the key piece value applies to]",
      ["list of IDs in source to match. Non-matching IDs are ignored"]]
      // filters/not_filters are optional fields similar to event trigger data
      // filter fields.
      "filters": [{
        "[key name 1]": ["key1 value 1", "key1 value 2"]
      }],
      "not_filters":  [{
          "[key name 1]": ["key1 value 1", "key1 value 2"],
          "[key name 2]": ["key2 value 1", "key2 value 2"],
      }]
    },
    ..
  ],
  // Specify an amount of an abstract value which can be integers in [1, 2^16]
  // to contribute to each key that is attached to aggregation keys in the
  // order they are generated.
  "aggregatable_values": [
     // Each source event can contribute a maximum of L1 = 2^16 to the
     // aggregate histogram.
    {
     "[key_name]": [value]
    },
    ..
  ],
  aggregatable_deduplication_keys: [{
  deduplication_key": [unsigned 64-bit integer],
    "filters": {
        "category": [filter_1, , filter_H]
      },
    "not_filters": {
        "category": [filter_1, , filter_J]
      }
  },
  ...
  {
  "deduplication_key": [unsigned 64-bit integer],
    "filters": {
        "category": [filter_1, , filter_D]
      },
    "not_filters": {
        "category": [filter_1, , filter_J]
      }
    }
  ]

  "debug_key": "[64-bit unsigned integer]",
  "debug_reporting": [boolean]

}
// Specify additional ad tech URLs to register this trigger with.
// Repeated Header field "Attribution-Reporting-Redirect"
Attribution-Reporting-Redirect: <Ad Tech Partner URI 1>
Attribution-Reporting-Redirect: <Ad Tech Partner URI 2>

Oto przykład z dodanymi przykładowymi wartościami:

Attribution-Reporting-Register-Trigger: {
  "event_trigger_data": [{
    "trigger_data": "1122", // Returns 010 for CTCs and 0 for VTCs in reports.
    "priority": "3",
    "deduplication_key": "3344"
    "filters": [{ // Filter strings can not exceed 25 characters
      "product_id": ["1234"],
      "source_type": ["event"]
    }]
  },
  {
    "trigger_data": "4", // Returns 100 for CTCs and 0 for VTCs in reports.
    "priority": "3",
    "deduplication_key": "3344"
    "filters": [{ // Filter strings can not exceed 25 characters
      "product_id": ["1234"],
      "source_type": ["navigation"]
    }]
  }],
  "aggregatable_trigger_data": [
    // Each dictionary independently adds pieces to multiple source keys.
    {
      // Conversion type purchase = 2 at a 9-bit offset, i.e. 2 << 9.
      // A 9-bit offset is needed because there are 511 possible campaigns,
      // which takes up 9 bits in the resulting key.
      "key_piece": "0x400",// Conversion type purchase = 2
      // Apply this key piece to:
      "source_keys": ["campaignCounts"]
       // Filter strings can not exceed 25 characters
    },
    {
      // Purchase category shirts = 21 at a 7-bit offset, i.e. 21 << 7.
      // A 7-bit offset is needed because there are ~100 regions for the geo
      // key, which takes up 7 bits of space in the resulting key.
      "key_piece": "0xA80",
      // Apply this key piece to:
      "source_keys": ["geoValue", "nonMatchingIdsAreIgnored"]
      // source_key values must not exceed the limit of 25 characters
    }
  ],
  "aggregatable_values":
    {
      // Privacy budget for each key is L1 / 2 = 2^15 (32768).
      // Conversion count was 1.
      // Scale the count to use the full budget allocated: 1 * 32768 = 32768.
      "campaignCounts": 32768,

      // Purchase price was $52.
      // Purchase values for the app range from $1 to $1,024 (integers only).
      // Scaling factor applied is 32768 / 1024 = 32.
      // For $52 purchase, scale the value by 32 ($52 * 32 = $1,664).
      "geoValue": 1664
    }
  ,
  // aggregatable_deduplication_keys is an optional field. Up to 50 "keys"
  // can be included in the aggregatable_deduplication_keys list. Filters, not
  // filters, and deduplication_key are optional fields. If deduplication_key
  // is omitted, it will be treated as a null value. See
  // https://wicg.github.io/attribution-reporting-api/#triggering-aggregatable-attribution
  aggregatable_deduplication_keys:
  [
    {
    deduplication_key": 3,
        "filters": {
          "category": [A]
        }
    },
    {
    "deduplication_key": 4,
        "filters": {
          "category": [C, D]
        },
        "not_filters": {
          "category": [F]
        }
    }
  ]
  // Opts into receiving verbose debug reports
  "debug_reporting": true
}
Attribution-Reporting-Redirect:https://adtechpartner.example?app_install=567

Obowiązuje limit 25 bajtów na identyfikator klucza agregacji i ciąg filtra. Ten oznacza, że identyfikatory kluczy agregacji i ciągi filtrów nie powinny przekraczać 25 znaków. W tym przykładzie campaignCounts ma 14 znaków, więc jest prawidłową wartością identyfikator klucza agregacji, 1234 ma 4 znaki, więc jest to prawidłowy ciąg filtra. Jeśli identyfikator klucza agregacji lub ciąg filtra przekracza 25 znaków, aktywatorem jest zignorowano.

Jeśli Attribution-Reporting-Redirect zawiera identyfikatory URI partnerów oferujących technologie reklamowe, w parametrze Interfejs Attribution Reporting API wysyła następnie żądanie podobne do każdego identyfikatora URI. Każda technologia reklamowa partner musi skonfigurować serwer, który odpowiada przy użyciu tych nagłówków:

// Metadata associated with trigger.
Attribution-Reporting-Register-Trigger: {
  "event_trigger_data": [{
    // "trigger_data" returned in event reports is truncated to
    // the last 1 or 3 bits, based on conversion type.
    "trigger_data": "[unsigned 64-bit integer]",
    "priority": "[signed 64-bit integer]",
    "deduplication_key": "[signed 64-bit integer]",
    // filter and not_filters are optional fields which allow configuring
    // different event trigger data based on source's filter_data. They
    // consist of a filter set, which is a list of filter maps. An
    // event_trigger_data object is ignored if none of the filter maps in the
    // set match the source's filter data. Note: "source_type" can be used as
    // a key in a filter map to filter based on the source's "navigation" or
    // "event" type. The first Event-Trigger that matches (based on the
    // filters/not_filters) will be used for report generation. If none of the
    // event-triggers match, no report will be generated.
    "filters": [{
      "[key name 1]": ["key1 value 1", "key1 value 2"],
      // If a key is missing from filters or source's filter_data, it will not be
      // used during matching.
      "[key name 2]": ["key2 value 1", "key2 value 2"],
    }],
    "not_filters":  [{
      "[key name 1]": ["key1 value 1", "key1 value 2"],
      // If a key is missing from not_filters or source's filter_data, it will not
      // be used during matching.
      "[key name 2]": ["key2 value 1", "key2 value 2"],
    }]
  }],
  "aggregatable_trigger_data": [
    // Each dictionary entry independently adds pieces to multiple source keys.
    {
      "key_piece": "[key piece value]",
      "source_keys": ["[key name the key piece value applies to]",
      ["list of IDs in source to match. Non-matching IDs are ignored"]],
      // filters/not_filters are optional fields similar to event trigger data
      // filter fields.
      "filters": [{
        "[key name 1]": ["key1 value 1", "key1 value 2"]
      }],
      "not_filters":  [{
          "[key name 1]": ["key1 value 1", "key1 value 2"],
          "[key name 2]": ["key2 value 1", "key2 value 2"],
      }]
    },
    ..
  ],
  // Specify an amount of an abstract value which can be integers in [1, 2^16] to
  // contribute to each key that is attached to aggregation keys in the order they
  // are generated.
  "aggregatable_values": [
    // Each source event can contribute a maximum of L1 = 2^16 to the aggregate
    // histogram.
    {
     "[key_name]": [value]
    }
  ]
}
// The Attribution-Reporting-Redirect header is ignored for ad tech partners.

Akceptowanie raportów na poziomie zdarzenia

Ten punkt końcowy powinien być adresowalny za pomocą identyfikatora URI. Zapoznaj się z sekcją Rejestracja w programie ochrony prywatności Konto w trybie piaskownicy, w którym znajdziesz więcej informacji o rejestrowaniu identyfikatorów URI. (Identyfikator URI to wywnioskowane na podstawie pochodzenia serwerów używanych do akceptowania rejestracji źródła oraz proces rejestracji). Używanie przykładowych identyfikatorów URI punktów końcowych, które akceptują źródło rejestracja i zaakceptuj rejestrację aktywatora, identyfikator URI tego punktu końcowego to:

https://adtech.example/.well-known/attribution-reporting/report-event-attribution

Skonfiguruj ten serwer tak, aby akceptował żądania JSON w tym formacie:

{
  "attribution_destination": "android-app://com.advertiser.example",
  "source_event_id": "12345678",
  "trigger_data": "2",
  "report_id": "12324323",
  "source_type": "navigation",
  "randomized_trigger_rate": "0.02"
   [Optional] "source_debug_key": "[64-bit unsigned integer]",
   [Optional] "trigger_debug_key": "[64-bit unsigned integer]",
}

Klucze debugowania zapewniają dodatkowy wgląd w raporty atrybucji. dowiedz się więcej o ich konfigurowaniu.

Akceptowanie raportów agregowanych

Ten punkt końcowy powinien być adresowalny za pomocą identyfikatora URI. Zapoznaj się z sekcją Rejestracja w programie ochrony prywatności Konto w trybie piaskownicy, w którym znajdziesz więcej informacji o rejestrowaniu identyfikatorów URI. (Identyfikator URI to wywnioskowane na podstawie pochodzenia serwerów używanych do akceptowania rejestracji źródła oraz proces rejestracji). Używanie przykładowych identyfikatorów URI punktów końcowych, które akceptują źródło rejestracja i zaakceptuj rejestrację aktywatora, identyfikator URI tego punktu końcowego to:

https://adtech.example/.well-known/attribution-reporting/report-aggregate-attribution

Zarówno zaszyfrowane, jak i niezaszyfrowane pola są wypełniane na potrzeby agregacji raportów. Zaszyfrowane raporty umożliwiają rozpoczęcie testów z użyciem agregacji usługi, a pole niezaszyfrowane dostarcza informacji o sposobie ustawiania par klucz-wartość w parach określa się strukturę danych.

Skonfiguruj ten serwer tak, aby akceptował żądania JSON w tym formacie:

{
  // Info that the aggregation services also need encoded in JSON
  // for use with AEAD. Line breaks added for readability.
  "shared_info": "{
     \"api\":\"attribution-reporting\",
     \"attribution_destination\": \"android-app://com.advertiser.example.advertiser\",
     \"scheduled_report_time\":\"[timestamp in seconds]\",
     \"source_registration_time\": \"[timestamp in seconds]\",
     \"version\":\"[api version]\",
     \"report_id\":\"[UUID]\",
     \"reporting_origin\":\"https://reporter.example\" }",

  // In the current Developer Preview release, The "payload" and "key_id" fields
  // are not used because the platform does not yet encrypt aggregate reports.
  // Currently, the "debug_cleartext_payload" field holds unencrypted reports.
  "aggregation_service_payloads": [
    {
      "payload": "[base64 HPKE encrypted data readable only by the aggregation service]",
      "key_id": "[string identifying public key used to encrypt payload]",

      "debug_cleartext_payload": "[unencrypted payload]"
    },
  ],

  "source_debug_key": "[64 bit unsigned integer]",
  "trigger_debug_key": "[64 bit unsigned integer]"
}

Klucze debugowania zapewniają dodatkowy wgląd w raporty atrybucji. dowiedz się więcej o ich konfigurowaniu.

Skonfiguruj klienta Androida

Aplikacja kliencka rejestruje źródła i reguły atrybucji oraz umożliwia na poziomie zdarzenia i generowania raportów agregowanych. Aby przygotować klienta Androida urządzenia lub emulatora do korzystania z interfejsu Attribution Reporting API, wykonaj te czynności:

  1. Skonfiguruj środowisko programistyczne na potrzeby Piaskownicy prywatności na na urządzeniu z Androidem.
  2. Zainstaluj obraz systemu na obsługiwanym urządzeniu lub skonfiguruj emulator, który obsługuje Piaskownicę prywatności na urządzeniach na urządzeniu z Androidem.
  3. Włącz dostęp do interfejsu Attribution Reporting API, uruchamiając polecenie za pomocą polecenia ADB. (interfejs API jest domyślnie wyłączony).

    adb shell device_config put adservices ppapi_app_allow_list \"\*\"
  4. Jeśli testujesz lokalnie interfejs Attribution Reporting API (np. testujesz na urządzenia, do którego masz fizycznie dostęp), uruchom to polecenie, aby wyłączyć rejestracja:

    adb shell device_config put adservices disable_measurement_enrollment_check "true"
  5. Uwzględnij uprawnienie ACCESS_ADSERVICES_ATTRIBUTION w Androidzie Plik manifestu i utwórz konfigurację usług reklamowych, aby Twoja aplikacja korzystają z interfejsów Attribution Reporting API:

    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
    
  6. (Opcjonalnie) Jeśli planujesz otrzymywać raporty na temat debugowania, dołącz do Uprawnienie ACCESS_ADSERVICES_AD_ID w pliku manifestu Androida:

    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />
    
  7. Odwołaj się do konfiguracji usług reklamowych w elemencie <application> tego elementu Twój plik manifestu:

    <property android:name="android.adservices.AD_SERVICES_CONFIG"
              android:resource="@xml/ad_services_config" />
    
  8. Określ zasób XML usług reklamowych, do którego odwołuje się plik manifestu, np. res/xml/ad_services_config.xml Więcej informacji o uprawnieniach do usług reklamowych i kontroli dostępu do pakietów SDK.

    <ad-services-config>
        <attribution allowAllToAccess="true" />
    </ad-services-config>
    

Rejestrowanie zdarzeń reklamowych

Aplikacja powinna rejestrować źródła i konwersje w miarę ich występowania, aby czy są prawidłowo zgłaszane. Metody klasy MeasurementManager które ułatwiają rejestrowanie zdarzeń źródła atrybucji oraz reguł konwersji.

Rejestrowanie zdarzenia źródła atrybucji

Gdy reklama zostaje wyświetlona lub kliknięta, aplikacja wydawcy wywołuje metodę registerSource() pod adresem zarejestrować źródło atrybucji, tak jak to widać we fragmencie kodu.

Interfejs Attribution Reporting API obsługuje te typy źródeł atrybucji wydarzenia:

  • kliknięcia, które zwykle rejestrujesz w ramach metody wywołania zwrotnego podobnej do onClick() Odpowiednie zdarzenie aktywujące następuje zwykle wkrótce po zdarzenie kliknięcia. Ten typ zdarzenia dostarcza więcej informacji o użytkowniku jest więc dobrym źródłem atrybucji, o wysokim priorytecie.
  • Widoków, które zwykle rejestrujesz w ramach metody wywołania zwrotnego podobnej do onAdShown() Odpowiednie zdarzenie aktywujące może wystąpić kilka godzin lub dni po zdarzeniu wyświetlenia.

Kotlin

companion object {
    private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}

val measurementManager = context.getSystemService(MeasurementManager::class.java)
var exampleClickEvent: InputEvent? = null

// Use the URI of the server-side endpoint that accepts attribution source
// registration.
val attributionSourceUri: Uri =
  Uri.parse("https://adtech.example/attribution_source?AD_TECH_PROVIDED_METADATA")

val future = CompletableFuture<Void>()

adView.setOnTouchListener(_: View?, event: MotionEvent?)) ->
    exampleClickEvent = event
    true
}

// Register Click Event
measurementManager.registerSource(
        attributionSourceUri,
        exampleClickEvent,
        CALLBACK_EXECUTOR,
        future::complete)

// Register View Event
measurementManager.registerSource(
        attributionSourceUri,
        null,
        CALLBACK_EXECUTOR,
        future::complete)

Java

private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();
private InputEvent exampleClickEvent;

MeasurementManager measurementManager =
        context.getSystemService(MeasurementManager.class);

// Use the URI of the server-side endpoint that accepts attribution source
// registration.
Uri attributionSourceUri =
Uri.parse("https://adtech.example/attribution_source?AD_TECH_PROVIDED_METADATA");

CompletableFuture<Void> future = new CompletableFuture<>();

adView.setOnTouchListener(v, event)) -> {
    exampleClickEvent = event;
    return true;
}

// Register Click Event
measurementManager.registerSource(attributionSourceUri, exampleClickEvent,
        CALLBACK_EXECUTOR, future::complete);

// Register View Event
measurementManager.registerSource(attributionSourceUri, null,
        CALLBACK_EXECUTOR, future::complete);

Po rejestracji interfejs API wysyła żądanie HTTP POST do punktu końcowego usługi pod adresem podanym przez: attributionSourceUri. Parametr punktu końcowego odpowiedź zawiera wartości dla destination, source_event_id, expiry oraz source_priority

Jeśli źródłowa technologia reklamowa chce udostępniać rejestracje źródeł, Identyfikator URI źródła atrybucji może obejmować przekierowania do innych punktów końcowych technologii reklamowych. Limity i reguł dotyczących przekierowań znajdziesz w propozycję techniczną.

Dodaliśmy obsługę przekierowań w łańcuchach połączeń w domenach registerSource i registerTrigger Oprócz nagłówka rejestracji konsument interfejsu API może teraz podasz przekierowanie HTTP jako odpowiedź serwera ze stanem 302 kod oraz „Lokalizacja” nagłówek z kolejnym adresem URL, który należy odwiedzić, aby uzyskać dodatkowe rejestracji.

Tylko „miejsce docelowe” zostało użyte pole podane przy pierwszej wizycie w całej łańcuchu połączeń. Liczba wizyt ma taki sam limit jak „Attribution-Reporting-Redirect” nagłówki. Dodatkowa obsługa przekierowań do istniejącego parametru „Attribution-Reporting-Redirect” , a jeśli oba są obecna, „Attribution-Reporting-Redirect”; zyskuje priorytet.

Rejestrowanie zdarzenia reguły konwersji

Aby zarejestrować zdarzenie reguły konwersji, wywołaj registerTrigger() w swojej aplikacji:

Kotlin

companion object {
    private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}

val measurementManager = context.getSystemService(MeasurementManager::class.java)

// Use the URI of the server-side endpoint that accepts trigger registration.
val attributionTriggerUri: Uri =
    Uri.parse("https://adtech.example/trigger?AD_TECH_PROVIDED_METADATA")

val future = CompletableFuture<Void>()

// Register trigger (conversion)
measurementManager.registerTrigger(
        attributionTriggerUri,
        CALLBACK_EXECUTOR,
        future::complete)

Java

private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();

MeasurementManager measurementManager =
        context.getSystemService(MeasurementManager.class);

// Use the URI of the server-side endpoint that accepts trigger registration.
Uri attributionTriggerUri =
        Uri.parse("https://adtech.example/trigger?AD_TECH_PROVIDED_METADATA");

CompletableFuture<Void> future = new CompletableFuture<>();

// Register trigger (conversion)
measurementManager.registerTrigger(
        attributionTriggerUri,
        CALLBACK_EXECUTOR,
        future::complete)

Po rejestracji interfejs API wysyła żądanie HTTP POST do punktu końcowego usługi pod adresem podanym przez: attributionTriggerUri. Odpowiedź punktu końcowego zawiera wartości na potrzeby raportów zbiorczych i zdarzeń.

Jeśli źródłowa platforma technologii reklamowych umożliwia udostępnianie rejestracji aktywatorów, identyfikator URI może zawierać przekierowania do identyfikatorów URI należących do innych platform technologii reklamowych. Ograniczenia i reguły dotyczące przekierowań są opisane w propozycję techniczną.

Rejestrowanie pomiarów w różnych aplikacjach i witrynach

W przypadku, gdy aplikacja i przeglądarka odgrywają rolę w na ścieżce od źródła do aktywacji, istnieją nieznaczne różnice implementacji rejestrowania zdarzeń reklamowych. Jeśli użytkownik zobaczy reklamę w aplikacji i przekierowany do przeglądarki w celu dokonania konwersji, źródło jest rejestrowane przez aplikację, a konwersja w przeglądarce. Podobnie, jeśli użytkownik uruchamia stronę i zostaje przekierowany do aplikacji, która dokonuje konwersji, przeglądarka rejestruje i aplikacja zarejestruje konwersję.

Ze względu na różnice w sposobie, w jaki technologie reklamowe są zorganizowane w sieci i w internecie, na Androida, dodaliśmy nowe interfejsy API do rejestrowania źródeł i aktywatorów, nie w przeglądarce. Kluczowa różnica między tymi interfejsami API a odpowiadającymi im interfejsy API oparte na aplikacjach wymagają, aby przeglądarka podążała za przekierowaniami, stosuje wszelkie filtrów dla danej przeglądarki oraz przekazywać na platformie prawidłowe rejestracje przez Dzwonię pod registerWebSource() lub registerWebTrigger().

Ten fragment kodu zawiera przykład wywołania interfejsu API, które przeglądarka rejestrują źródło atrybucji przed przekierowaniem użytkownika do aplikacji:

Kotlin

companion object {
    private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}

val measurementManager =
        context.getSystemService(MeasurementManager::class.java)
var exampleClickEvent: InputEvent? = null

// Use the URIs of the server-side endpoints that accept attribution source
// registration.
val sourceParam1 = WebSourceParams.Builder(Uri.parse(
        "https://adtech1.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
// True, if debugging is allowed for the ad tech.
    .setDebugKeyAllowed(true)
    .build()

val sourceParam2 = WebSourceParams.Builder(Uri.parse(
        "https://adtech2.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
    .setDebugKeyAllowed(false)
    .build()

val sourceParam3 = WebSourceParams.Builder(Uri.parse(
        "https://adtech3.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
    .build()

val sourceParams = Arrays.asList(sourceParam1, sourceParam2, sourceParam3)
val publisherOrigin = Uri.parse("https://publisher.example")
val appDestination = Uri.parse("android-app://com.example.store")
val webDestination = Uri.parse("https://example.com")

val future = CompletableFuture<Void>()

adView.setOnTouchListener {_: View?, event: MotionEvent? ->
    exampleClickEvent = event
    true
}
val clickRegistrationRequest = WebSourceRegistrationRequest.Builder(
          sourceParams,
          publisherOrigin)
      .setAppDestination(appDestination)
      .setWebDestination(webDestination)
      .setInputEvent(event)
      .build()
val viewRegistrationRequest = WebSourceRegistrationRequest.Builder(
          sourceParams,
          publisherOrigin)
      .setAppDestination(appDestination)
      .setWebDestination(webDestination)
      .setInputEvent(null)
      .build()

// Register a web source for a click event.
measurementManager.registerWebSource(
        clickRegistrationRequest,
        CALLBACK_EXECUTOR,
        future::complete)

// Register a web source for a view event.
measurementManager.registerWebSource(
        viewRegistrationRequest,
        CALLBACK_EXECUTOR,
        future::complete)

Java

private static final Executor CALLBACK_EXECUTOR =
        Executors.newCachedThreadPool();
private InputEvent exampleClickEvent;

MeasurementManager measurementManager =
        context.getSystemService(MeasurementManager.class);

// Use the URIs of the server-side endpoints that accept attribution source
// registration.
WebSourceParams sourceParam1 = WebSourceParams.Builder(Uri.parse(
        "https://adtech1.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
    // True, if debugging is allowed for the ad tech.
    .setDebugKeyAllowed(true)
    .build();

WebSourceParams sourceParam2 = WebSourceParams.Builder(Uri.parse(
        "https://adtech2.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
    .setDebugKeyAllowed(false)
    .build();

WebSourceParams sourceParam3 = WebSourceParams.Builder(Uri.parse(
        "https://adtech3.example/attribution_source?AD_TECH_PROVIDED_METADATA"))
    .build();

List<WebSourceParams> sourceParams =
        Arrays.asList(sourceParam1, sourceParam2, sourceParam3);
Uri publisherOrigin = Uri.parse("https://publisher.example");
Uri appDestination = Uri.parse("android-app://com.example.store");
Uri webDestination = Uri.parse("https://example.com");

CompletableFuture<Void> future = new CompletableFuture<>();

adView.setOnTouchListener(v, event) -> {
    exampleClickEvent = event;
    return true;
}

WebSourceRegistrationRequest clickRegistrationRequest =
        new WebSourceRegistrationRequest.Builder(sourceParams, publisherOrigin)
    .setAppDestination(appDestination)
    .setWebDestination(webDestination)
    .setInputEvent(event)
    .build();
WebSourceRegistrationRequest viewRegistrationRequest =
        new WebSourceRegistrationRequest.Builder(sourceParams, publisherOrigin)
    .setAppDestination(appDestination)
    .setWebDestination(webDestination)
    .setInputEvent(null)
    .build();

// Register a web source for a click event.
measurementManager.registerWebSource(clickRegistrationRequest,
        CALLBACK_EXECUTOR, future::complete);

// Register a web source for a view event.
measurementManager.registerWebSource(viewRegistrationRequest,
        CALLBACK_EXECUTOR, future::complete);

Ten fragment kodu zawiera przykład wywołania interfejsu API, które przeglądarka rejestruje konwersję po przekierowaniu użytkownika z aplikacji:

Kotlin

companion object {
    private val CALLBACK_EXECUTOR = Executors.newCachedThreadPool()
}

val measurementManager = context.getSystemService(MeasurementManager::class.java)

// Use the URIs of the server-side endpoints that accept trigger registration.
val triggerParam1 = WebTriggerParams.Builder(Uri.parse(
        "https://adtech1.example/trigger?AD_TECH_PROVIDED_METADATA"))
    // True, if debugging is allowed for the ad tech.
    .setDebugKeyAllowed(true)
    .build()

val triggerParam2 = WebTriggerParams.Builder(Uri.parse(
        "https://adtech2.example/trigger?AD_TECH_PROVIDED_METADATA"))
    .setDebugKeyAllowed(false)
    .build()

val triggerParams = Arrays.asList(triggerParam1, triggerParam2)
val advertiserOrigin = Uri.parse("https://advertiser.example")

val future = CompletableFuture<Void>()

val triggerRegistrationRequest = WebTriggerRegistrationRequest.Builder(
        triggerParams,
        advertiserOrigin)
    .build()

// Register the web trigger (conversion).
measurementManager.registerWebTrigger(
    triggerRegistrationRequest,
    CALLBACK_EXECUTOR,
    future::complete)

Java

private static final Executor CALLBACK_EXECUTOR =
        Executors.newCachedThreadPool();

MeasurementManager measurementManager =
        context.getSystemService(MeasurementManager.class);

// Use the URIs of the server-side endpoints that accept trigger registration.
WebTriggerParams triggerParam1 = WebTriggerParams.Builder(Uri.parse(
        "https://adtech1.example/trigger?AD_TECH_PROVIDED_METADATA"))
    // True, if debugging is allowed for the ad tech.
    .setDebugKeyAllowed(true)
    .build();

WebTriggerParams triggerParam2 = WebTriggerParams.Builder(Uri.parse(
        "https://adtech2.example/trigger?AD_TECH_PROVIDED_METADATA"))
    .setDebugKeyAllowed(false)
    .build();

List<WebTriggerParams> triggerParams =
        Arrays.asList(triggerParam1, triggerParam2);
Uri advertiserOrigin = Uri.parse("https://advertiser.example");

CompletableFuture<Void> future = new CompletableFuture<>();

WebTriggerRegistrationRequest triggerRegistrationRequest =
        new WebTriggerRegistrationRequest.Builder(
            triggerParams, advertiserOrigin)
    .build();

// Register the web trigger (conversion).
measurementManager.registerWebTrigger( triggerRegistrationRequest,
        CALLBACK_EXECUTOR, future::complete);

Dodawanie szumu w związku z ochroną prywatności

Raporty na poziomie zdarzenia zawierają miejsce docelowe, identyfikator źródła atrybucji i regułę. i skalowalnych danych. Są one wysyłane do raportu w pierwotnym (niezaszyfrowanym) formacie. pochodzeniu danych. Aby chronić prywatność użytkownika, można dodać szum, aby utrudnić identyfikować poszczególnych użytkowników. Raporty na poziomie zdarzenia zaszumione są generowane jest wysyłane zgodnie z zasadami prywatności różnicowej. Oto domyślne wartości procentowe szumu dla różnych scenariuszy:

Typ źródła

Wartość źródłowego miejsca docelowego

Prawdopodobieństwo w raporcie z hałasem na rejestrację źródła

Wyświetl

Aplikacja lub witryna

0,0000025

Wyświetl

Aplikacja i internet

0,0000042

Kliknij

Aplikacja lub witryna

0,0024263

Kliknij

Aplikacja i internet

0,0170218

W pomiarze atrybucji aplikacji do witryny, w którym źródła mogą zwiększać liczbę konwersji zarówno miejsc docelowych w aplikacjach, jak i w internecie, raporty na poziomie zdarzenia mogą określać, czy wystąpiło w aplikacji lub witrynie. Aby skompensować ten dodatkowy szczegół, funkcja generowanych raportów zaszumionych jest do 7-krotnie większej liczby kliknięć i ok.1,7-krotnie w przypadku wyświetleń.

Niektóre technologie reklamowe nie wymagają raportów na poziomie zdarzenia, aby określać, czy reguła wystąpiło w aplikacji lub miejscu docelowym w internecie. Techniki reklamowe mogą używać coarse_event_report_destinations w kolumnie Attribution-Reporting-Register-Source, aby zmniejszyć szum. Jeśli źródło z parametrem określone pole coarse_event_report_destinations wygrywa atrybucję, wartość zawiera bez rozróżnienia miejsca docelowe w aplikacjach i internecie, miejsca, w którym doszło do faktycznego wyzwalacza.

W poniższych przykładach użytkownik klika reklamę, a źródło jest zarejestrowane za pomocą interfejsu API. Następnie użytkownik dokonuje konwersji zarówno w aplikacji reklamodawcy, jak i w do witryny reklamodawcy. Obie te konwersje są rejestrowane jako reguły, przypisanej do pierwszego kliknięcia.

Nagłówek HTTP rejestracji źródła na podstawie kliknięć:

Attribution-Reporting-Register-Source: {
    "destination": "android-app://com.advertiser.example",
    "web_destination": "https://advertiser.com",
    "source_event_id": "234",
    "expiry": "60000",
    "priority": "5",
    // Ad tech opts out of receiving app-web destination distinction
    // in event report, avoids additional noise
    "coarse_event_report_destinations": "true"
}

Aktywator jest zarejestrowany z aplikacji o nazwie pakietu com.advertiser.example:

Attribution-Reporting-Register-Trigger: {
    "event_trigger_data": [{
    "trigger_data": "1",
    "priority": "1"
    }],
}

Aktywator jest zarejestrowany w przeglądarce z poziomu witryny w domenie eTLD+1 https://advertiser.com:

Attribution-Reporting-Register-Trigger: {
    "event_trigger_data": [{
    "trigger_data": "2",
    "priority": "2"
    }],
}

Wygenerowane raporty na poziomie zdarzenia zostaną wygenerowane. Zakładając, że oba aktywatory uzyskały przypisane do źródła, generowane są te raporty na poziomie zdarzenia:

  {
    "attribution_destination": ["android-app://com.advertiser.example,https://advertiser.com"],
    "scheduled_report_time": "800176400",
    "source_event_id": "53234",
    "trigger_data": "1",
    // Can be "event" if source were registered by user viewing the ad
    "source_type": "navigation",
    // Would be 0.0170218 without coarse_event_report_destinations as true in the source
    "randomized_trigger_rate": 0.0024263
  }

Generowanie i dostarczanie raportów

Attribution Reporting API wysyła raporty do punktów końcowych na serwerze, które akceptować raporty na poziomie zdarzenia i raporty zbiorcze.

Wymuszaj uruchamianie zadań raportowania

Po zarejestrowaniu zdarzenia źródła atrybucji lub zarejestrowania zdarzenia aktywującego system planuje uruchomienie zadania raportowania. Domyślnie to zadanie jest uruchamiane co 4 godz. Do celów testowych możesz wymusić uruchomienie lub skrócić zadania raportowania między zadaniami.

Wymuś uruchomienie zadania atrybucji:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 5

Wymuś uruchomienie zadania raportowania na poziomie zdarzenia:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 3

Wymuś uruchomienie agregowanego zadania raportowania:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 7

Sprawdź dane wyjściowe w narzędziu Logcat, aby dowiedzieć się, kiedy zadania zostały uruchomione. Powinien wyglądać Na przykład:

JobScheduler: executeRunCommand(): com.google.android.adservices.api/0 5 s=false f=true

Wymuszaj dostarczanie raportów

Nawet jeśli uruchomienie zadania raportowania będzie wymuszone, system i tak wysyła raporty zgodnie z zaplanowanym czasem dostawy, który wynosi od kilku godzin do kilku dni. Aby przeprowadzić test, możesz przyspieszyć działanie systemu urządzenia musi przypadać po zaplanowanych opóźnieniach, aby rozpocząć dostarczanie raportu.

Sprawdzanie raportów na serwerze

Po wysłaniu raportów potwierdź ich dostarczenie, sprawdzając odpowiednie raporty. dzienników serwera, takich jak pozorowana historia serwera lub niestandardowy system.

Dekodowanie raportu zbiorczego

Podczas odbierania raportu zbiorczego pole debug_cleartext_payload zawiera niezaszyfrowanej wersji raportu zbiorczego. Choć ta wersja nie jest zaszyfrowany, wciąż wymaga dekodowania.

Poniżej znajdziesz przykład dekodowania zawartości pliku debug_cleartext_payload w 2 etapach: w pierwszym używa się dekodowania Base64, a drugiego z użyciem CBOR. lub dekodowanie.

String base64DebugPayload  = "omRkYXRhgqJldmFsdWVEAAAGgGZidWNrZXRQAAAAAAAAAAAAAAAAAAAKhaJldmFsdWVEAACAAGZidWNrZXRQAAAAAAAAAAAAAAAAAAAFWWlvcGVyYXRpb25paGlzdG9ncmFt";
byte[] cborEncoded = Base64.getDecoder().decode(base64DebugPayload);

// CbodDecoder comes from this library https://github.com/c-rack/cbor-java
final List<DataItem> dataItems = new CborDecoder(new ByteArrayInputStream(cborEncoded)).decode();

// In here you can see the contents, but the value will be something like:
// Data items: [{ data: [{ value: co.nstant.in.cbor.model.ByteString@a8b5c07a,
//   bucket: co.nstant.in.cbor.model.ByteString@f812097d },
//   { value: co.nstant.in.cbor.model.ByteString@a8b5dfc0,
//   bucket: co.nstant.in.cbor.model.ByteString@f8120934 }], operation: histogram }]
Log.d("Data items : " + dataItems);

// In order to see the value for bucket and value, you can traverse the data
// and get their values, something like this:
final Map payload = (Map) dataItems.get(0);
final Array payloadArray = (Array) payload.get(new UnicodeString("data"));

payloadArray.getDataItems().forEach(i -> {
    BigInteger value = new BigInteger(((ByteString) ((Map)i).get(new UnicodeString("value"))).getBytes());
    BigInteger bucket = new BigInteger(((ByteString) ((Map)i).get(new UnicodeString("bucket"))).getBytes());
    Log.d("value : " + value + " ;bucket : " + bucket);
});

Testowanie

Aby łatwiej zacząć korzystać z interfejsu Attribution Reporting API, możesz użyć projekt MeasurementSampleApp w GitHubie. Ta przykładowa aplikacja pokazuje, rejestracji źródła atrybucji i rejestracji aktywatora.

W przypadku punktów końcowych serwera rozważ następujące zasoby referencyjne lub własny rozwiązanie:

  • MeasurementAdTechServerSpec obejmuje definicje usług OpenAPI, który można wdrożyć na obsługiwanych platformach próbnych i mikroserwisach.
  • MeasurementAdTechServer zawiera referencyjną implementację przykładowej implementacji. oparty na aplikacji Spring Boot dla Google App Engine.

Wymagania wstępne

wdróż przykładowe interfejsy API w zdalnych punktach końcowych dostępnych z urządzenia testowego lub za pomocą emulatora. Aby ułatwić testowanie, zapoznaj się z dokumentem MeasurementAdTechServerSpec. i przykładowe projekty MeasurementAdTechServer.

Funkcje do przetestowania

  • Źródło atrybucji ćwiczeń i rejestracje zdarzeń konwersji. Sprawdź, czy punkty końcowe po stronie serwera odpowiadają prawidłowym formatem.
  • wykonywać zadania raportowania.
  • Sprawdź dostarczanie raportów w backendzie lub konsoli serwera testowego.

Nadchodzące funkcje

Elastyczna konfiguracja na poziomie zdarzenia

Domyślna konfiguracja raportowania na poziomie zdarzenia jest zalecana w przypadku testy jednostkowe, ale mogą nie być idealne we wszystkich przypadkach użycia. Atrybucja Interfejs API do raportowania będzie obsługiwać opcjonalne, bardziej elastyczne konfiguracje, dzięki którym mają większą kontrolę nad strukturą raportów na poziomie zdarzenia i są w stanie maksymalnie wykorzystać przydatność danych. Ta dodatkowa elastyczność pozwoli przedstawiamy interfejs Attribution Reporting API w 2 fazach:

  • Etap 1. Elastyczna konfiguracja na poziomie zdarzenia Lite. podzbiór fazy 2.
  • Etap 2. Pełna wersja elastycznej konfiguracji na poziomie zdarzenia.

Etap 1. Poziom zdarzenia elastycznego Lite

Dodamy do pliku JSON następujące 2 opcjonalne parametry w Attribution-Reporting-Register-Source:

  • max_event_level_reports
  • event_report_windows
{
  ...
  // Optional. This is a parameter that acts across all trigger types for the
  // lifetime of this source. It restricts the total number of event-level
  // reports that this source can generate. After this maximum is hit, the
  // source is no longer capable of producing any new data. The use of
  // priority in the trigger attribution algorithm in the case of multiple
  // attributable triggers remains unchanged. Defaults to 3 for navigation
  // sources and 1 for event sources
  "max_event_level_reports": <int>,

  // Optional. Represents a series of time windows, starting at 0. Reports
  // for this source will be delivered an hour after the end of each window.
  // Time is encoded as seconds after source registration. If
  // event_report_windows is omitted, will use the default windows. This
  // field is mutually exclusive with the existing `event_report_window` field.
  // // End time is exclusive.
  "event_report_windows": {
    "start_time": <int>,
    "end_times": [<int>, ...]
  }
}

Przykład konfiguracji niestandardowej

Ta przykładowa konfiguracja jest przeznaczona dla dewelopera, który chce zoptymalizować kampanię pod kątem otrzymywanie raportów we wcześniejszych okresach raportowania.

{
  ...
  "max_event_level_reports": 2,
  "event_report_windows": {
    "end_times": [7200, 43200, 86400] // 2 hours, 12 hours, 1 day in seconds
  }
}

Etap 2. W pełni elastyczny poziom zdarzenia

Oprócz parametrów dodanych w pierwszym etapie dodamy też parametr dodatkowy opcjonalny parametr trigger_specs do pliku JSON w Attribution-Reporting-Register-Source

{
  // A trigger spec is a set of matching criteria, along with a scheme to
  // generate bucketized output based on accumulated values across multiple
  // triggers within the specified event_report_window. There will be a limit on
  // the number of specs possible to define for a source.
  "trigger_specs": [{
    // This spec will only apply to registrations that set one of the given
    // trigger data values (non-negative integers) in the list.
    // trigger_data will still appear in the event-level report.
    "trigger_data": [<int>, ...]

    // Represents a series of time windows, starting at the source registration
    // time. Reports for this spec will be delivered an hour after the end of
    // each window. Time is encoded as seconds after source registration.
    // end_times must consist of strictly increasing positive integers.
    //
    // Note: specs with identical trigger_data cannot have overlapping windows;
    // this ensures that triggers match at most one spec. If
    // event_report_windows is omitted, will use the "event_report_window" or
    // "event_report_windows" field specified at the global level for the source
    // (or the default windows if none are specified). End time is exclusive.
    "event_report_windows": {
      "start_time": <int>,
      "end_times": [<int>, ...],
    }

    // Represents an operator that summarizes the triggers within a window
    // count: number of triggers attributed within a window
    // value_sum: sum of the value of triggers within a window
    // The summary is reported as an index into a bucketization scheme. Defaults
    // to "count"
    "summary_window_operator": <one of "count" or "value_sum">,

    // Represents a bucketization of the integers from [0, MAX_INT], encoded as
    // a list of integers where new buckets begin (excluding 0 which is
    // implicitly included).
    // It must consist of strictly increasing positive integers.
    //
    // e.g. [5, 10, 100] encodes the following ranges:
    // [[0, 4], [5, 9], [10, 99], [100, MAX_INT]]
    //
    // At the end of each reporting window, triggers will be summarized into an
    // integer which slots into one of these ranges. Reports will be sent for
    // every new range boundary that is crossed. Reports will never be sent for
    // the range that includes 0, as every source is initialized in this range.
    //
    // If omitted, then represents a trivial mapping
    // [1, 2, ... , MAX_INT]
    // With MAX_INT being the maximum int value defined by the browser.
    "summary_buckets": [<bucket start>, ...]
  }, {
    // Next trigger_spec
  } ...],

  // See description in phase 1.
  "max_event_level_reports": <int>
  // See description in phase 1.
  "event_report_windows": {
    "start_time": <int>,
    "end_times": [<int>, ...]
  }
}

Ta konfiguracja w pełni określa przestrzeń wyjściową raportów na poziomie zdarzenia, za rejestrację źródła. Każda specyfikacja aktywatora w pełni określa:

  • Zestaw kryteriów:
    • konkretnych danych aktywatora, których dotyczy ta specyfikacja; To źródło jest kwalifikowa się do dopasowania tylko do reguł, które zawierają jeden z określonych trigger_data wartości w trigger_specs. Innymi słowy, jeśli reguła pasuje do tego źródła, ale jego trigger_data nie ma wartości 1 wartości w konfiguracji źródła, reguła zostanie zignorowana.
    • Gdy konkretna reguła pasuje do tej specyfikacji (z użyciem event_report_windows). Pamiętaj, że reguła nadal może być dopasowywana ze źródłem dla raportów agregowanych mimo błędu dopasowania wymienionych powyżej.
  • Specjalny algorytm do podsumowywania i grupowania wszystkich aktywatorów w grupie w oknie atrybucji. Dzięki temu aktywatory mogą określać parametr value podsumowywane dla określonej specyfikacji i zgłaszane jako wartość zbiorcza.
.

Reguły będą też obsługiwać dodawanie opcjonalnego parametru wartości w polu słownikach w: event_trigger_data.

{
  "event_trigger_data": [
    {
      "trigger_data": "2",
      "value": 100,  // Defaults to 1
      "filters": ...
    },
    ...
  ]
}

Każda rejestracja aktywatora będzie pasować do maksymalnie 1 specyfikacji aktywatora i aktualizacji powiązanej z nim wartości podsumowania. Ogólnie w momencie aktywowania:

  • Zastosuj globalne filtry atrybucji.
  • W przypadku każdej specyfikacji reguły sprawdź atrybut event_trigger_data w specyfikacji, aby znaleźć zgodnie ze specyfikacją: event_reporting_window. Organizacja najwyższego poziomu event_reporting_windows działa jako wartość domyślna w przypadku, gdy którakolwiek specyfikacja aktywatora jest brakujące pole podrzędne event_report_windows.
  • Do atrybucji jest wybierana pierwsza pasująca specyfikacja, a podsumowana wartość to zwiększył się o value.

Gdy event_report_window dla specyfikacji dobiegnie końca, zmapujemy jej podsumowanie do zasobnika i wysyłać raport na poziomie zdarzenia dla każdego przyrostu wartości w powodowane przez przypisane wartości reguł. W raportach będzie podana jedna dodatkowe pole, trigger_summary_bucket.

{
  ...
  "trigger_summary_bucket": [<bucket start>, <bucket end>],
}

Konfiguracje odpowiadające bieżącej wersji

Poniżej znajdziesz odpowiadające im konfiguracje bieżącego zdarzenia interfejsów API oraz źródeł nawigacji. Szczególnie w przypadku źródeł nawigacji ta definicja wyjaśnia, dlaczego poziomy szumu są tak wysokie w stosunku do źródeł zdarzeń utrzymują te same wartości ypsilon: dane wyjściowe źródeł nawigacji mają znacznie większe wartości kosmosu.

Możliwe, że istnieje wiele równoważnych konfiguracji, że niektóre parametry można ustawić jako domyślne lub skrócić.

Źródła zdarzeń równoważne
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
  "trigger_specs": [
  {
    "trigger_data": [0, 1],
    "event_report_windows": {
      "end_times": [<30 days>]
    },
    "summary_window_operator": "count",
    "summary_buckets": [1],
  }],
  "max_event_level_reports": 1,
  ...
  // expiry must be greater than or equal to the last element of the end_times
  "expiry": <30 days>,
}
Odpowiednie źródła nawigacji
// Note: most of the fields here are not required to be explicitly listed.
// Here we list them explicitly just for clarity.
{
  "trigger_specs": [
  {
    "trigger_data": [0, 1, 2, 3, 4, 5, 6, 7],
    "event_report_windows": {
      "end_times": [<2 days>, <7 days>, <30 days>]
    },
    "summary_window_operator": "count",
    "summary_buckets": [1, 2, 3],
  }],
  "max_event_level_reports": 3,
  ...
  // expiry must be greater than or equal to the last element of the end_times
  "expiry": <30 days>,
}

Przykładowe konfiguracje niestandardowe

Poniżej znajdziesz dodatkowe konfiguracje inne niż domyślne. We wszystkich tych przypadkach kompromisy między deweloperami to między innymi:

  • ograniczenie niektórych wymiarów konfiguracji domyślnej (#triggers, dane wyzwalacza moc zbioru, #windows) w celu zwiększenia kolejnej w celu zachowania poziomu szumu
  • ograniczenie niektórych wymiarów konfiguracji domyślnej (#triggers, dane wyzwalacza moc zbioru, #windows) w celu ograniczenia poziomu szumu

Zasobniki wartości aktywatora raportu

Ta przykładowa konfiguracja jest przeznaczona dla dewelopera, który chce zoptymalizować kampanię pod kątem wartości danych tylko dla jednego okna raportowania (np. 7 dni) i mniejszej liczby raportów i zmniejszyć szum. W tym przykładzie dowolny aktywator, który ustawia wartość trigger_data na wartość inna niż 0 jest nieodpowiednia do atrybucji.

{
  "trigger_specs": [
  {
    "trigger_data": [0],
    "event_report_windows": {
      "end_times": [604800, 1209600] // 7 days, 14 days represented in seconds
    },
    "summary_window_operator": "value_sum",
    "summary_buckets": [5, 10, 100]
  }],
}

Aktywatory mogły być rejestrowane przy użyciu zestawu pól value, które są sumowane, do zasobnika. Na przykład jeśli w ciągu 7 dni od źródła istnieją 3 reguły rejestracje z wartościami 1, 3 i 4.

{ "event_trigger_data": [{"trigger_data": "0", "value": 1}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 3}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 4}] }

Wartości są sumowane do 8 i raportowane w następujących raportach po 7 dniach + 1 godzina:

// Report 1
{
  ...
  "trigger_summary_bucket": [5, 9]
}

W ciągu kolejnych 7 dni rejestrowane są te aktywatory:

{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }

Wartości są sumowane do 8 + 50 + 45 = 103. W ten sposób uzyskujesz następujące raporty przy 14 dni + 1 godzina:

// Report 2
{
  ...
  "trigger_summary_bucket": [10, 99]
},

// Report 3
{
  ...
  "trigger_summary_bucket": [100, MAX_INT]
}
Liczba reguł raportowania

Ten przykład pokazuje, jak deweloper może skonfigurować źródło, aby obliczać wyzwala do 10 elementów.

{
  "trigger_specs": [
  {
    "trigger_data": [0],
    "event_report_windows": {
      "end_times": [604800] // 7 days represented in seconds
    },
    // This field could be omitted to save bandwidth since the default is "count"
    "summary_window_operator": "count",
    "summary_buckets": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  }],
}

Przypisane reguły, w których wartość trigger_data jest ustawiona na 0, są zliczane i ograniczone do 10. Wartość reguły jest ignorowana, ponieważ zasada summary_window_operator jest ustawiona na liczenie. Jeśli Zarejestrowano 4 reguły i zostały przypisane do źródła. Raport będzie wyglądał tak podobny do tego:

// Report 1
{
  ...
  "trigger_summary_bucket": [1, 1]
}
// Report 2
{
  ...
  "trigger_summary_bucket": [2, 2]
}
// Report 3
{
  ...
  "trigger_summary_bucket": [3, 3]
}
// Report 4
{
  ...
  "trigger_summary_bucket": [4, 4]
}
Plik binarny z częstszym raportowaniem

Ta przykładowa konfiguracja jest przeznaczona dla dewelopera, który chce się dowiedzieć, czy pod adresem w ciągu pierwszych 10 dni wystąpiła co najmniej jedna konwersja (niezależnie od wartości), ale chce otrzymywać raporty częściej niż domyślna. Znowu za W tym przykładzie każda reguła, która ustawia trigger_data na wartość inną niż 0, to nie kwalifikuje się do atrybucji. Dlatego ten przypadek użycia jest określany jako binarny.

{
  "trigger_specs": [
  {
    "trigger_data": [0],
    "event_report_windows": {
      // 1 day, 2 days, 3 days, 5 days, 7 days, 10 days represented in seconds
      "end_times": [86400, 172800, 259200, 432000, 604800, 864000]
    },
    // This field could be omitted to save bandwidth since the default is "count"
    "summary_window_operator": "count",
    "summary_buckets": [1]
  }],
}
Różnicuj specyfikacje aktywatora między źródłem a źródłem
{
  "trigger_specs": [
  {
    "trigger_data": [0, 1, 2, 3],
    "event_report_windows": {
      "end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
    }
  }],
  "max_event_level_reports": 3
}
{
  "trigger_specs": [
  {
    "trigger_data": [4, 5, 6, 7],
    "event_report_windows": {
      "end_times": [172800, 604800, 2592000] // 2 days, 7 days, 30 days represented in seconds
    }
  }],
  "max_event_level_reports": 3
}

Zachęcamy deweloperów do sugerowania różnych przypadków użycia, API. Zaktualizujemy to wyjaśnienie o przykładowe konfiguracje dla dla tych przypadków użycia.

Atrybucja międzysieciowa bez przekierowań

Specjaliści ds. technologii reklamowych powinni używać przekierowań, aby rejestrować wiele reguł źródła atrybucji oraz atrybucję międzysieciową. Ta funkcja pomaga użytkownikom z Atrybucja międzysieciowa, w której nie można stosować przekierowań między sieciami. Więcej informacji

Technologie reklamowe mogą wysyłać konfigurację w odpowiedzi dotyczącej rejestracji na podstawie tego, które źródła zarejestrowane przez inne technologie reklamowe są wybierane w celu wygenerowania źródeł; te źródła są następnie używane do atrybucji. Raporty zbiorcze generowane, jeśli reguła zostanie przypisana do źródła pochodnego. Raport zdarzeń generowanie dla źródeł pochodnych nie jest obsługiwane.

Techniki reklamowe mogą wybierać spośród aggregation_keys zarejestrowanych źródeł, które które zamierzają udostępnić partnerom zajmującym się technologiami reklamowymi. Te klucze można zadeklarować w sekcji opcjonalne pole shared_aggregation_keys znajdujące się w ramach rejestracji źródła nagłówek Attribution-Reporting-Register-Source:

"shared_aggregation_keys": ["[key name1]", "[key name2]"]

Źródła pochodne są generowane na podstawie konfiguracji reguły nagłówek rejestracji Attribution-Reporting-Register-Trigger:

  // Specifies the configuration based on which derived sources should be
  // generated. Those derived sources will be included for source matching at the
  // time of attribution. For example, if adtech2 is registering a trigger with an
  // attribution_config with source_network as adtech1, available sources
  // registered by adtech1 will be considered with additional filtering criteria
  // applied to that set as mentioned in the attribution_config. Derived
  // sources can have different values to priority, post_install_exclusivity_window
  // etc.

  "attribution_config": [
    {
      // Derived sources are created from this adtech's registered sources
      "source_network": "[original source's adtech enrollment ID]",
      //(optional) Filter sources whose priority falls in this range
      "source_priority_range": {
        "start": [priority filter lower bound],
        "end": [priority filter upper bound]
      },
      // (optional) Filter sources whose at least one of filter maps matches these
      // filters
      "source_filters": {
        "key name 1": ["key1 value 1"]
      },
      // (optional) Filter sources whose none of filter map matches these
      // filters
        "source_not_filters": {
          "key name 1": ["key1 value 1"]
        },
      // (optional) Apply this priority to the generated derived sources
      "priority": "[64 bit signed integer]",
      // (optional) The derived source will have expiry set as this or parent
      // source's, whichever is earlier
      "expiry": "[64 bit signed integer]",
      // (optional) set on the derived source
      "filter_data": {
        "key name 1": ["key1 value 1"]
      },
      // (optional) set on the derived source
      "post_install_exclusivity_window": "[64-bit unsigned integer]"
    }
  ]

Oto wersja z dodanymi przykładowymi wartościami:

  "attribution_config": [
    {
      "source_network": "adtech1-enrollment-id",
      "source_priority_range": {
        "start": 50,
        "end": 100
      },
      "source_filters": {
        "source_type": ["NAVIGATION"]
      },
      "source_not_filters": {
        "product_id": ["789"]
      },
      "priority": "30",
      "expiry": "78901",
      // (optional) set on the derived source
      "filter_data": {
        "product_id": ["1234"]
        },
      // (optional) set on the derived source
      "post_install_exclusivity_window": "7890"
    }
  ]

Do nagłówka aktywatora rejestracji dodaliśmy 2 nowe pola opcjonalne. Te pola włącz identyfikator zwycięskiej technologii reklamowej w agregowanych kluczach raportów:

  • x_network_bit_mapping: mapowanie identyfikatora rejestracji na identyfikator technologii reklamowej
  • x_network_data: przesunięcie (przesunięcie w lewo) zwycięskiej technologii reklamowej x_network_bit_mapping LUB operacja z kluczem aktywatora
Przykład:
"Attribution-Reporting-Register-Trigger": {
  "attribution_config": [...],
  "aggregatable_trigger_data": [
    {
     "key_piece": "0x400",
     "source_keys": ["campaignCounts"]
      "x_network_data" : {
        "key_offset" : 12 // [64 bit unsigned integer]
      }
    }
    
  ]
  
  "x_network_bit_mapping": {
   // This mapping is used to generate trigger key pieces with AdTech identifier
   // bits. eg. If AdTechA's sources wins the attribution then 0x1 here will be
   // OR'd with the trigger key pieces to generate the final key piece.
    "AdTechA-enrollment_id": "0x1", // Identifier bits in hex for A
    "AdTechB-enrollment_id": "0x2"  // Identifier bits in hex for B
  }
  
}

Oto wynik obliczeń części klucza wyzwalającego podczas generowania raportu dla Źródło AdTechB:

  • key_piece: 0x400 (010000000000)
  • key_offset: 12
  • Wartość parametru enrollment_id AdtechB: 2 (010) (z x_network_bit_mapping)
  • Wynikowy fragment klucza aktywującego: 0x400 | 0x2 << 12 = 0x2400

Ograniczenia

Aby zobaczyć listę pozostających w toku funkcji środowiska wykonawczego SDK, wyświetl informacjami o wersji.

Zgłaszanie błędów i problemów

Twoja opinia jest kluczowym elementem Piaskownicy prywatności na Androida. Daj nam znać wykrytych problemów lub pomysłów na ulepszenie Piaskownicy prywatności. na Androidzie.