Guida per gli sviluppatori dell'API Attribution Reporting

Mentre leggi Privacy Sandbox su Android documentazione, utilizza il pulsante Anteprima per sviluppatori o Beta per selezionare la versione del programma in uso, le istruzioni possono variare.


Inviare un feedback

L'API Attribution Reporting è progettata per migliorare la privacy degli utenti rimuovendo il ricorso a identificatori utente trasversali e 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 sugli annunci, visualizzazioni e conversioni richiamando metodi che registrano i trigger e origini di questi eventi.

Questa guida insegna come configurare gli endpoint server e creare un'app client che chiama questi servizi. Scopri di più sul design complessivo dell'attribuzione l'API di reporting nella proposta di progettazione.

Termini chiave

  • Le sorgenti di 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 l'attribuzione corrispondente sorgente. Questi report vengono inviati in risposta agli eventi di attivazione. La L'API Attribution Reporting supporta i report a livello di evento e report aggregabili.

Prima di iniziare

Per utilizzare l'API Attribution Reporting, completa le operazioni lato server e lato client elencate nelle sezioni seguenti.

Configura gli endpoint dell'API Attribution Reporting

L'API Attribution Reporting richiede un set di endpoint a cui puoi accedere da un emulatore o un dispositivo di test. Crea un endpoint per ciascuno dei seguenti attività lato server:

Esistono diversi metodi per configurare gli endpoint richiesti:

  • Il modo più rapido per iniziare a lavorare è eseguire il deployment Definizioni del servizio OpenAPI v3 dal nostro codice campione di un repository in una piattaforma simulata o di microservizi. Puoi utilizzare Postman, Prisma o qualsiasi altro server fittizio che accetta questo formato. esegui il deployment di ogni endpoint e tieni traccia gli URI da utilizzare nell'app. Per verificare l'invio dei report, consulta le chiamate in precedenza sulla piattaforma simulata o serverless.
  • Esegui il tuo server autonomo utilizzando il modello basato su Spring Boot Esempio di Kotlin. Esegui il deployment di questo server sul tuo cloud provider o interno dell'infrastruttura.
  • Utilizza le definizioni del servizio come esempi per integrare gli endpoint nel tuo di un sistema esistente.
di Gemini Advanced.

Accetta registrazione 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 a questo endpoint server. L'API Attribution Reporting, quindi, effettua una richiesta include una delle seguenti intestazioni:

  • Per gli eventi di clic:

    Attribution-Reporting-Source-Info: navigation
    
  • Per visualizzare gli eventi:

    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 dei partner di tecnologia pubblicitaria, il valore L'API Attribution Reporting invia quindi una richiesta simile a ciascun URI. Ogni tecnologia pubblicitaria Il partner 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.

Accetta la registrazione dell'attivatore 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 di trigger, fornisce l'URI per questo endpoint 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 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 di filtro. Questo gli ID chiave di aggregazione e le stringhe dei filtri non devono superare i 25 caratteri. In questo esempio, campaignCounts è composto da 14 caratteri, quindi è un valore valido ID chiave di aggregazione, mentre 1234 è di 4 caratteri, quindi è una stringa di filtro valida. Se l'ID della chiave di aggregazione o la stringa di filtro supera i 25 caratteri, l'attivatore viene ignorato.

Se Attribution-Reporting-Redirect contiene URI dei partner di tecnologia pubblicitaria, il valore L'API Attribution Reporting invia quindi una richiesta simile a ciascun URI. Ogni tecnologia pubblicitaria Il partner 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 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. Leggi l'articolo sull'iscrizione per una violazione delle norme sulla privacy Sandbox account per ulteriori informazioni sulla registrazione degli URI. (L'URI è dedotti dall'origine dei server utilizzati per accettare la registrazione di origine e attivare la registrazione.) Utilizzo degli URI di esempio per gli endpoint che accettano l'origine registrazione e accetta la registrazione del trigger, 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 acquisire ulteriori informazioni sui report sull'attribuzione. scopri di più sulla loro configurazione.

Report aggregabili accettati

Questo endpoint deve essere indirizzabile da un URI. Leggi l'articolo sull'iscrizione per una violazione delle norme sulla privacy Sandbox account per ulteriori informazioni sulla registrazione degli URI. (L'URI è dedotti dall'origine dei server utilizzati per accettare la registrazione di origine e attivare la registrazione.) Utilizzo degli URI di esempio per gli endpoint che accettano l'origine registrazione e accetta la registrazione del trigger, l'URI di questo endpoint è:

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

