Guide du développeur des signaux d'application protégés

Pour aider les développeurs à tester l'API Protected App Signals, ce document décrit toutes les API de la surface de l'API, explique comment configurer un environnement de test et fournit des exemples de configuration et de scripts.

Historique des versions

Janvier 2024

Première version du guide du développeur compatible avec la version PAS MVP

March 2024

Modifications apportées à l'API pour prendre en charge la version M-2024-05 de l'API Android et la version d'avril 2024 des composants côté serveur. Changements les plus importants:

  • Ajout de détails sur les autorisations requises pour l'API sur l'appareil
  • Ajout de détails sur la gestion du quota des signaux sur l'appareil
  • Mise à jour de la signature generateBid avec les modifications liées à la prise en charge de la récupération d'annonces contextuelles et de la sortie.
  • Mise à jour de la documentation de reportWin, y compris la prise en charge du trafic de sortie
  • Mise à jour de la documentation de l'API Ad Retrieval, supprimant la prise en charge de la récupération des annonces BYOS et documentant la fonction définie par l'utilisateur pour la récupération des annonces

Présentation de l'API

La surface de l'API Protected Signals inclut différents sous-ensembles d'API sur différents systèmes :

  • API Android :
    • API Signal Curation, composée des éléments suivants :
    • Mettre à jour l'API Signals
    • API Signals Encoding
    • API Protected Auction Support : à utiliser par les SDK pour lancer la mise aux enchères protégée sur les serveurs d'enchères et de mise aux enchères à l'aide de signaux d'application protégés.
  • API côté serveur :
    • API Protected Auction : série de scripts JavaScript exécutés dans les serveurs d'enchères et de mise aux enchères. Cette API permet aux vendeurs et aux acheteurs d'écrire la logique pour implémenter l'enchère protégée.
    • API Ad Retrieval : chargée de fournir une liste d'annonces candidates en fonction des informations contextuelles et utilisateur mises à la disposition du serveur d'enchères de l'acheteur.

Client Android

Côté client, la surface des signaux d'application protégés se compose de trois API différentes :

  • Signaux de mise à jour : API du système Android permettant de gérer les signaux sur l'appareil.
  • Encodage des signaux : API JavaScript pour préparer les signaux à envoyer au serveur lors de l'enchère.
  • Protected Auction Support : API permettant l'exécution d'une enchère protégée sur les serveurs d'enchères et de mise aux enchères. Cette API n'est pas spécifique aux signaux d'application protégés et sert également à prendre en charge les enchères pour l'API Protected Audience.

Mettre à jour l'API Signals

L'API Update Signals permet aux technologies publicitaires d'enregistrer des signaux liés à l'utilisateur inscrit et à l'application pour le compte d'un acheteur. L'API fonctionne sur un modèle de délégation. L'appelant fournit un URI à partir duquel le framework extrait les signaux correspondants, ainsi que la logique permettant d'encoder ces signaux à utiliser lors de l'enchère.

L'API nécessite l'autorisation android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS.

L'API updateSignals() récupère un objet JSON à partir de l'URI, qui décrit les signaux à ajouter ou à supprimer, et comment préparer ces signaux pour l'enchère.

Executor executor = Executors.newCachedThreadPool();
ProtectedSignalsManager protectedSignalsManager
     =  ProtectedSignalsManager.get(context);

// Initialize a UpdateSignalsRequest
UpdateSignalsRequest updateSignalsRequest = new
  UpdateSignalsRequest.Builder(Uri.parse("https://example-adtech1.com/signals"))
      .build();

