Guida per gli sviluppatori degli indicatori di app protetti

Per aiutare gli sviluppatori a iniziare a fare esperimenti con l'API Protected App Signals, questo documento descrive tutte le API all'interno dell'interfaccia API, illustra come configurare un ambiente di test e fornisce esempi di configurazione e script.

Cronologia delle versioni

Gennaio 2024

Prima release della guida per gli sviluppatori che supporta la release MVP di PAS

Marzo 2024

Modifiche all'API per supportare la release M-2024-05 dell'API Android e la release di aprile 2024 dei componenti lato server. Modifiche più importanti:

  • Sono stati aggiunti dettagli sulle autorizzazioni richieste per l'API on-device
  • Sono stati aggiunti dettagli sulla gestione della quota degli indicatori sul dispositivo
  • Firma generateBid aggiornata con modifiche relative al recupero e al supporto di Egress per gli annunci contestuali
  • Documentazione aggiornata di reportWin, incluso il supporto in uscita
  • Aggiornamento della documentazione dell'API Ad Retrieval che rimuove il supporto per il recupero degli annunci BYOS e che documenta l'UDF di recupero degli annunci

Panoramica dell'API

La piattaforma dell'API Protected Signals include diversi sottoinsiemi di API su sistemi diversi:

  • API Android:
    • API Signal Curation, composta da:
    • API Update Signals
    • API Signals Encoding
    • API di supporto per l'asta protetta: da utilizzare dagli SDK per eseguire l'asta protetta sui server di asta e offerta utilizzando gli indicatori delle app protette.
  • API lato server:
    • API Protected Auction: una serie di script JS in esecuzione nei server di offerte e aste. Questa API consente a venditori e acquirenti di scrivere la logica per implementare l'asta protetta.
    • API Ad Retrieval: è responsabile della fornitura di un elenco di annunci candidati in base alle informazioni contestuali e sugli utenti rese disponibili al server di offerte dell'acquirente.

Client Android

Sul lato client, la piattaforma Protected App Signals è composta da tre API diverse:

  • Aggiorna indicatori: un'API di sistema Android per abilitare la selezione degli indicatori sul dispositivo.
  • Codifica degli indicatori: un'API JavaScript per preparare gli indicatori da inviare al server durante l'asta.
  • Supporto per le aste protette: un'API per supportare l'esecuzione di un'asta protetta sui server di asta e di offerta. Questa API non è specifica per gli indicatori delle app protette e viene utilizzata anche per supportare le aste per l'API Protected Audience.

API Update Signals

L'API UpdateSignals consente alle ad tech di registrare indicatori relativi a utenti e app per conto di un acquirente. L'API funziona su un modello di delega. L'utente chiamante fornisce un URI da cui il framework recupera gli indicatori corrispondenti e la logica per codificarli da utilizzare nell'asta.

L'API richiede l'autorizzazione android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS.

L'API updateSignals() recupererà un oggetto JSON dall'URI che descrive quali indicatori aggiungere o rimuovere e come prepararli per l'asta.

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 piattaforma invia una richiesta https all'URI fornito nella richiesta per recuperare gli aggiornamenti degli indicatori. Oltre agli aggiornamenti degli indicatori, la risposta può includere un endpoint che ospita la logica di codifica per la conversione degli indicatori non elaborati in un payload codificato. Gli aggiornamenti degli indicatori devono essere in formato JSON e possono avere le seguenti chiavi:

Le chiavi di primo livello dell'oggetto JSON devono corrispondere a uno dei cinque comandi:

chiave

Descrizione

put

Aggiunge un nuovo indicatore, sovrascrivendo gli indicatori esistenti con la stessa chiave. Il valore

per questo è un oggetto JSON in cui le chiavi sono stringhe base 64 corrispondenti alla chiave da inserire e i valori sono stringhe base 64 corrispondenti al valore da inserire.

append

Aggiunge uno o più nuovi indicatori a una serie temporale di indicatori, rimuovendo quelli meno recenti

gli indicatori per fare spazio ai nuovi se le dimensioni della serie superano il valore massimo specificato. Il valore è un oggetto JSON in cui le chiavi sono stringhe base 64 corrispondenti alla chiave a cui aggiungere e i valori sono oggetti con due campi: "values" e "maxSignals".

"values": un elenco di stringhe base 64 corrispondenti ai valori degli indicatori da aggiungere alla serie temporale.

"maxSignals": il numero massimo di valori consentiti in questa serie temporale. Se