Entrambi i campi criptati e non criptati sono aggregabili report. I report criptati consentono di iniziare i test con l'aggregazione mentre il campo non criptato fornisce informazioni sul modo in cui viene impostata la coppia chiave-valore che stanno strutturando 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 acquisire ulteriori informazioni sui report sull'attribuzione. scopri di più sulla loro configurazione.

Configura il client Android

L'app del cliente registra le origini e gli attivatori di attribuzione e attiva la generazione di report aggregabili a livello di evento. Per preparare un client Android un emulatore o un dispositivo per utilizzare l'API Attribution Reporting, procedi nel seguente modo:

  1. Configura il tuo ambiente di sviluppo per Privacy Sandbox su Android.
  2. Installa un'immagine di sistema su un dispositivo supportato oppure configurare un emulatore che supporti Privacy Sandbox su Android.
  3. Attiva l'accesso all'API Attribution Reporting eseguendo la classe successivo al comando ADB. L'API è disabilitata per impostazione predefinita.

    adb shell device_config put adservices ppapi_app_allow_list \"\*\"
    
  4. Se stai testando a livello locale l'API Attribution Reporting (ad es. test su un dispositivo a cui hai accesso fisico), esegui questo comando per disabilitare registrazione:

    adb shell device_config put adservices disable_measurement_enrollment_check "true"
    
  5. Includi l'autorizzazione ACCESS_ADSERVICES_ATTRIBUTION nel tuo Android File manifest e crea una configurazione di servizi pubblicitari per l'app utilizza le API Attribution Reporting:

    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
    
  6. (Facoltativo) Se prevedi di ricevere report di debug, includi la sezione Autorizzazione ACCESS_ADSERVICES_AD_ID nel file manifest Android:

    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />
    
  7. Fare riferimento a una configurazione di servizi pubblicitari nell'elemento <application> di il tuo manifest:

    <property android:name="android.adservices.AD_SERVICES_CONFIG"
              android:resource="@xml/ad_services_config" />
    
  8. Specifica la risorsa XML dei servizi pubblicitari a cui viene fatto riferimento nel file manifest, ad esempio res/xml/ad_services_config.xml. Scopri di più su autorizzazioni dei servizi pubblicitari e controllo accesso SDK.

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

Registrare eventi relativi agli annunci

La tua app deve registrare le sorgenti e le conversioni man mano che si verificano per garantire che vengano segnalate correttamente. La classe MeasurementManager include metodi per registrare gli eventi relativi alle origini dell'attribuzione e attivatori di conversione.

Registra un evento origine attribuzione

Quando un annuncio viene visualizzato o selezionato, l'app di un publisher chiama registerSource() a Registrare un'origine di attribuzione come mostrato nello snippet di codice.

L'API Attribution Reporting supporta i seguenti tipi di origine dell'attribuzione eventi:

  • Clic, che generalmente registri con un metodo di callback simile a onClick(). L'evento di trigger corrispondente di solito si verifica subito dopo evento di clic. Questo tipo di evento fornisce ulteriori informazioni sull'utente ed è quindi un buon tipo di origine dell'attribuzione per fornire una priorità elevata.
  • Visualizzazioni, che in genere registri con un metodo di callback simile a onAdShown(). L'evento di trigger corrispondente può 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 di servizio all'indirizzo specificato da attributionSourceUri. L'endpoint risposta include i valori per destination, source_event_id, expiry e source_priority.

Se la tecnologia pubblicitaria di origine desidera condividere le registrazioni dell'origine, l'URI di origine dell'attribuzione può includere reindirizzamenti ad altri endpoint ad tech. Limiti le regole applicabili ai reindirizzamenti sono descritte nel dettaglio proposta tecnica.

È stato aggiunto il supporto per i reindirizzamenti daisy-chain per registerSource e registerTrigger. Oltre all'intestazione di registrazione, il consumer dell'API può ora forniscono un reindirizzamento HTTP come risposta del server che include lo stato 302. e una "Località" con l'URL successivo da visitare per un ulteriore registrazione.

Solo la "destinazione" fornito alla prima visita viene utilizzato attraverso la margherita. Il numero di visite presenta lo stesso limite del "Attribuzione-Report-Reindirizzamento" intestazioni. Questo supporto del reindirizzamento viene aggiunto all'elemento "Attribution-Reporting-Redirect" esistente assistenza e se entrambi sono attuale, "Attribution-Reporting-Redirect" la preferenza.

Registra un evento di trigger di conversione