OutcomeReceiver<Object, Exception> outcomeReceiver = new OutcomeReceiver<Object, Exception>() {
  @Override
  public void onResult(Object o) {
    //Post-success actions
  }

  @Override
  public void onError(Exception error) {
    //Post-failure actions
  };

// Call updateSignals
protectedSignalsManager.updateSignals(updateSignalsRequest,
    executor,
    outcomeReceiver);

La plate-forme envoie une requête HTTPS à l'URI fourni dans la requête pour récupérer les mises à jour des signaux. Avec les mises à jour des signaux, la réponse peut inclure un point de terminaison qui héberge la logique d'encodage permettant de convertir les signaux bruts en charge utile encodée. Les mises à jour des signaux doivent être au format JSON et peuvent avoir les clés suivantes :

Les clés de niveau supérieur de l'objet JSON doivent correspondre à l'une des cinq commandes suivantes :

clé

Description

put

Ajoute un nouveau signal en écrasant tous les signaux existants ayant la même clé. La valeur

correspondante est un objet JSON dans lequel les clés sont des chaînes en base64 correspondant à la clé à mettre et les valeurs sont des chaînes en base64 correspondant à la valeur à mettre.

append

Ajoute un ou plusieurs nouveaux signaux à une série temporelle de signaux, en supprimant les plus anciens

afin de faire de la place pour les nouveaux si la taille de la série dépasse la taille maximale donnée. La valeur correspondante est un objet JSON dans lequel les clés sont des chaînes en base64 correspondant à la clé à ajouter. Les valeurs sont des objets comportant deux champs : "values" et "maxSignals".

"values" : liste de chaînes en base64 correspondant aux valeurs de signaux à ajouter à la série temporelle.

"maxSignals" : nombre maximal de valeurs autorisées dans cette série temporelle. Si

le nombre actuel de signaux associés à la clé dépasse la valeur maxSignals, les signaux les plus anciens seront supprimés. Notez que vous pouvez ajouter des signaux à une clé ajoutée par le biais de la méthode "put". Notez que si vous ajoutez plus de valeurs que le nombre maximal autorisé, un échec se produira.

put_if_not_present

Ajoute un nouveau signal uniquement s'il n'existe aucun signal associé à la même clé. La valeur correspondante est un objet JSON dans lequel les clés sont des chaînes en base64 correspondant à la clé à insérer et les valeurs sont une chaîne en base64 correspondant à la valeur à mettre.

remove

Supprime le signal d'une clé. La valeur correspondante est une liste de chaînes en base64 correspondant aux clés de signaux à supprimer.

update_encoder

Fournit une action pour mettre à jour le point de terminaison et un URI qui peuvent être utilisés

pour récupérer une logique d'encodage. La sous-clé permettant de fournir une action de mise à jour est "action" et

les valeurs actuellement prises en charge sont uniquement "REGISTER". Si le point de terminaison de l'encodeur est fourni pour la première fois, il enregistre le point de terminaison de l'encodeur ou écrase le point de terminaison existant par le nouveau point de terminaison fourni. Vous devez indiquer le point de terminaison pour l'action "REGISTER". La sous-clé permettant de fournir un point de terminaison d'encodeur est "endpoint" et sa valeur est la chaîne URI

du point de terminaison.

Voici comment se présente un exemple de requête JSON :

{
    "put": {
        "AAAAAQ==": "AAAAZQ==",
        "AAAAAg==": "AAAAZg=="
    },
    "append": {
        "AAAAAw==": {
            "values": [
                "AAAAZw=="
            ],
            "max_signals": 3
        }
    },
    "put_if_not_present": {
        "AAAABA==": "AAAAaQ==",
        "AAAABQ==": "AAAAag=="
    },
    "update_encoder": {
        "action": "REGISTER",
        "endpoint": "https://adtech1.com/Protected App Signals_encode_script.js"
    }
}

Les signaux ont un quota sur l'appareil de l'ordre de 10 à 15 Ko. Une fois le quota dépassé, l'API protégeant la confidentialité évince les signaux à l'aide d'une stratégie FIFO. Le processus d'éviction permet de dépasser légèrement le quota pendant de courts intervalles de temps afin de réduire la fréquence des évictions.

API Signals Encoding

Les acheteurs doivent fournir une fonction Java Script à utiliser pour encoder les signaux stockés sur l'appareil à envoyer au serveur lors de l'enchère protégée. Les acheteurs peuvent fournir ce script en ajoutant l'URL à partir de laquelle il peut être extrait à l'aide de la clé "update_encoder" dans l'une des réponses à une requête API UpdateSignal. Le script aura la signature suivante :

function encodeSignals(signals, maxSize) {
  let result = new Uint8Array(maxSize);
  // first entry will contain the total size
  let size = 1;
  let keys = 0;
  
  for (const [key, values] of signals.entries()) {
    keys++;
    // In this encoding we only care about the first byte
    console.log("key " + keys + " is " + key)
    result[size++] = key[0];
    result[size++] = values.length;
    for(const value of values) {
      result[size++] = value.signal_value[0];
    }
  }
  result[0] = keys;
  
  return { 'status': 0, 'results': result.subarray(0, size)};
}

Le paramètre signals est un mappage de clés au format UInt8Arrays de taille 4 à des listes d'objets des signaux d'application protégés. Chaque objet des signaux d'application protégés comporte trois champs :

  • signal_value : un UInt8Array représentant la valeur du signal.
  • creation_time : un nombre représentant l'heure de création des signaux en secondes Epoch.
  • package_name : une chaîne représentant le nom du package qui a créé le signal.

Le paramètre maxSize est un nombre décrivant la plus grande taille de tableau autorisée pour la sortie.

La fonction doit générer un objet avec deux champs :

  • status : doit être défini sur 0 si le script a bien été exécuté.
  • results : doit être un UInt8Array de longueur inférieure ou égale à maxSize. Ce tableau sera envoyé au serveur lors des enchères et préparé par le script prepareDataForAdRetrieval.

L'encodage fournit aux technologies publicitaires une étape initiale d'ingénierie des caractéristiques, au cours de laquelle elles peuvent effectuer des transformations telles que la compression de signaux bruts en versions concaténées en fonction de leur propre logique personnalisée. Notez que lors d'enchères protégées exécutées dans les environnements d'exécution sécurisés (TEE, Trusted Execution Environments), la logique personnalisée des technologies publicitaires dispose d'un accès en lecture aux charges utiles de signaux générées par l'encodage. La logique personnalisée, appelée fonction définie par l'utilisateur (UDF), exécutée dans les environnements d'exécution sécurisés d'enchères et de mises aux enchères de l'acheteur disposera d'un accès en lecture aux signaux encodés et aux autres signaux de contexte fournis par l'application de l'éditeur pour effectuer la sélection des annonces (récupération des annonces et enchères).

Encodage des signaux

Toutes les heures, les acheteurs qui ont fourni une logique d'encodage avec leurs signaux enregistrés sont encodés dans une charge utile d'enchère. Le tableau d'octets de la charge utile de l'enchère est conservé sur l'appareil. Il est chiffré et les données seront collectées par les vendeurs dans le cadre des données sur la sélection des annonces, puis incluses dans le cadre d'une enchère protégée. Pour les tests, vous pouvez déclencher cet encodage en dehors de sa fréquence horaire en exécutant la commande suivante :

adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
Gestion des versions de la logique d'encodeur

Lorsqu'une requête est effectuée pour télécharger la logique d'encodeur personnalisé de la technologie publicitaire, le point de terminaison de la technologie publicitaire peut répondre avec un numéro de version dans les en-têtes de réponse. Cette version est conservée avec la logique d'encodeur sur l'appareil. Lorsque les signaux bruts sont encodés, la charge utile encodée est conservée avec la version utilisée pour l'encodage. Cette version est également envoyée au serveur d'enchères et de mise aux enchères lors d'une mise aux enchères protégée, afin que les technologies publicitaires puissent aligner leur logique d'enchères et d'encodage en fonction de la version.

Response header for providing encoder version : X_ENCODER_VERSION

API Protected Auction Support

Côté appareil, le lancement d'une mise aux enchères pour les signaux d'application protégés revient à la même mise aux enchères que pour les audiences protégées.

Services d'enchères et de mise aux enchères

Les API côté serveur incluent :

  • API Protected Auction : série de fonctions JS, ou UDF, que les acheteurs et les vendeurs peuvent déployer sur les composants des enchères et de mise aux enchères dont ils sont propriétaires, afin de déterminer les enchères et la logique d'enchères.
  • API Ad Retrieval : les acheteurs peuvent implémenter cette API en implémentant un point de terminaison REST qui sera chargé de fournir un ensemble d'annonces candidates pour la mise aux enchères des signaux d'application protégés.

API Protected Auction

L'API Protected Auction se compose d'une API JS ou de plusieurs UDF que les acheteurs et les vendeurs peuvent utiliser pour implémenter leur logique d'enchères et de mise aux enchères.

Fonction définie par l'utilisateur (UDF) de technologies publicitaires pour les acheteurs
UDF prepareDataForAdRetrieval

Avant que les signaux d'application protégés puissent être utilisés pour extraire des annonces candidates à partir du service de récupération d'annonces du TEE, les acheteurs doivent décoder et préparer les signaux d'application protégés ainsi que d'autres données fournies par le vendeur. La sortie de l'UDF prepareDataForAdRetrieval de l'acheteur est transmise au service de récupération d'annonces afin de récupérer les k premières annonces candidates pour les enchères.

// Inputs
// ------
// encodedOnDeviceSignals: A Uint8Array of bytes from the device.
// encodedOnDeviceSignalsVersion: An integer representing the encoded
//   version of the signals.
// sellerAuctionSignals: Information about auction (ad format, size) derived
//                       contextually.
// contextualSignals: Additional contextual signals that could help in
//                    generating bids.
//
// Outputs
// -------
// Returns a JSON structure to be used for retrieval.
// The structure of this object is left to the adtech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
   return {};
}
UDF generateBid