il numero corrente di indicatori associati alla chiave supera il valore maxSignals, gli indicatori più vecchi verranno rimossi. Tieni presente che puoi aggiungere un elemento a una chiave aggiunta con put. Tieni presente che l'aggiunta di più del numero massimo di valori causerà un errore.

put_if_not_present

Aggiunge un nuovo indicatore solo se non esistono indicatori con la stessa chiave. Il valore è un oggetto JSON in cui le chiavi sono stringhe base 64 corrispondenti alla chiave per la quale eseguire l'operazione PUT e i valori sono stringhe base 64 corrispondenti al valore da inserire.

remove

Rimuove l'indicatore per una chiave. Il valore è un elenco di stringhe base 64 corrispondenti alle chiavi degli indicatori da eliminare.

update_encoder

Fornisce un'azione per aggiornare l'endpoint e un URI che può essere utilizzato

per recuperare una logica di codifica. La chiave secondaria per fornire un'azione di aggiornamento è "action" e il

attualmente supportati è solo "REGISTER", che registrerà l'endpoint dell'encoder se viene fornito per la prima volta o sovrascriverà quello esistente con l'endpoint appena fornito. L'endpoint è obbligatorio per l'azione "REGISTER". La sottochiave per fornire un endpoint dell'encoder è "endpoint" e il valore è l'URI

stringa per l'endpoint.

Una richiesta JSON di esempio è la seguente:

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

Gli indicatori avranno una quota sul dispositivo nell'ordine di 10-15 KB. Una volta superata la quota, PPAPI eliminerà gli indicatori utilizzando una strategia FIFO. La procedura di espulsione consentirà di superare leggermente la quota per brevi intervalli di tempo al fine di ridurre la frequenza delle espulsioni.

API Signals Encoding

Gli acquirenti sono tenuti a fornire una funzione JavaScript da utilizzare per codificare gli indicatori memorizzati sul dispositivo da inviare al server durante l'asta protetta. Gli acquirenti possono fornire questo script aggiungendo l'URL da cui può essere recuperato utilizzando la chiave "update_encoder" in una delle risposte a una richiesta dell'API UpdateSignal. Lo script avrà la seguente firma:

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

Il parametro signals è una mappa dalle chiavi sotto forma di UInt8Array di dimensione 4 a elenchi di oggetti Protected App Signals. Ogni oggetto Protected App Signals ha tre campi:

  • signal_value: un UInt8Array che rappresenta il valore dell'indicatore.
  • creation_time: un numero che rappresenta la data e l'ora di creazione degli indicatori in epoch-secondi.
  • package_name: una stringa che rappresenta il nome del pacchetto che ha creato l'indicatore.

Il parametro maxSize è un numero che descrive la dimensione massima consentita dell'array per l'output.

La funzione deve produrre un oggetto con due campi:

  • status: deve essere 0 se lo script è stato eseguito correttamente.
  • results: deve essere un array di interi senza segno di lunghezza minore o uguale a maxSize. Questo array verrà inviato al server durante le aste e preparato dallo script prepareDataForAdRetrieval.

La codifica fornisce agli esperti di tecnologia pubblicitaria una fase iniziale di creazione di funzionalità, in cui possono eseguire trasformazioni come la compressione degli indicatori non elaborati in versioni concatenate in base alla propria logica personalizzata. Tieni presente che durante un'asta protetta eseguita in ambienti di esecuzione attendibili (TEE), la logica personalizzata della tecnologia pubblicitaria avrà accesso in lettura ai payload degli indicatori generati dalla codifica. La logica personalizzata, nota come funzione definita dall'utente (UDF), in esecuzione nel TEE B&A del compratore avrà accesso in lettura agli indicatori codificati e ad altri indicatori contestuali forniti dall'app del publisher per eseguire la selezione degli annunci (recupero degli annunci e offerta).

Codifica degli indicatori

Ogni ora, gli acquirenti che hanno fornito la logica di codifica con gli indicatori registrati vedranno codificati i propri indicatori in un payload dell'asta.L'array di byte per il payload dell'asta viene mantenuto sul dispositivo, è criptato e verrà raccolto dai venditori come parte dei dati di selezione degli annunci da includere nell'ambito di un'asta protetta. Per i test, puoi attivare questa codifica al di fuori della sua cadenza oraria eseguendo il seguente comando:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
Controllo delle versioni della logica dell'encoder