Per registrare un evento di attivatore di 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 di servizio all'indirizzo specificato da attributionTriggerUri. La risposta dell'endpoint include i 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 che appartengono ad altre piattaforme di tecnologia pubblicitaria. I limiti e le regole applicabili ai reindirizzamenti sono descritti in dettaglio nella proposta tecnica.

Registra la misurazione cross-app e web

Nel caso in cui sia un'app sia un browser abbiano un ruolo sul percorso dall'origine al trigger, ci sono sottili differenze nel della registrazione degli eventi annuncio. Se un utente vede un annuncio su un'app ed vengono reindirizzati a un browser per una conversione, la sorgente viene registrata dall'app, e la conversione da parte del browser web. Analogamente, se un utente inizia su un browser e viene indirizzato a un'app per la conversione, il browser registra e l'app registra la conversione.

Poiché esistono differenze nel modo in cui le tecnologie pubblicitarie sono organizzate sul web e Android abbiamo aggiunto nuove API per registrare le origini e i trigger quando eseguono sui browser. La differenza principale tra queste API e le API basate su app è che ci aspettiamo che il browser segua i reindirizzamenti, applichi filtri specifici per i browser e trasferire le registrazioni valide alla piattaforma chiamata registerWebSource() o registerWebTrigger().

Il seguente snippet di codice mostra un esempio della chiamata API che il 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 API che il browser 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 destinazione, ID origine attribuzione e trigger e i dati di Google Cloud. Vengono inviati nel formato originale (non criptato) ai report origine dati. Per proteggere la privacy dell'utente, è possibile aggiungere rumore per renderlo più difficile per identificare un singolo utente. Vengono generati report a livello di evento con rumore inviate in conformità con il framework sulla privacy differenziale. Di seguito sono riportati i valori predefiniti della percentuale di rumore per scenari diversi:

Tipo di origine

Valore destinazione origine

Probabilità di report con rumore per registrazione di origine

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, dove le sorgenti possono generare conversioni sia le destinazioni web sia quelle app, i report a livello di evento possono specificare se si è verificato un attivatore su app o web. Per compensare questo ulteriore dettaglio, i report con rumore generato sono fino a circa 7 volte per i clic e di circa 1,7 volte per le visualizzazioni.

Alcune tecnologie pubblicitarie non richiedono report a livello di evento per specificare se l'attivatore nella destinazione app o web. I tecnici pubblicitari possono utilizzare campo coarse_event_report_destinations sotto Attribution-Reporting-Register-Source per ridurre il rumore. Se una fonte con il campo coarse_event_report_destinations specificato vince l'attribuzione, il il report risultante include sia destinazioni app che web senza distinzione fino al punto in cui si è verificato l'effettivo trigger.

Nei seguenti esempi, un utente fa clic su un annuncio e la sorgente viene registrata. con l'API. L'utente esegue poi la conversione sia nell'app dell'inserzionista che sito web dell'inserzionista. Entrambe queste conversioni sono registrate come attivatori attribuiti al clic iniziale.

Un'intestazione HTTP della 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"
}

Dall'app viene registrato un trigger con il 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 sul 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. Presumendo che entrambi gli attivatori 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 inviare report

L'API Attribution Reporting invia i report agli endpoint sul tuo server che accettare report a livello di evento e report aggregabili.

Forza l'esecuzione dei job di reporting

Dopo aver registrato un evento di origine dell'attribuzione o un evento attivatore, il parametro nel sistema pianifica l'esecuzione del job di reporting. Per impostazione predefinita, questo job viene eseguito ogni 4 nell'orario lavorativo locale del TAM. A scopo di test, puoi forzare l'esecuzione o abbreviare i job di reporting tra un job e l'altro.

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 reporting a livello di evento:

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

Forzare l'aggregazione del job di generazione dei report:

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

Controlla l'output in logcat per vedere quando i job sono stati eseguiti. Dovrebbe avere l'aspetto ad esempio:

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

Forza la consegna dei report

Anche se l'esecuzione del job di reporting viene forzata, il sistema invia comunque i report in base ai tempi di consegna pianificati, che vanno da un paio di da alcune ore a diversi giorni. A scopo di test, puoi avanzare nel sistema dei dispositivi in ritardo rispetto ai ritardi pianificati per l'invio del report.

Verificare i report sul server

Una volta inviati i report, verifica l'invio controllando i report ricevuti, applicabili log del server, come la simulazione della cronologia del server o il tuo sistema personalizzato.

Decodifica il report aggregato