Une fois les k premières annonces candidates renvoyées, elles sont transmises à la logique d'enchères personnalisées de l'acheteur, UDF generateBid :

// Inputs
// ------
// ads: Data string returned by the ads retrieval service. This can include Protected App Signals
//   ads and related ads metadata.
// sellerAuctionSignals: Information about the auction (ad format, size),
//                       derived contextually
// buyerSignals: Any additional contextual information provided by the buyer
// preprocessedDataForRetrieval: This is the output of this UDF.
function generateBid(ads, sellerAuctionSignals, buyerSignals,
                    preprocessedDataForRetrieval,
                    rawSignals, rawSignalsVersion) {
    return { "ad": <ad Value Object>,
             "bid": <float>,
             "render": <render URL string>,
             'adCost': <optional float ad cost>,
             "egressPayload": <limitedEgressPayload>,
             "temporaryUnlimitedEgressPayload": <temporaryUnlimitedEgressPayload>
    };
}

Le résultat de cette fonction correspond à une enchère unique pour une annonce candidate, représentée sous la forme d'un fichier JSON équivalent à ProtectedAppSignalsAdWithBidMetadata. La fonction peut également renvoyer deux tableaux, qui seront ensuite transmis à reportWin pour permettre l'entraînement du modèle (pour en savoir plus sur la sortie et l'entraînement du modèle, consultez la section sur les rapports dans l'explication PAS).