Quando viene effettuata una richiesta per scaricare la logica dell'encoder personalizzato per la tecnologia pubblicitaria, l'endpoint della tecnologia pubblicitaria può rispondere con un numero di versione nelle intestazioni di risposta. Questa versione viene mantenuta insieme alla logica dell'encoder sul dispositivo. Quando gli indicatori non elaborati vengono codificati, il payload codificato viene mantenuto insieme alla versione utilizzata per la codifica. Questa versione viene inviata anche al server B&A durante un'asta protetta, in modo che le tecnologie pubblicitarie possano allineare la logica di offerta e codifica in base alla versione.

Response header for providing encoder version : X_ENCODER_VERSION

API Protected Auction Support

Sul lato del dispositivo, eseguire un'asta per gli indicatori delle app protette è come eseguire un'asta per i segmenti di pubblico protetti.

Servizi di offerte e aste

Le API lato server includono:

  • API Protected Auction: una serie di funzioni JS o UDF che acquirenti e venditori possono implementare nei componenti B&A di loro proprietà per determinare le offerte e la logica dell'asta.
  • API di recupero degli annunci: gli acquirenti possono implementare questa API implementando un endpoint REST che sarà responsabile della fornitura di un insieme di annunci candidati per l'asta Protected App Signal.

API Protected Auction

L'API Protected Auction è composta da API JS o UDF che acquirenti e venditori possono utilizzare per implementare la logica di asta e offerta.

UDF di tecnologia pubblicitaria dell'acquirente
Funzione definita dall'utente prepareDataForAdRetrieval

Prima che gli indicatori delle app protette possano essere utilizzati per recuperare gli annunci candidati dal servizio di recupero annunci TEE, gli acquirenti devono decodificare e preparare gli indicatori delle app protette e altri dati forniti dal venditore. L'output della UDF prepareDataForAdRetrieval degli acquirenti viene passato al servizio di recupero degli annunci per recuperare i k annunci candidati migliori per l'asta.

// 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 {};
}
Funzione definita dall'utente generateBid

Dopo aver restituito i k annunci candidati migliori, questi vengono passati alla logica delle offerte personalizzate dell'acquirente, generateBid UDF:

// 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>
    };
}

L'output di questa funzione è un'offerta singola per un annuncio candidato, rappresentata come un valore JSON equivalente a ProtectedAppSignalsAdWithBidMetadata. La funzione può anche restituire due array che verranno poi passati a reportWin per abilitare l'addestramento del modello. Per ulteriori dettagli sull'esportazione e sull'addestramento del modello, consulta la sezione relativa ai report nella spiegazione di PAS.

Funzione definita dall'utente reportWin

Al termine di un'asta, il servizio di asta genera URL di generazione di report per gli acquirenti e registra i beacon utilizzando la funzione definita dall'utente reportWin (la stessa funzione reportWin utilizzata per Protected Audiences). Il dispositivo invierà un ping al client una volta che l'annuncio è stato visualizzato. La firma di questo metodo è quasi uguale a quella della versione Protected Audience, ad eccezione di due parametri aggiuntivi, egressPayload e temporaryUnlimitedEgressPayload, che vengono utilizzati per attivare l'addestramento del modello e vengono compilati con i risultati di generateBid.

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals,
                   egressPayload, temporaryUnlimitedEgressPayload) {
  // ...
}
UDF di tecnologia pubblicitaria del venditore
Funzione definita dall'utente scoreAd

Questa UDF viene utilizzata dai venditori per selezionare l'annuncio ricevuto dagli acquirenti che vincerà l'asta.

function scoreAd(adMetadata, bid, auctionConfig,
                 trustedScoringSignals, bid_metadata) {
  // ...
  return {desirability: desirabilityScoreForThisAd,
              allowComponentAuction: true_or_false};
}
Funzione definita dall'utente reportResult

Questa UDF consente al venditore di generare (eventualmente) report a livello di evento con le informazioni relative all'annuncio vincente.

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

API Ad Retrieval

Nella release MVP , il servizio di recupero degli annunci sarà un servizio gestito e ospitato dall'acquirente e il servizio di offerta recupera gli annunci candidati da questo servizio. A partire da aprile 2024, il server di recupero degli annunci deve essere eseguito in un ambiente di esecuzione sicuro (TEE) e esporrà un'interfaccia GRPC/proto. Le società di ad tech devono configurare questo server e fornire il relativo URL nell'ambito del deployment dello stack B&A. Un'implementazione di questo servizio in esecuzione nel TEE è disponibile nel repository GitHub di Privacy Sandbox e nel resto della documentazione si presume che questo sia il codice utilizzato nel deployment.

