Guide du développeur de l'API Attribution Reporting

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

Lorsque vous lisez la documentation concernant la Privacy Sandbox sur Android, cliquez sur le bouton Preview développeur ou Bêta pour sélectionner la version du programme que vous utilisez, car les instructions peuvent varier.


L'API Attribution Reporting est conçue pour améliorer la confidentialité des utilisateurs en supprimant la dépendance aux identifiants utilisateur multipartites, et pour prendre en charge des cas d'utilisation clés de l'attribution et de la mesure des conversions dans les applications. Ce guide du développeur vous explique comment configurer et tester les API Attribution Reporting pour enregistrer les clics, les vues et les conversions de vos annonces, en appelant des méthodes qui enregistrent les déclencheurs et les sources pertinents pour de tels événements.

Ce guide vous explique comment configurer des points de terminaison de serveur et créer une application cliente qui appelle ces services. Pour en savoir plus sur la conception globale de l'API Attribution Reporting, consultez la proposition de conception.

Mots clés

  • Les sources d'attribution font référence aux vues ou aux clics.
  • Les déclencheurs sont des événements qui peuvent être attribués aux conversions.
  • Les rapports contiennent des données sur un déclencheur et la source d'attribution correspondante. Ces rapports sont envoyés en réponse à des événements déclencheurs. L'API Attribution Reporting est compatible avec les rapports au niveau des événements et les rapports agrégables.

Avant de commencer

Pour utiliser l'API Attribution Reporting, effectuez les tâches côté serveur et côté client indiquées dans les sections suivantes.

Configurer les points de terminaison de l'API Attribution Reporting

L'API Attribution Reporting nécessite un ensemble de points de terminaison auxquels vous pouvez accéder depuis un appareil de test ou un émulateur. Créez un point de terminaison pour chacune des tâches suivantes côté serveur :

Il existe plusieurs méthodes pour configurer les points de terminaison requis :

  • Le moyen le plus rapide est de déployer les définitions de service OpenAPI v3 depuis notre dépôt d'exemple de code sur une plate-forme fictive ou de microservices. Vous pouvez utiliser Postman, Prism ou toute autre plate-forme fictive de serveur qui accepte ce format. Déployez chaque point de terminaison et effectuez le suivi des URI à utiliser dans votre application. Pour vérifier la diffusion du rapport, reportez-vous aux appels précédemment effectués vers la plate-forme fictive ou sans serveur.
  • Exécutez votre propre serveur autonome à l'aide de l'exemple Kotlin basé sur Spring Boot. Déployez ce serveur sur votre fournisseur de services cloud ou sur votre infrastructure interne.
  • Utilisez les définitions de service comme exemples pour intégrer les points de terminaison dans votre système existant.

Accepter l'enregistrement de la source

Ce point de terminaison doit être adressable à partir d'un URI semblable à celui-ci :

https://adtech.example/attribution_source

Lorsqu'une application cliente enregistre une source d'attribution, elle fournit l'URI de ce point de terminaison du serveur. L'API Attribution Reporting envoie ensuite une requête et inclut l'un des en-têtes suivants :

  • Pour les événements de clic :

    Attribution-Reporting-Source-Info: navigation
    
  • Pour les événements de vue :

    Attribution-Reporting-Source-Info: event
    

Configurez le point de terminaison de votre serveur pour qu'il réponde comme suit :

// 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]",
  "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": [{
    "id": "[key name]",
    "key_piece": "[key piece value]",
  },
  ..
  ]
    "debug_key": "[64-bit unsigned integer]"
}
// Specify additional adtech URLs to register this source with.
Attribution-Reporting-Redirect: <Ad Tech Partner URI 1>
Attribution-Reporting-Redirect: <Ad Tech Partner URI 2>

Voici un exemple concret :

Attribution-Reporting-Register-Source: {
  "destination": "android-app://com.example.advertiser",
  "source_event_id": "234",
  "expiry": "60000",
  "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".
    "id": "campaignCounts",
  // User saw an ad from campaign 345 (out of 511).
    "key_piece": "0x159",
  },
  {
  // Generates a "0x5" key piece (low order bits of the key) for the key named
  // "geoValue".
    "id": "geoValue",
  // Source-side geo region = 5 (US), out of a possible ~100 regions.
    "key_piece": "0x5",
  }]
}
Attribution-Reporting-Redirect:
https://adtechpartner1.example?their_ad_click_id=567
Attribution-Reporting-Redirect:
https://adtechpartner2.example?their_ad_click_id=890