UDF reportWin

À la fin d'une enchère, le service d'enchères génère des URL de rapport pour les acheteurs et enregistre des balises à l'aide de reportWin UDF (il s'agit de la même fonction reportWin que celle utilisée pour les audiences protégées). L'appareil enverra un ping une fois l'annonce diffusée par le client. La signature de cette méthode est presque identique à la version de l'API Protected Audience, à l'exception de deux paramètres supplémentaires egressPayload et temporaryUnlimitedEgressPayload, utilisés pour activer l'entraînement du modèle et contenant les résultats de generateBid.

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals,
                   egressPayload, temporaryUnlimitedEgressPayload) {
  // ...
}
Fonctions définies par l'utilisateur (UDF) de technologies publicitaires pour les vendeurs
UDF scoreAd

Les vendeurs utilisent cette UDF pour sélectionner les annonces envoyées par les acheteurs qui remporteront l'enchère.

function scoreAd(adMetadata, bid, auctionConfig,
                 trustedScoringSignals, bid_metadata) {
  // ...
  return {desirability: desirabilityScoreForThisAd,
              allowComponentAuction: true_or_false};
}
UDF reportResult

Cette UDF permet au vendeur (à terme) de créer des rapports au niveau des événements avec les informations concernant l'annonce gagnante.

function reportResult(auctionConfig, reporting_metadata) {
  // ...
  registerAdBeacon({"click", clickUrl,"view", viewUrl});
  sendReportTo(reportResultUrl);
  return signalsForWinner;
}

API Ad Retrieval

Dans la version MVP, le service de récupération d'annonces sera un service géré et hébergé par l'acheteur, et le service d'enchères récupère les annonces candidates de ce service. À partir d'avril 2024, le serveur de récupération des annonces devra s'exécuter dans un environnement d'exécution sécurisé (TEE) et exposera une interface gRPC/proto. Les entreprises de technologie publicitaire doivent configurer ce serveur et fournir leur URL lors du déploiement de la pile d'enchères et dans le cadre de la mise aux enchères. Une implémentation de ce service s'exécutant dans le TEE est disponible dans le GitHub de la Privacy Sandbox. Dans le reste de la documentation, nous partons du principe qu'il s'agit du code utilisé dans le déploiement.