A partire da aprile 2024, le versioni B&A supportano il recupero degli annunci basati su percorso contestuale. In questo caso, il server di aste riceverà un elenco di identificativi annunci inviati dal server RTB durante la parte contestuale dell'asta. Gli identificatori verranno inviati a un server KV TEE per recuperare tutte le informazioni relative agli annunci da utilizzare durante la fase di offerta (ad es. ad-render-url, metadati e incorporamenti degli annunci da utilizzare nella selezione dei migliori k). Questo secondo percorso non richiede alcuna logica specifica per essere disegnato, pertanto qui illustreremo solo come configurare il caso d'uso di recupero degli annunci basato su TEE.

Funzione definita dall'utente getCandidateAds
function getCandidateAds(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals, contextualAdIds,) {
    return adsMetadataString;
}

Dove:

  • requestMetadata: JSON. Metadati del server per richiesta all'UDF. Per il momento vuoto.
  • preparedDataForAdRetrieval: i contenuti di questo campo dipendono dalla strategia di recupero degli annunci. In caso di recupero di annunci contestuali, questo parametro conterrà gli indicatori non elaborati provenienti dal dispositivo e trasmessi dal servizio di offerta. In caso di recupero di annunci TEE utilizzando il server di recupero annunci, questo parametro conterrà il risultato della UDF prepareDataForAdRetrieval. Nota: in questa fase, gli indicatori Protected App Signals verrebbero decodificati e decriptati.
  • deviceMetadata: oggetto JSON contenente i metadati del dispositivo inoltrati dal servizio pubblicitario del venditore. Per ulteriori dettagli, consulta la documentazione di B&A.
    • X-Accept-Language: la lingua utilizzata sul dispositivo.
    • X-User-Agent: user agent utilizzato sul dispositivo.
    • X-BnA-Client-IP: indirizzo IP del dispositivo.
  • contextualSignals: stringa arbitraria proveniente dal server di offerte contestuali gestito dalla stessa DSP. La UDF dovrebbe essere in grado di decodificare la stringa e utilizzarla. Gli indicatori contestuali possono contenere qualsiasi informazione, ad esempio informazioni sulla versione del modello di ML per l'embedding protetto passato utilizzando gli indicatori delle app protette.
  • contextualAdIds: oggetto JSON contenente un elenco facoltativo di ID annuncio.

La UDF deve restituire una stringa in caso di esito positivo. La stringa viene restituita al server di aste, che la passa alla UDF generateBid. Anche se la stringa può essere semplicemente una stringa, molto probabilmente dovrebbe essere un oggetto serializzato il cui schema è definito autonomamente da ogni tecnologia pubblicitaria. Non sono previsti vincoli per lo schema, a condizione che la logica generateBid dell'ad tech possa riconoscere e utilizzare la stringa.

Configurare il sistema per lo sviluppo

Android

Per configurare l'ambiente di sviluppo Android, devi eseguire i seguenti passaggi:

  1. Crea un emulatore (opzione preferita) o un dispositivo fisico su cui è in esecuzione l'immagine Developer Preview 10
  2. Esegui questo comando:
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity

Quindi, seleziona l'opzione mostrata per dare il consenso agli annunci suggeriti dall'app.

  1. Esegui il comando seguente per abilitare le API pertinenti. Potresti dover eseguire di nuovo questa operazione di tanto in tanto, poiché la configurazione predefinita di disattivato verrà sincronizzata periodicamente.
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. Riavvia il dispositivo.
  2. Sostituisci le chiavi dell'asta del dispositivo in modo che rimandino al tuo server delle chiavi dell'asta. È importante eseguire questo passaggio prima di tentare di eseguire un'asta per evitare che le chiavi errate vengano memorizzate nella cache.

Servizi di offerte e aste

Per configurare i server B&A, consulta la documentazione di configurazione self-service.

Questo documento si concentrerà su come configurare i server specifici dell'acquirente, poiché non sono necessarie modifiche per i venditori.

Prerequisiti

Prima di implementare uno stack di servizi B&A, la tecnologia pubblicitaria dell'acquirente deve:

  • Assicurati che abbiano implementato il proprio servizio di recupero degli annunci TEE (consulta la sezione pertinente).
  • Assicurati che l'ad tech disponga di tutte le UDF necessarie (prepareDataForAdRetrieval, generateBid, reportWin, getCandidateAds) definite e ospitate.

È utile anche comprendere il funzionamento dell'asta protetta con Protected Audience con B&A, ma non è obbligatorio.

Configurazione di Terraform