Si Attribution-Reporting-Redirects contient les URI de partenaires de technologie publicitaire, l'API Attribution Reporting envoie une requête similaire à chaque URI. Chaque partenaire de technologie publicitaire doit configurer un serveur qui répond avec ces en-têtes :

Attribution-Reporting-Register-Source: {
  "destination": "[app package name]",
  "web_destination": "[eTLD+1]",
  "source_event_id": "[64 bit unsigned integer]",
  "expiry": "[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": [{
    "id": "[key name]",
    "key_piece": "[key piece value]",
   },
   ..
  ]
}
// The Attribution-Reporting-Redirect header is ignored for adtech partners.

Accepter l'enregistrement du déclencheur de conversion

Ce point de terminaison doit être adressable à partir d'un URI semblable à celui-ci :

https://adtech.example/attribution_trigger

Lorsqu'une application cliente enregistre un événement déclencheur, elle fournit l'URI de ce point de terminaison du serveur. L'API Attribution Reporting envoie ensuite une requête et inclut l'un des en-têtes suivants :

Configurez le point de terminaison de votre serveur pour qu'il réponde comme suit :

// 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.
    // Note: "source_type" can be used as a key to filter based on the source's
    // type "navigation" or "event".
    // The first "Event-Trigger" that matches, based on "filters" and
    // "not_filters", is used for report generation. If there are no matches,
    // no report is generated.
    "filters": {
      "[key name 1]": ["key1 value 1", "key1 value 2"],
      // If a key is missing from "filters" or the attribution source's
      // "filter_data", it isn't 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 the attribution source's
      // "filter_data", it isn't used during matching.
      "[key name 2]": ["key2 value 1", "key2 value 2"],
    }
  }],
  // Specify a list of dictionaries that generates aggregation keys.
  "aggregabtable_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" and "not_filters" are optional fields, similar to the 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
  // that they're generated.
  "aggregabtable_values": [
     // Each source event can contribute a maximum of L1 = 2^16 to the aggregate
     // histogram.
    {
     "[key_name]": [value]
    },
    ..
  ]
"debug_key": "[64-bit unsigned integer]"
}
// Specify additional Adtech 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>

Voici un exemple concret :

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": {
      "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": {
      "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"]
    },
    {
      // 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", "nonMatchingIdsListedHereAreIgnored"]
    }
  ],
  "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
    }
  ]
}
Attribution-Reporting-Redirect:https://adtechpartner.example?app_install=567

Si Attribution-Reporting-Redirect contient les URI de partenaires de technologie publicitaire, l'API Attribution Reporting envoie une requête similaire à chaque URI. Chaque partenaire de technologie publicitaire doit configurer un serveur qui répond avec ces en-têtes :

