Mentre leggi la documentazione di Privacy Sandbox su Android, utilizza il pulsante Anteprima per sviluppatori o Beta per selezionare la versione del programma con cui stai lavorando, poiché le istruzioni possono variare.
L'API Attribution Reporting è progettata per migliorare la privacy degli utenti eliminando il ricorso a identificatori di utenti trasversali, nonché 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 gli attivatori e le origini pertinenti per questi eventi.
Questa guida spiega come configurare gli endpoint del server e creare un'app client che chiami questi servizi. Scopri di più sul design complessivo dell'API Attribution Reporting nella proposta di design.
Termini chiave
- Le origini attribuzione si riferiscono a clic o visualizzazioni.
- Gli attivatori sono eventi che possono essere attribuiti alle conversioni.
- I report contengono dati su un attivatore e sull'origine di attribuzione corrispondente. Questi report vengono inviati in risposta agli eventi di attivazione. 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 da un emulatore. Crea un endpoint per ciascuna delle seguenti attività lato server:
- Registra un'origine di attribuzione (visualizzazione o clic)
- Registra un attivatore (conversione)
- Accetta i report a livello di evento
- Accettare report aggregabili
Esistono diversi metodi per configurare gli endpoint richiesti:
- Il modo più rapido per iniziare a utilizzare la piattaforma è eseguire il deployment delle definizioni di servizio OpenAPI v3 dal nostro repository di codice di esempio a una piattaforma di microservizi o simulata. Puoi utilizzare Postman, Prism o qualsiasi altra piattaforma per server simulati che accetti questo formato. Esegui il deployment di ogni endpoint e tieni traccia degli URI da utilizzare nella tua app. Per verificare l'invio dei report, fai riferimento alle chiamate eseguite in precedenza alla piattaforma simulata o serverless.
- Esegui il tuo server autonomo utilizzando l'esempio Kotlin basato su Spring Boot. Esegui il deployment di questo server sul tuo provider cloud o sulla tua infrastruttura interna.
- Utilizza le definizioni dei servizi come esempi per integrare gli endpoint nel 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 un'origine 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: navigation
Per 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 gli URI dei partner di tecnologia pubblicitaria, l'API Attribution Reporting effettua una richiesta simile a ogni URI. Ogni partner di ad tech deve configurare un server che risponda con le seguenti 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 dell'attivatore delle conversioni
Questo endpoint deve essere indirizzabile da un URI simile al seguente:
https://adtech.example/attribution_trigger
Quando un'app client registra un evento di attivazione, fornisce l'URI per questo endpoint del server. L'API Attribution Reporting invia 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 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
Esiste un limite di 25 byte per ID chiave di aggregazione e stringa filtro. Ciò significa che gli ID chiave di aggregazione e le stringhe di filtro non devono superare i 25 caratteri. In questo esempio, campaignCounts
è costituito da 14 caratteri, quindi è un ID chiave di aggregazione valido, mentre 1234
è costituito da 4 caratteri, quindi è una stringa di filtro valida.
Se la stringa del filtro o l'ID chiave di aggregazione supera i 25 caratteri, l'attivatore viene ignorato.
Se Attribution-Reporting-Redirect
contiene gli URI dei partner di tecnologia pubblicitaria, l'API Attribution Reporting effettua una richiesta simile a ogni URI. Ogni partner di ad tech deve configurare un server che risponda con le seguenti 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 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.
Accettare i report a livello di evento
Questo endpoint deve essere indirizzabile da un URI. Per ulteriori informazioni sull'iscrizione 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 della fonte 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 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 i report aggregabili
Questo endpoint deve essere indirizzabile da un URI. Per ulteriori informazioni sull'iscrizione 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 della fonte e accettano la registrazione dell'attivatore, l'URI di questo endpoint è:
https://adtech.example/.well-known/attribution-reporting/report-aggregate-attribution
I campi criptati e non criptati vengono compilati per i report aggregabili. I report criptati ti consentono di iniziare a eseguire 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 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 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]"
}
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 gli attivatori e le origini di attribuzione e consente la generazione di report aggregati e a livello di evento. 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 l'API Attribution Reporting a livello locale (ad esempio su un dispositivo a cui hai accesso fisicamente), esegui questo comando per disattivare la registrazione:
adb shell device_config put adservices disable_measurement_enrollment_check "true"
Includi l'autorizzazione
ACCESS_ADSERVICES_ATTRIBUTION
nel file Android Manifest e crea una configurazione di 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_ID
nel file Android Manifest:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />
Fai riferimento a una configurazione dei servizi pubblicitari nell'elemento
<application>
del tuo 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ù sulle autorizzazioni dei servizi pubblicitari e sul controllo dell'accesso dell'SDK.<ad-services-config> <attribution allowAllToAccess="true" /> </ad-services-config>
Registra gli eventi correlati agli annunci
L'app deve registrare le origini e le conversioni man mano che si verificano per assicurarsi che vengano registrate correttamente. La classe MeasurementManager
include metodi per aiutarti a registrare gli eventi delle sorgenti di attribuzione e gli attivatori delle conversioni.
Registra un evento di origine attribuzione
Quando un annuncio viene visualizzato o viene fatto clic su di esso, un'app del 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:
- Clic, che in genere registri in un metodo di callback simile a
onClick()
. L'evento trigger corrispondente si verifica in genere poco dopo l'evento click. Questo tipo di evento fornisce maggiori informazioni sull'interazione degli utenti ed è quindi un buon tipo di origine di attribuzione a cui assegnare una priorità elevata. Visualizzazioni, che in genere registri in un metodo di callback simile a
onAdShown()
. L'evento di attivazione 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 di attribuzione originale può includere reindirizzamenti ad altri endpoint di tecnologia pubblicitaria. I limiti e le regole applicabili ai reindirizzamenti sono descritti nel documento tecnico.
È stato aggiunto il supporto per i reindirizzamenti a catena per registerSource
e
registerTrigger
. Oltre all'intestazione di registrazione, il consumatore dell'API ora può 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 un'ulteriore registrazione.
Nell'intera catena viene utilizzato solo il campo "destinazione" fornito nella prima visita. Il numero di visite ha lo stesso limite delle intestazioni "Attribution-Reporting-Redirect". Questo supporto per i reindirizzamenti si aggiunge al supporto esistente di "Attribution-Reporting-Redirect" e, se sono presenti entrambi, "Attribution-Reporting-Redirect" ha la precedenza.
Registra un evento di attivazione della 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 i valori per i report aggregati e sugli eventi.
Se la piattaforma ad tech di origine consente la condivisione delle registrazioni degli attivatori, l'URI può includere reindirizzamenti a URI appartenenti ad altre piattaforme ad tech. I limiti e le regole applicabili ai reindirizzamenti sono descritti nella proposta tecnica.
Registra la misurazione tra app e web
Se sia un'app sia un browser svolgono un ruolo nel percorso dell'utente dall'origine all'attivatore, esistono sottili differenze nell'implementazione della registrazione degli eventi correlati agli annunci. Se un utente visualizza 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. Analogamente, se un utente inizia su un browser web e viene indirizzato a un'app per la conversione, il browser registra l'origine e l'app registra la conversione.
Poiché esistono differenze nel modo in cui le tecnologie pubblicitarie sono organizzate sul web e su Android, abbiamo aggiunto nuove API per registrare le origini e gli attivatori quando si verificano sui browser. La differenza principale tra queste API e le API basate su app corrispondenti è 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 all'API effettuata dal browser per registrare un'origine 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 all'API effettuata dal browser per registrare una conversione dopo che l'utente è stato reindirizzato 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 attivatori. Vengono inviati nel formato originale (non criptato) all'origine del report. Per proteggere la privacy dell'utente, è possibile aggiungere del rumore per rendere più difficile identificare un singolo utente. I report a livello di evento con rumore vengono generati e inviati in conformità con il framework di privacy differenziale. Questi sono i valori predefiniti della percentuale di rumore per diversi scenari:
Tipo di origine |
Valore della destinazione dell'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 indirizzare le conversioni sia alle destinazioni web sia a quelle app, i report a livello di evento possono specificare se l'attivatore si è verificato nell'app o sul web. Per compensare questo livello di dettaglio aggiuntivo, i report con rumore generati possono essere fino a circa 7 volte superiori per i clic e circa 1,7 volte superiori per le visualizzazioni.
Alcune tecnologie pubblicitarie non richiedono report a livello di evento per specificare se l'attivatore si è verificato nella destinazione web o nell'app. I professionisti del marketing digitale possono utilizzare il campo coarse_event_report_destinations
sotto l'intestazione Attribution-Reporting-Register-Source
per ridurre il rumore. Se un'origine con il campo coarse_event_report_destinations
specificato ottiene l'attribuzione, il report risultante include le destinazioni web e dell'app senza distinzioni in base a dove si è verificato l'attivatore effettivo.
Nei seguenti esempi, un utente fa clic su un annuncio e l'origine è registrata con l'API. L'utente effettua quindi una conversione sia nell'app sia sul sito web dell'inserzionista. Entrambe queste conversioni vengono registrate come attivatori 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"
}
Viene registrato un trigger dall'app con il nome del pacchettocom.advertiser.example
:
Attribution-Reporting-Register-Trigger: {
"event_trigger_data": [{
"trigger_data": "1",
"priority": "1"
}],
}
Un attivatore viene registrato da un browser del sito web con il dominio eTLD+1https://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 gli attivatori 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 pubblicare report
L'API Attribution Reporting invia report agli endpoint sul tuo server che accettano report a livello di evento e report aggregabili.
Forzare l'esecuzione dei job di generazione di report
Dopo aver registrato un evento di origine dell'attribuzione o un evento di attivazione, il sistema pianifica l'esecuzione del job di generazione di report. Per impostazione predefinita, questo job viene eseguito ogni 4 ore. Ai fini del test, puoi forzare l'esecuzione dei job di generazione di report o accorciare gli intervalli tra i job.
Forzare l'esecuzione del job di attribuzione:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 5
Forzare l'esecuzione del job di generazione di report a livello di evento:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 3
Forzare 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 l'invio dei report
Anche se il job di generazione di report viene eseguito forzatamente, il sistema invia comunque i report in base ai relativi tempi di invio pianificati, che vanno da un paio di ore a diversi giorni. Per scopi di test, puoi anticipare l'ora di sistema del dispositivo in modo che sia successiva ai ritardi pianificati per avviare l'invio dei report.
Verifica 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 utilizza la decodifica Base 64 e il secondo 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 dell'attivatore.
Per gli endpoint del server, prendi in considerazione le seguenti risorse di riferimento o la tua soluzione personalizzata:
- MeasurementAdTechServerSpec include definizioni di servizi OpenAPI, che possono essere implementate su piattaforme di microservizi o simulati supportate.
- MeasurementAdTechServer include un'implementazione di riferimento di un server simulato 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
- Esegui le registrazioni dell'origine attribuzione e dell'attivatore di conversione. Verifica che gli endpoint lato server rispondano con il formato corretto.
- Esegui job di generazione di report.
- Verifica l'invio 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 e 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 a livello di evento Lite; 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_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>, ...]
}
}
Esempio di configurazione personalizzata
Questa configurazione di esempio supporta uno sviluppatore che vuole ottimizzare la ricezione dei report in finestre di generazione dei report 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 completamente flessibile
Oltre ai parametri aggiunti nella Fase 1, aggiungeremo un altro parametro facoltativo 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 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>, ...]
}
}
Questa configurazione specifica completamente lo spazio di output dei report a livello di evento per la registrazione delle origini. Per ogni specifica dell'attivatore, specifichiamo completamente:
- Un insieme di criteri di corrispondenza:
- I dati di attivazione specifici a cui si applica questa specifica. Questa origine è idonea per essere associata solo agli attivatori che hanno uno dei valori
trigger_data
specificati intrigger_specs
. In altre parole, se l'attivatore corrisponde a questa origine, ma il relativotrigger_data
non è uno dei valori nella configurazione dell'origine, l'attivatore viene ignorato. - Quando un attivatore specifico corrisponde a questa specifica (utilizzando
event_report_windows
). Tieni presente che l'attivatore potrebbe comunque essere associato a una sorgente per i report aggregabili nonostante non soddisfi i due criteri di corrispondenza menzionati in precedenza.
- I dati di attivazione specifici a cui si applica questa specifica. Questa origine è idonea per essere associata solo agli attivatori che hanno uno dei valori
- Un algoritmo specifico per riepilogare e raggruppare tutti gli attivatori all'interno di una finestra di attribuzione. In questo modo, gli attivatori possono specificare un parametro
value
che viene sommato per una determinata specifica, ma viene riportato come valore raggruppato.
Gli attivatori supporteranno anche l'aggiunta di un parametro valore facoltativo nei
dizionari all'interno di event_trigger_data
.
{
"event_trigger_data": [
{
"trigger_data": "2",
"value": 100, // Defaults to 1
"filters": ...
},
...
]
}
Ogni registrazione dell'attivatore corrisponderà a un massimo di una specifica dell'attivatore e aggiornerà il valore di riepilogo associato. In linea generale, al momento dell'attivazione:
- Applica i filtri di attribuzione globale.
- Per ogni specifica dell'attivatore, valuta il
event_trigger_data
nella specifica per trovare una corrispondenza utilizzando ilevent_reporting_window
della specifica. Il valoreevent_reporting_windows
di primo livello funge da valore predefinito nel caso in cui una specifica dell'attivatore sia il sottocampoevent_report_windows
mancante. - La prima specifica trovata viene scelta per l'attribuzione e il valore di riepilogo viene incrementato di
value
.
Al termine dell'event_report_window
per una specifica, ne mapperemo il valore di riepilogo a un bucket e invieremo un report a livello di evento per ogni incremento nel bucket di riepilogo causato dai valori di trigger attribuiti. I report includeranno un campo aggiuntivo, trigger_summary_bucket
.
{
...
"trigger_summary_bucket": [<bucket start>, <bucket end>],
}
Configurazioni equivalenti alla versione corrente
Di seguito sono riportate le configurazioni equivalenti per le origini di navigazione e per gli eventi correnti delle API. Soprattutto per le origini di navigazione, questo illustra perché i livelli di rumore sono così elevati rispetto alle origini evento per mantenere gli stessi valori di 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 potati.
Origini evento 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>,
}
Origini 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>,
}
Configurazioni personalizzate di esempio
Di seguito sono riportate alcune configurazioni aggiuntive rispetto ai valori predefiniti. In tutti questi esempi, i compromessi per gli sviluppatori includono:
- ridurre alcune dimensioni della configurazione predefinita ("#triggers", cardinalità dei dati dell'attivatore, "#windows") per aumentarne un'altra per preservare il livello di rumore
- ridurre alcune dimensioni della configurazione predefinita ("#triggers", cardinalità dei dati dell'attivatore, "#windows") per ridurre il livello di rumore
Bucket di valori di trigger dei report
Questa configurazione di esempio supporta uno sviluppatore che vuole ottimizzare in base ai dati sul valore per una sola finestra di generazione di report (ad es. 7 giorni), scambiando un numero inferiore di finestre di generazione di report con meno rumore. In questo esempio, qualsiasi attivatore 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]
}],
}
Gli attivatori possono essere registrati con l'insieme di campi value
, che vengono sommati e raggruppati. Ad esempio, se ci sono tre attivatori entro 7 giorni dalle registrazioni della fonte 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 attivatori:
{ "event_trigger_data": [{"trigger_data": "0", "value": 50}] }
{ "event_trigger_data": [{"trigger_data": "0", "value": 45}] }
La somma dei valori è 8 + 50 + 45 = 103. Ciò genera i seguenti report dopo 14 giorni e 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 di attivatori 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 hanno un limite di 10.
Il valore dell'attivatore viene ignorato poiché summary_window_operator
è impostato su conteggio. Se
vengono registrati e attribuiti all'origine quattro attivatori, 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]
}
File binario con report più frequenti
Questa configurazione di esempio supporta uno sviluppatore che vuole sapere se almeno una conversione si è verificata nei primi 10 giorni (indipendentemente dal valore), ma vuole ricevere i report a intervalli più frequenti rispetto a quelli predefiniti. Anche in questo
esempio, qualsiasi attivatore che imposta trigger_data
su un valore diverso da 0 è
non idoneo per l'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 degli trigger da una sorgente 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 dell'API e aggiorneremo questa spiegazione con configurazioni di esempio per questi casi d'uso.
Attribuzione su più reti senza reindirizzamenti
Gli esperti di ad tech devono utilizzare i reindirizzamenti per registrare più attivatori delle origini di attribuzione e per eseguire l'attribuzione su più reti. Questa funzionalità consente di supportare l'attribuzione tra reti quando i reindirizzamenti non sono possibili tra le reti. Ulteriori informazioni.
Le tecnologie pubblicitarie possono inviare la configurazione nella risposta alla registrazione dell'attivatore in base alle origini registrate da altre tecnologie pubblicitarie selezionate per generare origini derivate, che vengono poi utilizzate per l'attribuzione. I report aggregati vengono generati se l'attivatore viene attribuito a un'origine derivata. La generazione di report sugli eventi per le origini derivate non è supportata.
Le tecnologie pubblicitarie possono scegliere tra i aggregation_keys
nelle loro origini registrate quelle che intendono condividere con le tecnologie pubblicitarie partner. Queste chiavi possono essere dichiarate nel
campo facoltativo shared_aggregation_keys
, situato sotto l'intestazione
Attribution-Reporting-Register-Source
di registrazione dell'origine:
"shared_aggregation_keys": ["[key name1]", "[key name2]"]
Le origini derivate vengono generate in base alla configurazione nell'intestazione di registrazione dell'attivatore 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"
}
]
Sono stati aggiunti due nuovi campi facoltativi per attivare l'intestazione di registrazione. Questi campi attivano l'identificatore della tecnologia pubblicitaria vincente nelle chiavi dei report aggregabili:
x_network_bit_mapping
: mappatura dei bit dell'ID registrazione all'identificatore ad techx_network_data
: offset (spostamento a sinistra) per l'operazione ORx_network_bit_mapping
della tecnologia pubblicitaria vincente con il componente chiave dell'attivatore
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 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
}
…
}
Di seguito è riportato il calcolo del componente della chiave di attivazione risultante quando viene generato un report per la sorgente di AdTechB:
key_piece
:0x400 (010000000000)
key_offset
:12
- Valore
enrollment_id
di AdtechB:2 (010)
(dax_network_bit_mapping
) - Componente della chiave di attivazione risultante:
0x400 | 0x2 << 12 = 0x2400
Limitazioni
Per un elenco delle funzionalità in corso di implementazione per il runtime dell'SDK, consulta le note di rilascio.
Segnalare bug e problemi
Il tuo feedback è una parte fondamentale di Privacy Sandbox su Android. Comunicaci eventuali problemi riscontrati o idee per migliorare Privacy Sandbox su Android.