Quando ricevi un report aggregato, il campo debug_cleartext_payload viene applicato una versione non criptata del report aggregato. Anche se questa versione il report non è criptato, deve essere ancora decodificato.

Di seguito è riportato un esempio di decodifica dei contenuti dell'debug_cleartext_payload in due passaggi: la prima con la decodifica Base 64 e la seconda con CBOR e decodificare.

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 la Progetto MeasurementSampleApp su GitHub. Questa app di esempio mostra l'origine della registrazione e attivare la registrazione.

Per gli endpoint server, prendi in considerazione le seguenti risorse di riferimento o le soluzione:

  • MeasurementAdTechServerSpec include le definizioni del servizio OpenAPI, di cui è possibile eseguire il deployment su piattaforme fittizie o di microservizi supportate.
  • MeasurementAdTechServer include un'implementazione di riferimento di una simulazione basato sull'app Spring Boot per Google App Engine.

Prerequisiti

Esegui il deployment di API simulate su endpoint remoti accessibili dal dispositivo di test oppure un emulatore. Per semplificare i test, consulta la pagina MeasurementAdTechServerSpec e MeasurementAdTechServer di esempio.

Funzionalità da testare

  • L'origine dell'attribuzione dell'allenamento e la conversione attivano le registrazioni. Verifica che gli endpoint lato server rispondono con il formato corretto.
  • Eseguire i job di reporting.
  • Verifica il recapito dei report sul backend o sulla console del tuo server di test.

Funzionalità in arrivo

Configurazione flessibile a livello di evento

Si consiglia la configurazione predefinita per i report a livello di evento per iniziare test di utilità, ma potrebbe non essere l'ideale per tutti i casi d'uso. L'attribuzione L'API di reporting supporterà configurazioni facoltative e più flessibili in modo che hanno aumentato il controllo sulla struttura dei report a livello di evento. sono in grado di massimizzare l'utilità dei dati. Questa maggiore flessibilità 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 due parametri facoltativi seguenti al file JSON in Attribution-Reporting-Register-Source:

  • max_event_level_reports
  • event_report_windows
di Gemini Advanced.
{
  ...
  // 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 eseguire l'ottimizzazione per ricevere 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 completamente flessibile

Oltre ai parametri aggiunti nella Fase 1, aggiungeremo 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 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 registrazione di origine. Per ogni specifica trigger, specifichiamo completamente:

  • Una serie di criteri di corrispondenza:
    • A quali dati di trigger specifici si applica questa specifica. Questa origine è può essere abbinata solo agli attivatori che hanno uno degli trigger_data in trigger_specs. In altre parole, se il trigger sarebbe stato corrispondente a questa origine, ma il relativo trigger_data non è uno dei valori nella configurazione dell'origine, l'attivatore viene ignorato.
    • Quando un trigger specifico corrisponde a questa specifica (utilizzando event_report_windows). Tieni presente che l'attivatore potrebbe comunque essere abbinato con una fonte per report aggregabili nonostante non funzionino le due corrispondenze criteri menzionati in precedenza.
  • Un algoritmo specifico per riepilogare e suddividere in bucket tutti i trigger all'interno finestra di attribuzione. In questo modo, i trigger possono specificare un parametro value che viene sommato per una determinata specifica, ma riportato come valore in bucket.
di Gemini Advanced.

Gli attivatori supporteranno anche l'aggiunta di un parametro di valore facoltativo nel campo dizionari all'interno di event_trigger_data.

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

Ogni registrazione trigger corrisponde a un massimo di una specifica trigger e viene aggiornata al relativo valore di riepilogo. A livello generale, al momento del trigger:

  • Applicare filtri di attribuzione globali.
  • Per ogni specifica del trigger, valuta il valore event_trigger_data sulla specifica per trovare un usando il valore event_reporting_window della specifica. Il livello superiore event_reporting_windows funge da valore predefinito nel caso in cui una specifica del trigger sia il campo secondario event_report_windows mancante.
  • Viene scelta la prima specifica corrispondente per l'attribuzione, mentre il valore di riepilogo incrementato di value.

Quando il valore event_report_window per una specifica viene completato, ne mapperemo il riepilogo a un bucket e invia un report a livello di evento per ogni incremento bucket di riepilogo causato dai valori trigger attribuiti. I report includono uno 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 API origini di navigazione. Soprattutto per le sorgenti di navigazione, spiega perché i livelli di rumore sono così alti rispetto alle origini di eventi per mantengono gli stessi valori epsilon: le sorgenti di navigazione hanno un output molto più grande spazio.

È possibile che esistano più configurazioni equivalenti, dato che 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>,
}
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>,
}