Per utilizzare Protected App Signals, le tecnologie pubblicitarie devono:

  • Attiva il supporto di Protected App Signals in B&A.
  • Fornisci gli endpoint URL da cui è possibile recuperare le nuove funzioni UDF per prepareDataForAdRetrieval, generateBid e reportWin.

Inoltre, questa guida presuppone che le tecnologie pubblicitarie che vogliono utilizzare B&A per il remarketing continueranno a impostare tutti i flag di configurazione esistenti per l'asta di remarketing come di consueto.

Configurazione della tecnologia pubblicitaria dell'acquirente

Utilizzando questo file di esempio, gli acquirenti devono impostare i seguenti flag:

  • Attiva Protected App Signals: opzione attivata per raccogliere i dati di Protected App Signals.
  • URL Protected App Signals: impostato sugli URL dei server Protected App Signals.

I professionisti della tecnologia pubblicitaria devono sostituire gli URL corretti nei segnaposto per i seguenti campi:

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"

Configurazione della tecnologia pubblicitaria del venditore

Utilizzando questo file demo come esempio, i venditori devono impostare i seguenti flag. (Nota: qui è evidenziata solo la configurazione relativa a Protected App Signals). Le tecnologie pubblicitarie devono assicurarsi di sostituire gli URL corretti nei segnaposto:

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"

Servizi di recupero di KV e annunci

A seconda delle strategie scelte per supportare il recupero degli annunci, il sistema richiederà il deployment di una o due istanze del servizio KV. Faremo riferimento all'istanza KV utilizzata per il recupero degli annunci basato su TEE come Ad Retrieval Server e all'istanza per supportare il recupero basato sul percorso contestuale come KV Lookup Server.

In entrambi i casi, il deployment dei server segue la documentazione disponibile nel repository GitHub del server KV. La differenza tra i due casi è che la ricerca funziona immediatamente senza alcuna configurazione aggiuntiva, mentre la ricerca del recupero richiede il deployment della UDF getCandidateAds per implementare la logica di recupero. Per maggiori dettagli, consulta la guida all'onboarding del server KV. Tieni presente che B&A si aspetta che entrambi i servizi vengano impiegati nello stesso service mesh del servizio di offerta.

Configurazione di esempio

Considera il seguente scenario: utilizzando l'API Protected App Signals, una tecnologia pubblicitaria memorizza indicatori pertinenti in base all'utilizzo delle app da parte degli utenti. Nel nostro esempio vengono memorizzati indicatori che rappresentano gli acquisti in-app di diverse app. Durante un'asta, gli indicatori criptati vengono raccolti e trasmessi a un'asta protetta eseguita in B&A. Le UDF dell'acquirente in esecuzione in B&A utilizzano gli indicatori per recuperare gli annunci candidati e calcolare un'offerta.

[Acquirente] Esempi di indicatori

Aggiunge un indicatore con una chiave pari a 0 e un valore pari a 1.

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

Aggiunge un indicatore con una chiave pari a 1 e un valore pari a 2.

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

[Acquirente] Esempio di codifica di indicatori

Codifica ogni segnale in due byte, il primo dei quali è il primo byte della chiave del segnale e il secondo è il primo byte del valore del segnale.

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

[Acquirente] Esempio di 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;
}

[Acquirenti] Funzione UDF di recupero di annunci di esempio

Nel nostro esempio, il server di recupero degli annunci invia i metadati (ovvero l'ID per ogni annuncio in questo esempio, ma può contenere altri dati per ciascun annuncio che possono essere utili per la generazione delle offerte in un secondo momento) per ciascuno dei k annunci candidati migliori.

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

[Buyers] Esempio di 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};
}

[Buyers] Esempio di reportWin

La UDF reportWin comunica all'acquirente che ha vinto l'asta.

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

[Venditore] Configurazione del server KV

I venditori devono configurare un server KV di indicatori di punteggio in modo che sia disponibile una mappatura dagli URL di rendering degli annunci agli indicatori di punteggio corrispondenti, ad esempio: se https:/buyer-domain.com/get-fitness-app e https:/buyer-domain.com/get-fastfood-app dovessero essere restituiti dall'acquirente, il venditore può avere il seguente esempio di risposta agli indicatori di punteggio quando viene eseguita una query dall'SFE utilizzando un GET su 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"
      ]
   }
}

Esempio di scoreAd [Venditore]

/**
 * 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
  };
}

Esempio di reportResult [Venditore]

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

App di esempio

Come esempio di come l'API può essere utilizzata per creare un'app che utilizza un semplice flusso come descritto sopra, abbiamo creato un'app di esempio Protected App Signals che si trova in questo repository di esempi.