// 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]",
    // "filters" and "not_filters" are optional fields which allow configuring
    // for configuring different event trigger data based on the attribution]
    // source's "filter_data". Note that "source_type" can be used as a key to
    // filter based on the source's type "navigation" or "event".
    // The first "Event-Trigger" that matches, based on "filters" and
    // "not_filters", is used for report generation. If there are no matches,
    // no report is generated.
    "filters": {
      "[key name 1]": ["key1 value 1", "key1 value 2"],
      // If a key is missing from "filters" or the attribution source's
      // "filter_data", it isn't 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 the attribution source's
      // "filter_data", it isn't 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" and "not_filters" are optional fields, similar to the 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 adtech partners.

Accepter les rapports au niveau des événements

Ce point de terminaison doit être adressable à partir d'un URI. Pour en savoir plus sur l'enregistrement des URI, consultez Créer un compte Privacy Sandbox. Notez que l'URI est déduit de l'eTLD+1 des serveurs utilisés pour accepter l'enregistrement de la source et déclencher l'enregistrement. En utilisant les exemples d'URI pour les points de terminaison qui acceptent l'enregistrement de la source et l'enregistrement du déclencheur, l'URI de ce point de terminaison est le suivant :

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

Configurez ce serveur pour accepter les requêtes JSON qui utilisent le format suivant :

{
  "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]",
}

Les clés de débogage permettent d'obtenir des informations supplémentaires dans vos rapports sur l'attribution. Découvrez comment les configurer.

Accepter les rapports agrégables

Ce point de terminaison doit être adressable à partir d'un URI. Pour en savoir plus sur l'enregistrement des URI, consultez Créer un compte Privacy Sandbox. Notez que l'URI est déduit de l'origine des serveurs utilisés pour accepter l'enregistrement de la source et déclencher l'enregistrement. En utilisant les exemples d'URI pour les points de terminaison qui acceptent l'enregistrement de la source et l'enregistrement du déclencheur, l'URI de ce point de terminaison est le suivant :

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

Actuellement, les champs chiffrés et non chiffrés sont renseignés pour les rapports agrégables. Les rapports chiffrés vous permettent de commencer les tests avec le service d'agrégation, tandis que le champ non chiffré fournit des informations sur la façon dont les paires clé/valeur définies structurent les données.

Configurez ce serveur pour accepter les requêtes JSON qui utilisent le format suivant :

{
  // 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]"
}

Les clés de débogage permettent d'obtenir des informations supplémentaires dans vos rapports sur l'attribution. Découvrez comment les configurer.

Configurer le client Android

L'application cliente enregistre les sources et les déclencheurs d'attribution, et permet de générer des rapports au niveau des événements et agrégables. Pour préparer un appareil client ou un émulateur Android à l'aide de l'API Attribution Reporting, procédez comme suit :

  1. Configurez votre environnement de développement pour la Privacy Sandbox sur Android.
  2. Installez une image système sur un appareil compatible ou configurez un émulateur compatible avec la Privacy Sandbox sur Android.
  3. Activez l'accès à l'API Attribution Reporting en exécutant la commande ADB suivante. (L'API est désactivée par défaut.)

    adb shell device_config put adservices ppapi_app_allow_list \"*\"
    
  4. Incluez l'autorisation ACCESS_ADSERVICES_ATTRIBUTION et créez une configuration de services publicitaires pour que votre application utilise les API Attribution Reporting, comme indiqué dans l'extrait de code suivant :

    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
    
  5. Spécifiez la ressource XML des services publicitaires référencée dans le fichier manifeste, telle que res/xml/ad_services_config.xml. En savoir plus sur les autorisations des services publicitaires et le contrôle des accès au SDK

    <property android:name="android.adservices.AD_SERVICES_CONFIG"
          android:resource="@xml/ad_services_config" />
    
  6. Référencer une configuration de services publicitaires dans l'élément <application> de votre fichier manifeste :

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

Enregistrer des événements d'annonce

Votre application devrait enregistrer les sources et les conversions au fur et à mesure pour qu'elles soient correctement rapportées. La classe MeasurementManager inclut des méthodes vous permettant d'enregistrer des événements de source d'attribution et des déclencheurs de conversion.

Enregistrer un événement de source d'attribution

Lorsqu'une personne voit une annonce ou clique dessus, une application d'éditeur appelle registerSource() pour enregistrer une source d'attribution, comme illustré dans l'extrait de code.

L'API Attribution Reporting est compatible avec les types d'événements de source d'attribution suivants :

  • Clics, que vous enregistrez généralement dans une méthode de rappel semblable à onClick(). L'événement déclencheur correspondant se produit généralement peu de temps après l'événement de clic. Ce type d'événement fournit plus d'informations sur l'interaction utilisateur et constitue donc un bon type de source d'attribution pour octroyer un niveau de priorité élevé.
  • Vues, que vous enregistrez généralement dans une méthode de rappel semblable à onAdShown(). L'événement de déclenchement correspondant peut se produire des heures ou des jours après l'événement de vue.

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);

Après l'enregistrement, l'API envoie une requête HTTP POST au point de terminaison de service à l'adresse spécifiée par attributionSourceUri. La réponse du point de terminaison inclut des valeurs pour destination, source_event_id, expiry et source_priority.

Si la technologie publicitaire d'origine souhaite partager les enregistrements de la source, l'URI de la source d'attribution d'origine peut inclure des redirections vers d'autres points de terminaison de la technologie publicitaire. Les limites et les règles applicables aux redirections sont détaillées dans la proposition technique.

Enregistrer un événement déclencheur de conversion

Pour enregistrer un événement de déclencheur de conversion, appelez registerTrigger() dans votre application :

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)

Après l'enregistrement, l'API envoie une requête HTTP POST au point de terminaison de service à l'adresse spécifiée par attributionTriggerUri. La réponse du point de terminaison inclut les valeurs des événements et des rapports d'agrégation.

Si la plate-forme de technologie publicitaire d'origine autorise le partage des enregistrements de déclencheurs, l'URI peut inclure des redirections vers des URI appartenant à d'autres plates-formes de technologie publicitaire. Les limites et les règles applicables aux redirections sont détaillées dans la proposition technique.