Depuis avril 2024, les versions d'enchères et de mise aux enchères prennent en charge la récupération des annonces de chemin d'accès contextuel. Dans ce cas, le serveur d'enchères reçoit une liste d'identifiants d'annonces envoyés par le serveur RTB lors de la partie contextuelle de l'enchère. Les identifiants seront envoyés à un serveur TEE KV pour récupérer toutes les informations liées aux annonces à utiliser lors de la phase d'enchères (par exemple, "ad-render-url", les métadonnées et les représentations vectorielles continues d'annonces à utiliser dans la sélection "top-k"). Ce deuxième chemin d'accès ne nécessite le déploiement d'aucune logique spécifique. Nous ne documenterons donc ici que comment configurer le cas d'utilisation de récupération d'annonces basé sur le TEE.

UDF HandleRequest
function HandleRequest(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals) {
    return adsMetadataString;
}

Où :

  • requestMetadata : JSON Métadonnées de serveur par requête dans la fonction définie par l'utilisateur. Vider pour le moment.
  • preparedDataForAdRetrieval: le contenu de ce champ dépend de la stratégie de récupération des annonces. Dans le cas de la récupération d'annonces contextuelles, ce paramètre contiendra les signaux bruts provenant de l'appareil et transmis par le service d'enchères. Dans le cas de la récupération d'annonces TEE à l'aide du serveur de récupération d'annonces, ce paramètre contient le résultat de la fonction prepareDataForAdRetrieval définie par l'utilisateur. Remarque: À ce stade, les signaux d'application protégés sont décodés et non chiffrés.
  • deviceMetadata: objet JSON contenant les métadonnées de l'appareil transférées par le service publicitaire du vendeur. Pour en savoir plus, consultez la documentation sur les enchères et mises aux enchères.
    • X-Accept-Language: langue utilisée sur l'appareil.
    • X-User-Agent: user-agent utilisé sur l'appareil
    • X-BnA-Client-IP: adresse IP de l'appareil.
  • contextualSignals: chaîne arbitraire provenant du serveur d'enchères contextuelles géré par la même DSP. La fonction définie par l'utilisateur doit pouvoir décoder la chaîne et l'utiliser. Ils peuvent contenir des informations telles que des informations sur la version du modèle de ML pour la représentation vectorielle continue protégée transmise à l'aide de signaux d'application protégés.

En cas de réussite, l'UDF doit renvoyer une chaîne. La chaîne est renvoyée au serveur d'enchères, qui la transmet ensuite à la fonction generateBid définie par l'utilisateur. Bien que la chaîne puisse être simplement une chaîne simple, il est très probable qu'il s'agisse d'un objet sérialisé dont le schéma est défini par chaque technologie publicitaire elle-même. Il n'y a aucune contrainte sur le schéma tant que la logique generateBid de la technologie publicitaire peut reconnaître et utiliser la chaîne.

Configurer le système pour le développement

Android

Pour configurer votre environnement de développement Android, vous devez procéder comme suit :

  1. Créez un émulateur (de préférence) ou un appareil physique qui exécute l'image Preview développeur 10.
  2. Pour ce faire, exécutez la commande suivante :
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity

Sélectionnez ensuite l'option affichée permettant d'autoriser les annonces suggérées par les applis.

  1. Exécutez la commande suivante pour activer les API appropriées. Vous devrez peut-être réexécuter cette commande de temps en temps, car la configuration par défaut de la colonne "Désactivé" sera régulièrement synchronisée.
adb shell device_config put adservices fledge_custom_audience_service_kill_switch false;  adb shell device_config put adservices fledge_select_ads_kill_switch false; adb shell device_config put adservices fledge_on_device_auction_kill_switch false; adb shell device_config put adservices fledge_auction_server_kill_switch false; adb shell "device_config put adservices disable_fledge_enrollment_check true";  adb shell device_config put adservices ppapi_app_allow_list '\*'; adb shell device_config put adservices fledge_auction_server_overall_timeout_ms 60000;
  1. Redémarrez l'appareil.
  2. Ignorez les clés d'enchères de l'appareil pour qu'elles pointent vers votre serveur de clés d'enchères. Il est important d'effectuer cette étape avant de tenter de lancer une mise aux enchères afin d'éviter la mise en cache de clés incorrectes.

Services d'enchères et de mise aux enchères

Pour configurer les serveurs d'enchères et de mise aux enchères, consultez la documentation de configuration en libre-service.

Ce document explique comment configurer les serveurs propres à l'acheteur, car aucune modification n'est requise pour les vendeurs.

Conditions préalables

