Mentre leggi la documentazione di Privacy Sandbox su Android, utilizza il pulsante Developer Preview o Beta per selezionare la versione del programma che stai utilizzando, poiché le istruzioni possono variare.
L'API Attribution Reporting è progettata per migliorare la privacy degli utenti eliminando il ricorso a identificatori di utenti trasversali e per supportare casi d'uso chiave per l'attribuzione e la misurazione delle conversioni nelle app. Questa Guida per gli sviluppatori descrive come configurare e testare le API Attribution Reporting per registrare clic, visualizzazioni e conversioni degli annunci chiamando metodi che registrano i trigger e le origini pertinenti per questi eventi.
Questa guida spiega come configurare gli endpoint del server e creare un'app client che chiama questi servizi. Scopri di più sulla progettazione complessiva dell'API Attribution Reporting nella proposta di progettazione.
Termini chiave
- Le origini attribuzione si riferiscono a clic o visualizzazioni.
- I trigger sono eventi che possono essere attribuiti alle conversioni.
- I report contengono dati su un trigger e sull'origine dell'attribuzione corrispondente. Questi report vengono inviati in risposta agli eventi trigger. L'API Attribution Reporting supporta i report a livello di evento e i report aggregabili.
Prima di iniziare
Per utilizzare l'API Attribution Reporting, completa le attività lato server e lato client elencate nelle sezioni seguenti.
Configurare gli endpoint dell'API Attribution Reporting
L'API Attribution Reporting richiede un insieme di endpoint a cui puoi accedere da un dispositivo di test o un emulatore. Crea un endpoint per ognuna delle seguenti attività lato server:
- Registra un'origine dell'attribuzione (visualizzazione o clic)
- Registra un trigger (conversione)
- Accetta i report a livello di evento
- Accettare i report aggregabili
Esistono diversi metodi per configurare gli endpoint richiesti:
- Il modo più rapido per iniziare è eseguire il deployment delle definizioni di servizio OpenAPI v3 dal nostro repository di codice di esempio a una piattaforma di microservizi o di simulazione. Puoi utilizzare Postman, Prism o qualsiasi altra piattaforma di server di test che accetti questo formato. Esegui il deployment di ogni endpoint e tieni traccia degli URI da utilizzare nella tua app. Per verificare la distribuzione dei report, fai riferimento alle chiamate effettuate in precedenza alla piattaforma serverless o di simulazione.
- Esegui il tuo server autonomo utilizzando l'esempio Kotlin basato su Spring Boot. Esegui il deployment di questo server sul tuo provider cloud o sull'infrastruttura interna.
- Utilizza le definizioni di servizio come esempi per integrare gli endpoint nel tuo sistema esistente.
Accetta la registrazione dell'origine
Questo endpoint deve essere indirizzabile da un URI simile al seguente:
https://adtech.example/attribution_source
Quando un'app client registra una sorgente di attribuzione, fornisce l'URI per questo endpoint del server. L'API Attribution Reporting effettua quindi una richiesta e include una delle seguenti intestazioni:
Per gli eventi di clic:
Attribution-Reporting-Source-Info: navigationPer gli eventi di visualizzazione:
Attribution-Reporting-Source-Info: event
Configura l'endpoint del server in modo che risponda con quanto segue:
// 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>
Ecco un esempio con valori di esempio aggiunti:
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
Se Attribution-Reporting-Redirects contiene URI di partner di tecnologia pubblicitaria, l'API Attribution Reporting effettua una richiesta simile a ogni URI. Ogni partner
di tecnologia pubblicitaria deve configurare un server che risponda con queste intestazioni:
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.
Accettare la registrazione dei trigger di conversione
Questo endpoint deve essere indirizzabile da un URI simile al seguente:
https://adtech.example/attribution_trigger
Quando un'app client registra un evento trigger, fornisce l'URI per questo endpoint del server. L'API Attribution Reporting effettua quindi una richiesta e include una delle seguenti intestazioni:
Configura l'endpoint del server in modo che risponda con quanto segue:
// 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>
Ecco un esempio con valori di esempio aggiunti:
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't 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't 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't 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
Esiste un limite di 25 byte per ID chiave di aggregazione e stringa di filtro. Ciò
significa che gli ID delle chiavi di aggregazione e le stringhe di filtro non devono superare i 25
caratteri. In questo esempio, campaignCounts è composto da 14 caratteri, quindi è un ID chiave di aggregazione valido, mentre 1234 è composto da 4 caratteri, quindi è una stringa di filtro valida.
Se un ID chiave di aggregazione o una stringa di filtro supera i 25 caratteri, il trigger viene
ignorato.
Se Attribution-Reporting-Redirect contiene URI di partner di tecnologia pubblicitaria, l'API Attribution Reporting effettua una richiesta simile a ogni URI. Ogni partner
di tecnologia pubblicitaria deve configurare un server che risponda con queste intestazioni:
// 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 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"],
}]
}],
"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.
Accettare report a livello di evento
Questo endpoint deve essere indirizzabile da un URI. Per saperne di più sulla registrazione degli URI, consulta Registrarsi per un account Privacy Sandbox. L'URI viene dedotto dall'origine dei server utilizzati per accettare la registrazione dell'origine e attivare la registrazione. Utilizzando gli URI di esempio per gli endpoint che accettano la registrazione dell'origine e accettano la registrazione dell'attivatore, l'URI di questo endpoint è:
https://adtech.example/.well-known/attribution-reporting/report-event-attribution
Configura questo server in modo che accetti le richieste JSON che utilizzano il seguente formato:
{
"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]",
}
Le chiavi di debug consentono di ottenere ulteriori informazioni sui report sull'attribuzione; scopri di più sulla loro configurazione.
Accettare report aggregabili
Questo endpoint deve essere indirizzabile da un URI. Per saperne di più sulla registrazione degli URI, consulta Registrarsi per un account Privacy Sandbox. L'URI viene dedotto dall'origine dei server utilizzati per accettare la registrazione dell'origine e attivare la registrazione. Utilizzando gli URI di esempio per gli endpoint che accettano la registrazione dell'origine e accettano la registrazione dell'attivatore, l'URI di questo endpoint è:
https://adtech.example/.well-known/attribution-reporting/report-aggregate-attribution
Vengono compilati sia i campi criptati che quelli non criptati per i report aggregabili. I report criptati ti consentono di iniziare i test con il servizio di aggregazione, mentre il campo non criptato fornisce informazioni sul modo in cui le coppie chiave-valore impostate strutturano i dati.
Configura questo server in modo che accetti le richieste JSON che utilizzano il seguente formato:
{
// 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 doesn't yet encrypt aggregate reports.
// 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]"
}
Le chiavi di debug consentono di ottenere ulteriori informazioni sui report sull'attribuzione; scopri di più sulla loro configurazione.
Configurare il client Android
L'app client registra le origini e gli attivatori dell'attribuzione e consente la generazione di report a livello di evento e aggregabili. Per preparare un dispositivo o un emulatore client Android per l'utilizzo dell'API Attribution Reporting:
- Configura l'ambiente di sviluppo per Privacy Sandbox su Android.
- Installa un'immagine di sistema su un dispositivo supportato o configura un emulatore che includa il supporto di Privacy Sandbox su Android.
Abilita l'accesso all'API Attribution Reporting eseguendo il seguente comando ADB. L'API è disabilitata per impostazione predefinita.
adb shell device_config put adservices ppapi_app_allow_list \"\*\"Se stai testando localmente l'API Attribution Reporting (ad esempio su un dispositivo a cui hai accesso fisico), esegui questo comando per disattivare la registrazione:
adb shell device_config put adservices disable_measurement_enrollment_check "true"Includi l'autorizzazione
ACCESS_ADSERVICES_ATTRIBUTIONnel file manifest Android e crea una configurazione dei servizi pubblicitari per consentire alla tua app di utilizzare le API Attribution Reporting:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />(Facoltativo) Se prevedi di ricevere report di debug, includi l'autorizzazione
ACCESS_ADSERVICES_AD_IDnel file manifest di Android:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />Fai riferimento a una configurazione dei servizi pubblicitari nell'elemento
<application>del manifest:<property android:name="android.adservices.AD_SERVICES_CONFIG" android:resource="@xml/ad_services_config" />Specifica la risorsa XML dei servizi pubblicitari a cui viene fatto riferimento nel manifest, ad esempio
res/xml/ad_services_config.xml. Scopri di più su autorizzazioni dei servizi pubblicitari e controllo dell'accesso agli SDK.<ad-services-config> <attribution allowAllToAccess="true" /> </ad-services-config>
Registra eventi annuncio
La tua app deve registrare le sorgenti e le conversioni man mano che si verificano per verificare
che vengano registrate correttamente. La classe MeasurementManager include metodi
per aiutarti a registrare eventi di origine dell'attribuzione e
trigger di conversione.
Registrare un evento origine attribuzione
Quando un annuncio viene visualizzato o su cui viene fatto clic, un'app publisher chiama registerSource() per registrare un'origine attribuzione come mostrato nello snippet di codice.
L'API Attribution Reporting supporta i seguenti tipi di eventi di origine dell'attribuzione:
- I clic, che in genere registri con un metodo di callback simile a
onClick(). L'evento trigger corrispondente si verifica in genere subito dopo l'evento di clic. Questo tipo di evento fornisce maggiori informazioni sull'interazione dell'utente ed è quindi un buon tipo di sorgente di attribuzione a cui dare una priorità elevata. Visualizzazioni, che in genere vengono registrate all'interno di un metodo di callback simile a
onAdShown(). L'evento trigger corrispondente potrebbe verificarsi ore o giorni dopo l'evento di visualizzazione.
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);
Dopo la registrazione, l'API invia una richiesta POST HTTP all'endpoint del servizio
all'indirizzo specificato da attributionSourceUri. La risposta
dell'endpoint include i valori per destination, source_event_id, expiry e
source_priority.
Se la tecnologia pubblicitaria di origine vuole condividere le registrazioni delle origini, l'URI dell'origine dell'attribuzione originale può includere reindirizzamenti ad altri endpoint di tecnologia pubblicitaria. I limiti e le regole applicabili ai reindirizzamenti sono descritti in dettaglio nella proposta tecnica.
È stato aggiunto il supporto per i reindirizzamenti a catena per registerSource e
registerTrigger. Oltre all'intestazione di registrazione, il consumer API può
ora fornire un reindirizzamento HTTP come risposta del server che include un codice di stato
302 e un'intestazione "Location" con l'URL successivo da visitare per una registrazione
aggiuntiva.
Viene utilizzato solo il campo "destinazione" fornito nella prima visita in tutta la catena. Il numero di visite ha lo stesso limite delle intestazioni "Attribution-Reporting-Redirect". Questo supporto per il reindirizzamento si aggiunge al supporto esistente per "Attribution-Reporting-Redirect" e, se entrambi sono presenti, "Attribution-Reporting-Redirect" ha la precedenza.
Registrare un evento di trigger di conversione
Per registrare un evento di attivazione della conversione, chiama registerTrigger() nella tua app:
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)
Dopo la registrazione, l'API invia una richiesta POST HTTP all'endpoint del servizio
all'indirizzo specificato da attributionTriggerUri. La
risposta dell'endpoint include valori per i report sugli eventi e aggregati.
Se la piattaforma di tecnologia pubblicitaria di origine consente la condivisione delle registrazioni dei trigger, l'URI può includere reindirizzamenti a URI appartenenti ad altre piattaforme di tecnologia pubblicitaria. I limiti e le regole applicabili ai reindirizzamenti sono descritti in dettaglio nella proposta tecnica.
Registrare la misurazione cross-app e cross-web
Nel caso in cui sia un'app che un browser svolgano un ruolo nel percorso dell'utente dalla sorgente all'attivazione, esistono sottili differenze nell'implementazione della registrazione degli eventi pubblicitari. Se un utente vede un annuncio in un'app e viene reindirizzato a un browser per una conversione, la sorgente viene registrata dall'app e la conversione dal browser web. Allo stesso modo, se un utente inizia su un browser web e viene indirizzato a un'app per la conversione, il browser registra la sorgente e l'app registra la conversione.
Poiché l'organizzazione delle tecnologie pubblicitarie sul web e su
Android è diversa, abbiamo aggiunto nuove API per registrare origini e trigger quando si verificano
nei browser. La differenza principale tra queste API e le API corrispondenti basate su app è che ci aspettiamo che il browser segua i reindirizzamenti, applichi eventuali filtri specifici del browser e trasmetta le registrazioni valide alla piattaforma chiamando registerWebSource() o registerWebTrigger().
Il seguente snippet di codice mostra un esempio della chiamata API che il browser effettua per registrare una sorgente di attribuzione prima di indirizzare l'utente a un'app:
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);
Il seguente snippet di codice mostra un esempio della chiamata API che il browser effettua per registrare una conversione dopo che l'utente è stato indirizzato dall'app:
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);
Aggiunta di rumore per la privacy
I report a livello di evento contengono dati su destinazione, ID origine attribuzione e trigger. Vengono inviati nel formato originale (non criptato) all'origine del report. Per proteggere la privacy degli utenti, è possibile aggiungere rumore per rendere più difficile l'identificazione di un singolo utente. I report a livello di evento con rumore vengono generati e inviati in conformità al framework di privacy differenziale. Questi sono i valori predefiniti della percentuale di rumore per diversi scenari:
Tipo di origine |
Valore della destinazione di origine |
Probabilità di report con rumore per registrazione della sorgente |
Visualizza |
App o web |
0,0000025 |
Visualizza |
App e Web |
0,0000042 |
Clic |
App o web |
0,0024263 |
Clic |
App e Web |
0,0170218 |
Nella misurazione dell'attribuzione da app a web, in cui le sorgenti possono generare conversioni sia verso destinazioni app che web, i report a livello di evento possono specificare se il trigger si è verificato nell'app o sul web. Per compensare questo dettaglio aggiuntivo, i report con rumore generati sono fino a circa 7 volte per i clic e circa 1,7 volte per le visualizzazioni.
Alcune tecnologie pubblicitarie non richiedono che i report a livello di evento specifichino se il trigger
si è verificato nella destinazione app o web. Le tecnologie pubblicitarie possono utilizzare il campo coarse_event_report_destinations nell'intestazione Attribution-Reporting-Register-Source per ridurre il rumore. Se una sorgente con
il campo coarse_event_report_destinations specificato vince l'attribuzione, il
report risultante include destinazioni web e app senza distinzione
per quanto riguarda il luogo in cui si è verificato l'attivatore effettivo.
Negli esempi seguenti, un utente fa clic su un annuncio e l'origine viene registrata con l'API. L'utente genera quindi una conversione sia nell'app dell'inserzionista sia sul sito web dell'inserzionista. Entrambe queste conversioni vengono registrate come trigger e attribuite al clic iniziale.
Un'intestazione HTTP di registrazione dell'origine basata sui clic:
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"
}
Un intent viene registrato dall'app con nome del pacchetto
com.advertiser.example:
Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
"trigger_data": "1",
"priority": "1"
}],
}
Un trigger viene registrato da un browser dal sito web con il dominio eTLD+1
https://advertiser.com:
Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
"trigger_data": "2",
"priority": "2"
}],
}
Vengono generati i report a livello di evento risultanti. Supponendo che entrambi i trigger vengano attribuiti all'origine, vengono generati i seguenti report a livello di evento:
{
"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
}
Generare e consegnare report
L'API Attribution Reporting invia i report agli endpoint del tuo server che accettano report a livello di evento e report aggregabili.
Forza l'esecuzione dei job di generazione dei report
Dopo aver registrato un evento di origine dell'attribuzione o un evento trigger, il sistema pianifica l'esecuzione del job di generazione dei report. Per impostazione predefinita, questo job viene eseguito ogni 4 ore. A scopo di test, puoi forzare l'esecuzione dei job di generazione dei report o ridurre gli intervalli tra i job.
Forza l'esecuzione del job di attribuzione:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 5
Forza l'esecuzione del job di report a livello di evento:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 3
Forza l'esecuzione del job di generazione di report aggregabili:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 7
Controlla l'output in logcat per vedere quando sono stati eseguiti i job. Dovrebbe avere un aspetto simile al seguente:
JobScheduler: executeRunCommand(): com.google.android.adservices.api/0 5 s=false f=true
Forzare la consegna dei report
Anche se l'esecuzione del job di generazione dei report è forzata, il sistema invia comunque i report in base ai tempi di consegna pianificati, che variano da un paio di ore a diversi giorni. A scopo di test, puoi impostare l'ora del sistema del dispositivo in modo che sia successiva ai ritardi pianificati per avviare la generazione del report.
Verificare i report sul server
Una volta inviati i report, verifica la consegna controllando i report ricevuti, i log del server applicabili, ad esempio la cronologia del server simulato o il tuo sistema personalizzato.
Decodificare il report aggregato
Quando ricevi un report aggregato, il campo debug_cleartext_payload contiene
una versione non criptata del report aggregato. Sebbene questa versione del report non sia criptata, deve comunque essere decodificata.
Di seguito è riportato un esempio di decodifica dei contenuti del campo debug_cleartext_payload in due passaggi: il primo utilizzando la decodifica Base64 e il secondo utilizzando la decodifica CBOR.
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);
});
Test
Per iniziare a utilizzare l'API Attribution Reporting, puoi utilizzare il progetto MeasurementSampleApp su GitHub. Questa app di esempio mostra la registrazione dell'origine dell'attribuzione e la registrazione dell'attivatore.
Per gli endpoint server, valuta le seguenti risorse di riferimento o la tua soluzione personalizzata:
- MeasurementAdTechServerSpec include definizioni di servizi OpenAPI, che possono essere implementate in piattaforme di microservizi o di simulazione supportate.
- MeasurementAdTechServer include un'implementazione di riferimento di un server mock basato sull'app Spring Boot per Google App Engine.
Prerequisiti
Esegui il deployment di API simulate su endpoint remoti accessibili dal dispositivo di test o dall'emulatore. Per semplificare i test, consulta i progetti di esempio MeasurementAdTechServerSpec e MeasurementAdTechServer.
Funzionalità da testare
- Registrazioni dell'origine dell'attribuzione dell'esercizio e dell'attivazione della conversione. Verifica che gli endpoint lato server rispondano con il formato corretto.
- Esegui job di generazione dei report.
- Verifica la consegna dei report nel backend o nella console del server di test.
Funzionalità in arrivo
Configurazione flessibile a livello di evento
La configurazione predefinita per i report a livello di evento è consigliata per iniziare i test di utilità, ma potrebbe non essere ideale per tutti i casi d'uso. L'API Attribution Reporting supporterà configurazioni facoltative più flessibili, in modo che le tecnologie pubblicitarie abbiano un maggiore controllo sulla struttura dei report a livello di evento e possano massimizzare l'utilità dei dati. Questa maggiore flessibilità verrà introdotta nell'API Attribution Reporting in due fasi:
- Fase 1: configurazione flessibile semplificata a livello di evento; un sottoinsieme della fase 2.
- Fase 2: versione completa della configurazione flessibile a livello di evento.
Fase 1: livello di evento flessibile Lite
Aggiungeremo i seguenti due parametri facoltativi al JSON in
Attribution-Reporting-Register-Source:
max_event_level_reportsevent_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>, ...]
}
}
Esempio di configurazione personalizzata
Questa configurazione di esempio supporta uno sviluppatore che vuole ottimizzare la ricezione dei report nelle finestre di reporting precedenti.
{
...
"max_event_level_reports": 2,
"event_report_windows": {
"end_times": [7200, 43200, 86400] // 2 hours, 12 hours, 1 day in seconds
}
}
Fase 2: livello di evento flessibile completo
Oltre ai parametri aggiunti nella fase 1, aggiungeremo un
parametro facoltativo aggiuntivo trigger_specs al JSON in
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 makes sure 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>, ...]
}
}
Questa configurazione specifica completamente lo spazio di output dei report a livello di evento, per la registrazione della sorgente. Per ogni specifica del trigger, specifichiamo completamente:
- Un insieme di criteri di corrispondenza:
- A quali dati di attivazione specifici si applica questa specifica. Questa origine è
idonea a essere abbinata solo ai trigger che hanno uno dei valori
trigger_dataspecificati intrigger_specs. In altre parole, se il trigger corrisponde a questa origine, ma il suotrigger_datanon è uno dei valori nella configurazione dell'origine, il trigger viene ignorato. - Quando un attivatore specifico corrisponde a questa specifica (utilizzando
event_report_windows). Tieni presente che l'attivatore potrebbe comunque corrispondere a una sorgente per i report aggregabili nonostante non soddisfi i due criteri di corrispondenza menzionati in precedenza.
- A quali dati di attivazione specifici si applica questa specifica. Questa origine è
idonea a essere abbinata solo ai trigger che hanno uno dei valori
- Un algoritmo specifico per riepilogare e raggruppare tutti i trigger all'interno di
una finestra di attribuzione. Ciò consente ai trigger di specificare un parametro
valueche viene sommato per una determinata specifica, ma riportato come valore raggruppato.
I trigger supporteranno anche l'aggiunta di un parametro di valore facoltativo nei
dizionari all'interno di event_trigger_data.
{
"event_trigger_data": [
{
"trigger_data": "2",
"value": 100, // Defaults to 1
"filters": ...
},
...
]
}
Ogni registrazione del trigger corrisponderà al massimo a una specifica del trigger e aggiornerà il valore di riepilogo associato. A livello generale, al momento dell'attivazione:
- Applica filtri di attribuzione globali.
- Per ogni specifica del trigger, valuta
event_trigger_datanella specifica per trovare una corrispondenza utilizzandoevent_reporting_windowdella specifica.event_reporting_windowsdi primo livello funge da valore predefinito nel caso in cui una specifica di trigger sia il sottocampoevent_report_windowsmancante. - La prima specifica corrispondente viene scelta per l'attribuzione e il valore di riepilogo viene
incrementato di
value.
Quando viene completato il event_report_window per una specifica, il relativo valore di riepilogo viene mappato a un bucket e viene inviato un report a livello di evento per ogni incremento nel bucket di riepilogo causato dai valori di attivazione attribuiti. I report includeranno un
campo aggiuntivo, trigger_summary_bucket.
{
...
"trigger_summary_bucket": [<bucket start>, <bucket end>],
}
Configurazioni equivalenti alla versione attuale
Di seguito sono riportate le configurazioni equivalenti per le origini di navigazione e degli eventi correnti delle API, rispettivamente. Soprattutto per le origini di navigazione, questo illustra perché i livelli di rumore sono così elevati rispetto alle origini eventi per mantenere gli stessi valori epsilon: le origini di navigazione hanno uno spazio di output molto più ampio.
È possibile che esistano più configurazioni equivalenti, dato che alcuni parametri possono essere impostati come predefiniti o eliminati.
Origini eventi equivalenti
// 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>,
}
Fonti di navigazione equivalenti
// 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>,
}
Esempi di configurazioni personalizzate
Di seguito sono riportate alcune configurazioni aggiuntive al di fuori di quelle predefinite. In tutti questi esempi, i compromessi per gli sviluppatori includono:
- riducendo una dimensione della configurazione predefinita (numero di trigger, cardinalità dei dati dei trigger, numero di finestre) per aumentare un'altra dimensione e preservare il livello di rumore
- riducendo alcune dimensioni della configurazione predefinita (numero di trigger, cardinalità dei dati dei trigger, numero di finestre) per ridurre il livello di rumore
Bucket di valori del trigger del report
Questa configurazione di esempio supporta uno sviluppatore che vuole ottimizzare i dati sul valore per una sola finestra di reporting (ad es. 7 giorni), scambiando un numero inferiore di finestre di reporting con meno rumore. In questo esempio, qualsiasi trigger che imposta trigger_data su
un valore diverso da 0 non è idoneo per l'attribuzione.
{
"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]
}],
}
I trigger possono essere registrati con il set di campi value, che vengono sommati e
raggruppati. Ad esempio, se ci sono tre trigger entro 7 giorni dalle registrazioni
della sorgente con valori 1, 3 e 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}] }
I valori vengono sommati a 8 e riportati nei seguenti report dopo 7 giorni + 1 ora:
// Report 1
{
...
"trigger_summary_bucket": [5, 9]
}
Nei 7 giorni successivi, vengono registrati i seguenti trigger:
{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }
I valori vengono sommati a 8 + 50 + 45 = 103. In questo modo, vengono generati i seguenti report a 14 giorni + 1 ora:
// Report 2
{
...
"trigger_summary_bucket": [10, 99]
},
// Report 3
{
...
"trigger_summary_bucket": [100, MAX_INT]
}
Conteggi degli attivatori dei report
Questo esempio mostra come uno sviluppatore può configurare un'origine per ottenere un conteggio dei trigger fino a 10.
{
"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]
}],
}
Gli attivatori attribuiti con trigger_data impostato su 0 vengono conteggiati e limitati a 10.
Il valore del trigger viene ignorato perché summary_window_operator è impostato su conteggio. Se
vengono registrati e attribuiti all'origine 4 trigger, il report avrà
il seguente aspetto:
// 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]
}
Binario con report più frequenti
Questa configurazione di esempio supporta uno sviluppatore che vuole sapere se si è verificata almeno una conversione nei primi 10 giorni (indipendentemente dal valore), ma vuole ricevere report a intervalli più frequenti rispetto a quelli predefiniti. Anche in
questo esempio, qualsiasi trigger che imposta trigger_data su un valore diverso da 0 non è
idoneo all'attribuzione. Per questo motivo, questo caso d'uso è definito
binario.
{
"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]
}],
}
Variare le specifiche del trigger da un'origine all'altra
{
"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
}
Invitiamo gli sviluppatori a suggerire diversi casi d'uso che potrebbero avere per questa estensione API e aggiorneremo questa spiegazione con configurazioni di esempio per questi casi d'uso.
Attribuzione su più reti senza reindirizzamenti
Le tecnologie pubblicitarie devono utilizzare i reindirizzamenti per registrare più trigger di origine dell'attribuzione e per eseguire l'attribuzione cross-network. Questa funzionalità supporta l'attribuzione cross-network in cui i reindirizzamenti non sono fattibili tra le reti. Ulteriori informazioni.
Le tecnologie pubblicitarie possono inviare la configurazione nella risposta di registrazione del trigger in base alle origini registrate da altre tecnologie pubblicitarie selezionate per generare origini derivate; queste origini derivate vengono poi utilizzate per l'attribuzione. I report aggregati vengono generati se il trigger viene attribuito a un'origine derivata. La generazione di report sugli eventi per le origini derivate non è supportata.
Le tecnologie pubblicitarie possono scegliere tra le aggregation_keys nelle loro origini registrate che
intendono condividere con le tecnologie pubblicitarie partner. Queste chiavi possono essere dichiarate nel
campo facoltativo shared_aggregation_keys, che si trova sotto l'intestazione
di registrazione dell'origine Attribution-Reporting-Register-Source:
"shared_aggregation_keys": ["[key name1]", "[key name2]"]
Le origini derivate vengono generate in base alla configurazione nell'intestazione di registrazione del trigger 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]"
}
]
Ecco una versione con valori di esempio aggiunti:
"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"
}
]
Vengono aggiunti due nuovi campi facoltativi all'intestazione della registrazione del trigger. Questi campi consentono l'identificatore della tecnologia pubblicitaria vincente nelle chiavi dei report aggregabili:
x_network_bit_mapping: Mappatura dei bit dell'identificatore della tecnologia pubblicitaria all'ID registrazionex_network_data: offset (spostamento a sinistra) per l'operazionex_network_bit_mappingOR della tecnologia pubblicitaria vincente con il componente chiave del trigger
Esempio:
"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 ad tech identifier
// bits. eg. If Ad Tech-A's sources wins the attribution then 0x1 here will be
// OR'd with the trigger key pieces to generate the final key piece.
"Ad-Tech-A-enrollment_id": "0x1", // Identifier bits in hex for A
"Ad-Tech-B-enrollment_id": "0x2" // Identifier bits in hex for B
}
…
}
Ecco il calcolo del pezzo di chiave del trigger risultante quando viene generato un report per l'origine di AdTechB:
key_piece:0x400 (010000000000)key_offset:12- Valore
enrollment_iddi AdtechB:2 (010)(dal giornox_network_bit_mapping) - Componente della chiave di attivazione risultante:
0x400 | 0x2 << 12 = 0x2400
Limitazioni
Per un elenco delle funzionalità in corso di implementazione per l'SDK Runtime, consulta le note di rilascio.
Segnalare bug e problemi
Il tuo feedback è una parte fondamentale di Privacy Sandbox su Android. Comunicaci eventuali problemi che riscontri o idee per migliorare Privacy Sandbox su Android.