Esempi di configurazioni personalizzate

Di seguito sono riportate alcune configurazioni aggiuntive diverse da quelle predefinite. In tutti questi esempi, i compromessi che uno sviluppatore può offrire sono:

  • riduzione di alcune dimensioni della configurazione predefinita (#trigger, dati di attivazione cardinalità, #windows) per aumentarne un'altra al fine di preservare il livello di rumore
  • riduzione di alcune dimensioni della configurazione predefinita (#trigger, dati di attivazione cardinalità, #windows) per un livello di rumore ridotto

Bucket di valori trigger dei report

Questa configurazione di esempio supporta uno sviluppatore che vuole ottimizzare per il valore solo per una finestra di reporting (ad es. 7 giorni), con meno transazioni per ridurre il 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]
  }],
}

Gli attivatori possono essere registrati con un set di campi value, che vengono sommati e in bucket. Ad esempio, se ci sono tre attivatori entro 7 giorni dall'origine registrazioni 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, verranno registrati i seguenti attivatori:

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

I valori vengono sommati come 8 + 50 + 45 = 103. In questo modo vengono generati i seguenti report 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 attiva 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 dell'attivatore viene ignorato perché summary_window_operator è impostato come conteggio. Se Quattro attivatori sono stati registrati e attribuiti all'origine; il report nel seguente modo:

// 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]
}
Dati binari con report più frequenti

Questa configurazione di esempio supporta uno sviluppatore che vuole sapere se nei primi 10 giorni si è verificata almeno una conversione (indipendentemente dal valore), ma vuole ricevere report a intervalli più frequenti rispetto a quello predefinito. Ancora una volta, nel In questo esempio, qualsiasi trigger che imposti trigger_data su un valore diverso da 0 non idoneo per l'attribuzione. Ecco perché questo caso d'uso è chiamato 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]
  }],
}
Varia le specifiche dei trigger dall'origine all'origine
{
  "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
}

Incoraggiamo gli sviluppatori a suggerire i diversi casi d'uso che potrebbero avere per questo argomento API e aggiorneremo questa esplicativa con configurazioni di esempio per per questi casi d'uso.

Attribuzione su più reti senza reindirizzamenti

I tecnici pubblicitari devono utilizzare i reindirizzamenti per registrare più attivatori origine di attribuzione ed eseguire l'attribuzione su più reti. Questa funzionalità consente di L'attribuzione su più reti, laddove non è possibile eseguire i reindirizzamenti tra più reti. Ulteriori informazioni.

I tecnici pubblicitari possono inviare la configurazione nella risposta di attivazione della registrazione in base a quali origini registrate da altre tecnologie pubblicitarie vengono selezionate per generare fonti; queste origini derivate vengono utilizzate per l'attribuzione. Report aggregati vengono generati se il trigger viene attribuito a un'origine derivata. Report sugli eventi per le origini derivate non è supportata.

I tecnici pubblicitari possono scegliere tra le aggregation_keys nelle loro origini registrate che che intende condividere con i partner ad tech. Queste chiavi possono essere dichiarate campo facoltativo shared_aggregation_keys, situato sotto la registrazione di origine intestazione Attribution-Reporting-Register-Source:

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

Le origini derivate vengono generate in base alla configurazione sotto il trigger intestazione registrazione 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 per attivare l'intestazione della registrazione. Questi campi abilitare le chiavi dei report inaggregabili dell'identificatore della tecnologia pubblicitaria vincente:

  • x_network_bit_mapping: mappatura di bit dell'ID registrazione nell'identificatore della tecnologia pubblicitaria
  • x_network_data: offset (spostamento a sinistra) per la tecnologia pubblicitaria vincente. Operazione x_network_bit_mapping OR con la parte 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 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 della parte chiave dell'attivatore risultante durante la generazione di un report per Fonte di AdTechB:

  • key_piece: 0x400 (010000000000)
  • key_offset: 12
  • Valore enrollment_id di AdtechB: 2 (010) (da x_network_bit_mapping)
  • Elemento chiave dell'attivatore risultante: 0x400 | 0x2 << 12 = 0x2400

Limitazioni

Per un elenco delle funzionalità in corso per SDK Runtime, visualizza la note di rilascio.

Segnalare bug e problemi

Il tuo feedback è una parte fondamentale di Privacy Sandbox su Android. Contattaci di eventuali problemi trovati o di idee per migliorare Privacy Sandbox su Android.