Avant de déployer une pile de services d'enchères et de mise aux enchères, la technologie publicitaire de l'acheteur doit :

  • Assurez-vous qu'elle a déployé son propre service de récupération d'annonces TEE (voir la section correspondante).
  • Assurez-vous que la technologie publicitaire dispose de toutes les UDF nécessaires (prepareDataForAdRetrieval, generateBid, reportWin, HandleRequest) définies et hébergées.

Il est également utile de comprendre le fonctionnement des enchères protégées avec l'API Protected Audience avec les enchères et mises aux enchères, mais ce n'est pas obligatoire.

Configuration Terraform

Pour utiliser les signaux d'application protégés, les technologies publicitaires doivent :

  • Prendre en charge des signaux d'application protégés dans les enchères et mises aux enchères.
  • Fournir les points de terminaison d'URL à partir desquels les nouvelles UDF pour prepareDataForAdRetrieval, generateBid et reportWin peuvent être extraites.

En outre, ce guide part du principe que les technologies publicitaires qui souhaitent utiliser les enchères et mises aux enchères pour le remarketing doivent définir comme d'habitude tous les indicateurs de configuration existants pour les enchères de remarketing.

Configuration des technologies publicitaires des acheteurs

En prenant ce fichier de démonstration comme exemple, les acheteurs doivent définir les indicateurs suivants :

  • Activer les signaux d'application protégés : permet de collecter les données des signaux d'application protégés.
  • URL des signaux d'application protégés : définit les URL des serveurs de signaux d'application protégés.

Les technologies publicitaires doivent remplacer les URL appropriées dans les espaces réservés pour les champs suivants :

module "buyer" {
  # ... More config here.

  runtime_flags = {
    # ... More config here.

    ENABLE_PROTECTED_APP_SIGNALS                  = "true"
    PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS = "60000"
    TEE_AD_RETRIEVAL_KV_SERVER_ADDR               = "<service mesh address of the instance>"
    AD_RETRIEVAL_TIMEOUT_MS                       = "60000"
    BUYER_CODE_FETCH_CONFIG                       = <<EOF
    {
        "protectedAppSignalsBiddingJsUrl": "<URL to Protected App Signals generateBid UDF>",
        "urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
        "urlFetchPeriodMs": 13000000,
        "prepareDataForAdsRetrievalJsUrl": "<URL to the UDF>"
    }
    EOF

  }  # runtime_flags

}  # Module "buyer"

Configuration des technologies publicitaires des vendeurs