Enregistrer des mesures multi-applications et Web

Dans le cas où une application et un navigateur jouent tous deux un rôle dans le parcours utilisateur, de la source au déclencheur, il existe de légères différences dans l'implémentation des enregistrements d'événements d'annonce. Si un utilisateur voit une annonce dans une application et est redirigé vers un navigateur pour une conversion, la source est enregistrée par l'application et la conversion par le navigateur Web. De même, si un utilisateur démarre dans un navigateur Web et qu'il est redirigé vers une application pour la conversion, le navigateur enregistre la source et l'application enregistre la conversion.

Étant donné qu'il existe des différences dans l'organisation des technologies publicitaires sur le Web et sur Android, nous avons ajouté de nouvelles API pour enregistrer les sources et les déclencheurs lorsqu'ils se produisent dans les navigateurs. La principale différence entre ces API et les API basées sur les applications correspondantes est que le navigateur doit suivre les redirections, appliquer des filtres spécifiques au navigateur et transmettre les enregistrements valides à la plate-forme en appelant registerWebSource() ou registerWebTrigger().

L'extrait de code suivant présente un exemple d'appel d'API par le navigateur pour enregistrer une source d'attribution avant de rediriger l'utilisateur vers une application :

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 adtech.
    .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 adtech.
    .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);

L'extrait de code suivant présente un exemple d'appel d'API par le navigateur pour enregistrer une conversion après que l'utilisateur a été redirigé depuis l'application :

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 adtech.
    .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 adtech.
    .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);

Générer et diffuser des rapports

L'API Attribution Reporting envoie des rapports aux points de terminaison de votre serveur qui acceptent les rapports au niveau des événements et des rapports agrégables.

Forcer l'exécution des tâches de création de rapports

Une fois que vous avez enregistré un événement de source d'attribution ou de déclencheur, le système planifie l'exécution de la tâche de création de rapports. Par défaut, cette tâche s'exécute toutes les quatre heures. À des fins de test, vous pouvez forcer les tâches de création de rapports à s'exécuter ou raccourcir les intervalles entre les tâches.

Forcer l'exécution de la tâche d'attribution :

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

Forcer l'exécution de la tâche de création de rapports au niveau des événements :

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

Forcer l'exécution de la tâche de création de rapports agrégables :

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

Vérifiez le résultat dans logcat pour voir quand les tâches ont été exécutées. Le résultat devrait ressembler à ceci :

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

Forcer la diffusion des rapports

Même si l'exécution de la tâche de création de rapport est forcée, le système envoie toujours des rapports en fonction des délais de diffusion planifiés, qui peuvent aller de quelques heures à plusieurs jours. À des fins de test, vous pouvez repousser l'heure du système de l'appareil après les délais planifiés pour lancer la diffusion du rapport.

Vérifier les rapports sur votre serveur

Une fois les rapports envoyés, vérifiez leur diffusion en consultant les rapports reçus, les journaux de serveur applicables tels que l'historique du serveur fictif ou votre système personnalisé.

Tests

Pour commencer à utiliser l'API Attribution Reporting, vous pouvez utiliser le projet MeasurementSampleApp sur GitHub. Cet application exemple illustre l'enregistrement de la source d'attribution et du déclencheur.

Pour les points de terminaison du serveur, utiliser les ressources de référence suivantes ou votre solution personnalisée :

  • MeasurementAdTechServerSpec inclut les définitions de service OpenAPI, qui peuvent être déployées sur une plate-forme fictive ou sur des plates-formes de microservices compatibles.
  • MeasurementAdTechServer inclut une implémentation de référence d'un serveur fictif basé sur l'application Spring Boot pour Google App Engine.

Conditions préalables

Déployez des API fictives sur des points de terminaison distants accessibles depuis votre appareil de test ou votre émulateur. Pour faciliter les tests, reportez-vous aux exemples de projets MeasurementAdTechServerSpec et MeasurementAdTechServer.

Fonctionnalité à tester

Limites

Pour obtenir la liste des fonctionnalités en cours de développement pour l'environnement d'exécution du SDK, consultez les notes de version.

Signaler des bugs et des problèmes

Vos commentaires sont essentiels pour la Privacy Sandbox sur Android. Signalez-nous les problèmes que vous rencontrez et vos idées pour améliorer Privacy Sandbox sur Android.