En prenant ce fichier démo comme exemple, les vendeurs doivent définir les indicateurs suivants. (Remarque : Seule la configuration liée aux signaux d'application protégés est mise en surbrillance ici.) Les technologies publicitaires doivent s'assurer de remplacer les URL appropriées dans les espaces réservés :

module "seller" {
  # ... More config here.

  runtime_flags = {
    # ... More config here.

    ENABLE_PROTECTED_APP_SIGNALS                  = "true"

    SELLER_CODE_FETCH_CONFIG                           = <<EOF
  {
    "urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
    "urlFetchPeriodMs": 13000000,
    "protectedAppSignalsBuyerReportWinJsUrls": {"<Buyer Domain>": "URL to reportWin UDF"}
  }
  EOF

  }  # runtime_flags

}  # Module "seller"

Services de valeurs-clés et de récupération d'annonces

Selon les stratégies choisies pour permettre la récupération des annonces, le système nécessitera le déploiement d'une ou deux instances du service KV. Nous utiliserons Ad Retrieval Server pour désigner l'instance KV utilisée pour la récupération d'annonces basée sur le TEE et KV Lookup Server pour désigner l'instance, qui permet la récupération basée sur un chemin d'accès contextuel.

Dans les deux cas, le déploiement des serveurs suit la documentation disponible dans GitHub du serveur KV. La différence entre les deux cas est que le cas de recherche fonctionne directement et sans configuration supplémentaire, tandis que la récupération nécessite le déploiement de la fonction HandleRequest définie par l'utilisateur pour mettre en œuvre la logique de récupération. Pour en savoir plus, consultez le guide d'intégration des serveurs KV. Notez que les enchères et la mise aux enchères s'attendent à ce que les deux services soient déployés dans le même maillage de services que le service d'enchères.

Exemple de configuration

Prenons le scénario suivant : à l'aide de l'API Protected App Signals, une technologie publicitaire stocke des signaux pertinents en fonction de l'utilisation de l'application par l'utilisateur. Dans notre exemple, les signaux qui représentent les achats via plusieurs applications sont stockés. Lors d'une enchère, les signaux chiffrés sont collectés et transmis à des enchères protégées qui se déroulent dans les enchères et mises aux enchères. Les UDF de l'acheteur exécutées dans les enchères et les mises aux enchères utilisent ces signaux pour extraire les annonces candidates et calculer une enchère.

[Acheteur] Exemples de signaux

Ajoute un signal avec une clé de 0 et une valeur de 1.

{
  "put": {
    "AA==": "AQ=="
  },
  "update_encoder": {
    "action": "REGISTER",
    "endpoint": "https://example.com/example_script"
  }
}

Ajoute un signal avec une clé de 1 et une valeur de 2.

{
  "put": {
    "AQ==": "Ag=="
  },
  "update_encoder": {
    "action": "REGISTER",
    "endpoint": "https://example.com/example_script"
  }
}

[Acheteur] Exemple d'utilisation d'encodeSignals

Encode chaque signal en deux octets, le premier octet étant le premier octet de la clé du signal et le deuxième octet étant le premier octet de la valeur du signal.

function encodeSignals(signals, maxSize) {
  // if there are no signals don't write a payload
  if (signals.size === 0) {
      return {};
  }

  let result = new Uint8Array(signals.size * 2);
  let index = 0;
  
  for (const [key, values] of signals.entries()) {
    result[index++] = key[0];
    result[index++] = values[0].signal_value[0];
  }
  
  return { 'status': 0, 'results': result};
}

[Acheteur] Exemple d'utilisation de prepareDataForAdRetrieval

/**
 * `encodedOnDeviceSignals` is a Uint8Array and would contain
 * the app signals emanating from device. For purpose of the
 * demo, in our sample example, we assume that device is sending
 * the signals with pair of bytes formatted as following:
 * "<id><In app spending>". Where id corresponds to an ad category
 * that user uses on device, and the in app spending is a measure
 * of how much money the user has spent in this app category
 * previously. In our example, id of 0 will correspond to a
 * fitness ad category and a non-zero id will correspond to
 * food app category -- though this info will be useful
 * later in the B&A pipeline.
 *
 * Returns a JSON object indicating what type of ad(s) may be
 * most relevant to the user. In a real setup ad techs might
 * want to decode the signals as part of this script.
 *
 * Note: This example script makes use of only encoded device signals
 * but adtech can take other signals into account as well to prepare
 * the data that will be useful down stream for ad retrieval and
 * bid generation. The max length of the app signals used in this
 * sample example is arbitrarily limited to 4 bytes.
 */
function prepareDataForAdRetrieval(encodedOnDeviceSignals,
                                   encodedOnDeviceSignalsVersion,
                                   sellerAuctionSignals,
                                   contextualSignals) {
  if (encodedOnDeviceSignals.length === 0 || encodedOnDeviceSignals.length > 4 ||
      encodedOnDeviceSignals.length % 2 !== 0) {
     throw "Expected encoded signals length to be an even number in (0, 4]";
  }

  var preparedDataForAdRetrieval = {};
  for (var i = 0; i < encodedOnDeviceSignals.length; i += 2) {
    preparedDataForAdRetrieval[encodedOnDeviceSignals[i]] = encodedOnDeviceSignals[i + 1];
  }
  return preparedDataForAdRetrieval;
}

[Acheteurs] Exemple de fonction définie par l'utilisateur pour la récupération d'annonces

Dans notre exemple, le serveur de récupération d'annonces envoie des métadonnées (c'est-à-dire l'identifiant de chaque annonce de cet exemple, mais il peut contenir d'autres données pour chacune des annonces susceptibles de vous aider à générer des enchères ultérieurement) pour chacune des k premières annonces candidates.

function HandleRequest(requestMetadata, protectedSignals, deviceMetadata,
                      contextualSignals) {
 return "[{\"adId\":\"0\"},{\"adId\":\"1\"}]"

[Acheteurs] Exemple d'utilisation de generateBid

/**
 * This script receives the data returned by the ad retrieval service
 * in the `ads` argument. This argument is supposed to contain all
 * the Protected App Signals related ads and the metadata obtained from the retrieval
 * service.
 *
 * `preparedDataForAdRetrieval` argument contains the data returned
 * from the `prepareDataForAdRetrieval` UDF.
 *
 * This script is responsible for generating bids for the ads
 * collected from the retrieval service and ad techs can decide to
 * run a small inference model as part of this script in order to
 * decide the best bid given all the signals available to them.
 *
 * For the purpose of the demo, this sample script assumes
 * that ad retrieval service has sent us most relevant ads for the
 * user and this scripts decides on the ad render URL as well as
 * what value to bid for each ad based on the previously decoded
 * device signals. For simplicity sake, this script only considers
 * 2 types of app categories i.e. fitness and food.
 *
 * Note: Only one bid is returned among all the
 * input ad candidates.
 */
function generateBid(ads, sellerAuctionSignals, buyerSignals, preparedDataForAdRetrieval) {
  if (ads === null) {
    console.log("No ads obtained from the ad retrieval service")
    return {};
  }     
        
  const kFitnessAd = "0";
  const kFoodAd = "1";
  const kBuyerDomain = "https://buyer-domain.com";
        
  let resultingBid = 0;
  let resultingRender = kBuyerDomain + "/no-ad";
  for (let i = 0 ; i < ads.length; ++i) {
    let render = "";
    let bid = 0;
    switch (ads[i].adId) {
      case kFitnessAd:
        render = kBuyerDomain + "/get-fitness-app";
        bid = preparedDataForAdRetrieval[kFitnessAd];
        break;
      case kFoodAd:
        render = kBuyerDomain + "/get-fastfood-app";
        bid = preparedDataForAdRetrieval[kFoodAd];
        break;
      default:
        console.log("Unknown ad category");
        render = kBuyerDomain + "/no-ad";
        break;
    }
    console.log("Existing bid: " + resultingBid + ", incoming candidate bid: " + bid);
    if (bid > resultingBid) {
      resultingBid = bid;
      resultingRender = render;
    }
  }
  return {"render": resultingRender, "bid": resultingBid};
}

[Acheteurs] Exemple d'utilisation de reportWin

L'UDF reportWin indique à l'acheteur qu'il a remporté l'enchère.

function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                                       buyerReportingSignals, directFromSellerSignals,
                                       egressPayload,
                                       temporaryUnlimitedEgressPayload) {
  sendReportTo("https://buyer-controlled-domain.com/");
  registerAdBeacon({"clickEvent":"https://buyer-controlled-domain.com/clickEvent"});
  return;
}

[Vendeur] Configuration du serveur de KV

Les vendeurs doivent configurer un serveur de KV pour les signaux d'évaluation afin qu'un mappage entre les URL de rendu des annonces et les signaux d'évaluation correspondants soit disponible. Par exemple : si https:/buyer-domain.com/get-fitness-app et https:/buyer-domain.com/get-fastfood-app doivent être renvoyé par l'acheteur, le vendeur peut avoir l'exemple suivant de réponse des signaux d'évaluation lorsqu'il est interrogé par le SFE à l'aide d'un GET sur https://key-value-server-endpoint.com?client_type=1&renderUrls=<render-url-returned-by-the-buyer> :

{
   "renderUrls" : {
      "https:/buyer-domain.com/get-fitness-app" : [
         "1",
         "2"
      ],
      "https:/buyer-domain.com/get-fastfood-app" : [
         "3",
         "4"
      ]
   }
}

[Vendeur] Exemple d'utilisation de scoreAd

/**
 * This module generates a random desirability score for the Protected App
 * Signals ad in this example. In a production deployment,
 * however, the sellers would want to use all the available signals to generate
 * a score for the ad.
 */
function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

function scoreAd(adMetadata, bid, auctionConfig,
                                   trustedScoringSignals, deviceSignals,
                                   directFromSellerSignals) {
  return {
    "desirability": getRandomInt(10000),
    "allowComponentAuction": false
  };
}

[Vendeur] Exemple d'utilisation de reportResult

function reportResult(auctionConfig, sellerReportingSignals, directFromSellerSignals){
  let signalsForWinner = {};
    sendReportTo("https://seller-controlled-domain.com");
    registerAdBeacon({"clickEvent":
                    "https://seller-controlled-domain.com/clickEvent"});
    return signalsForWinner;
}

Application exemple

Pour illustrer comment l'API peut être utilisée pour créer une application qui utilise un flux simple (comme décrit ci-dessus), nous avons créé un exemple d'application Protected App Signals, disponible dans cet exemple de dépôt.