Guida per gli sviluppatori degli indicatori di app protetti

Per aiutare gli sviluppatori a iniziare a sperimentare con l'API Protected App Signals, questo documento descrive tutte le API all'interno della piattaforma API, descrive nel dettaglio come configurare un ambiente di test e fornisce esempi di configurazione e script.

Cronologia delle versioni

Gennaio 2024

Prima versione della guida per gli sviluppatori che supporta il rilascio dell'MVP 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 di indicatori on-device
  • Firma generateBid aggiornata con modifiche relative al recupero contestuale degli annunci e al supporto in uscita
  • Documentazione aggiornata per reportWin, che include il supporto del traffico in uscita
  • Aggiorna la documentazione dell'API Ad Retrieval, rimuovendo il supporto per il recupero di annunci BYOS e documentando la funzione definita dall'utente per il recupero degli annunci

Panoramica dell'API

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

  • API Android:
    • L'API Signal Curation, composta da:
    • Aggiorna l'API Signals
    • API Signals Encoding
    • API Protected Asta Supporto: da utilizzare dagli SDK per eseguire l'asta protetta sui server delle offerte e delle aste (B&A) utilizzando indicatori dell'app protetti.
  • API lato server:
    • API Protected Asta: una serie di script JS in esecuzione nei server delle offerte e delle aste. Questa API consente ai venditori e agli 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 messe a disposizione del server di offerta dell'acquirente.

Client Android

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

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

Aggiorna l'API Signals

L'API Update Signals consente agli ad tech di registrare indicatori relativi a utenti e app per conto di un acquirente. L'API opera su un modello di delega. Il 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. Insieme agli aggiornamenti degli indicatori, la risposta può includere un endpoint che ospita la logica di codifica per convertire i segnali non elaborati in payload codificato. Gli aggiornamenti degli indicatori dovrebbero essere in formato JSON e possono avere le seguenti chiavi:

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

chiave

Descrizione

put

Aggiunge un nuovo indicatore, sovrascrivendo tutti quelli esistenti con la stessa chiave. Il valore

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

append

Aggiunge un nuovo indicatore a una serie temporale di indicatori, rimuovendo quelli meno recenti

indicatori per fare spazio a quelli nuovi se la dimensione della serie supera il limite massimo. Il valore è un oggetto JSON in cui le chiavi sono stringhe di base 64 corrispondenti alla chiave da aggiungere e i valori sono oggetti con due campi: "values" e "maxSignals".

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

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

il numero corrente di indicatori associati alla chiave supera maxSignals, gli indicatori meno recenti verranno rimossi. Tieni presente che puoi aggiungere elementi a una chiave aggiunta tramite put. Tieni presente che l'aggiunta di un numero di valori superiore al numero massimo causerà un errore.

put_if_not_present

Aggiunge un nuovo indicatore solo se non esistono indicatori esistenti con la stessa chiave. Il valore è un oggetto JSON in cui le chiavi sono stringhe di base 64 corrispondenti alla chiave da inserire e i valori sono stringhe di base 64 corrispondenti al valore da mettere.

remove

Rimuove il segnale per una chiave. Il valore è un elenco di stringhe in base 64 corrispondenti alle chiavi dei segnali che devono essere eliminate.

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 è "azione" e la

attualmente supportati è solo "REGISTER", che registrerà l'endpoint del codificatore se fornito per la prima volta o sovrascriverà quello esistente con il nuovo endpoint fornito. Per l'azione "REGISTER" è necessario specificare l'endpoint.La chiave secondaria per fornire un endpoint del codificatore è "endpoint" e il valore è l'URI

per l'endpoint.

Una richiesta JSON di esempio potrebbe essere 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 dell'ordine di 10-15 kB. Una volta superata la quota, PPAPI rimuoverà gli indicatori utilizzando una strategia FIFO. Il processo di rimozione consentirà un leggero superamento della quota per brevi intervalli di tempo, in modo da ridurre la frequenza delle rimozioni.

API Signals Encoding

Gli acquirenti devono fornire una funzione Java Script 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 è possibile recuperarlo utilizzando la chiave "update_encoder" in qualsiasi risposta a una richiesta 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 delle chiavi sotto forma di UInt8Arrays 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 l'ora di creazione degli indicatori in secondi epoche.
  • 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 dell'array consentita per l'output.

La funzione dovrebbe restituire un oggetto con due campi:

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

La codifica offre agli ad tech una fase iniziale del feature engineering, in cui possono eseguire trasformazioni come la compressione dei segnali non elaborati in versioni concatenate basate sulla propria logica personalizzata. Tieni presente che, durante un'asta protetta in esecuzione in ambienti di esecuzione attendibili (TEE, Trusted Execution Environments), la logica personalizzata di 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 dell'acquirente, avrà accesso in lettura agli indicatori codificati e ad altri indicatori di contesto forniti dall'app del publisher per eseguire la selezione degli annunci (recupero degli annunci e offerte).

Codifica degli indicatori

Ogni ora, per gli acquirenti che hanno fornito la logica di codifica con i propri indicatori registrati, gli indicatori vengono codificati in un payload dell'asta.L'array di byte per il payload dell'asta è permanente sul dispositivo, criptato e viene raccolto dai venditori come parte dei dati di selezione degli annunci per essere incluso in 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 del codificatore

Quando viene effettuata una richiesta per scaricare la logica di codifica personalizzata dell'ad tech, l'endpoint ad tech può rispondere con un numero di versione nelle intestazioni della risposta. Questa versione è persistente insieme alla logica del codificatore sul dispositivo. Quando i segnali non elaborati vengono codificati, il payload codificato viene mantenuto insieme alla versione utilizzata per la codifica. Questa versione viene anche inviata al server B&A durante un'asta protetta, in modo che i tecnici pubblicitari possano allineare la logica di offerta e codifica in base alla versione.

Response header for providing encoder version : X_ENCODER_VERSION

API Protected Asta Supporto

Per quanto riguarda i dispositivi, eseguire un'asta per gli indicatori di app protetti equivale a eseguire un'asta per segmenti di pubblico protetti.

Servizi di offerte e aste

Le API lato server includono:

  • API Protected Asta: una serie di funzioni JS o funzioni definite dall'utente che acquirenti e venditori possono implementare nei componenti B&A di loro proprietà per determinare le offerte e la logica dell'asta.
  • API Ad Retrieval: gli acquirenti possono implementare questa API implementando un endpoint REST che sarà responsabile di fornire un insieme di annunci candidati per l'asta Protected App Signal.

API Protected Asta

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

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

Prima di poter utilizzare Protected App Signals per recuperare gli annunci candidati dal servizio di recupero degli annunci TEE, gli acquirenti devono decodificare e preparare gli indicatori di app protetti e gli altri dati forniti dal venditore. L'output della funzione definita dall'utente prepareDataForAdRetrieval degli acquirenti viene passato al servizio di recupero degli annunci per recuperare i primi k di annunci candidati per le offerte.

// 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 che vengono restituiti i primi k annunci candidati, questi vengono trasferiti alla logica di 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 è una singola offerta per un candidato dell'annuncio, rappresentata come un 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 sul traffico in uscita e sull'addestramento del modello, consulta la sezione sui report nell'spiegazione PAS)

funzione definita dall'utente reportWin

Al termine dell'asta, il servizio di aste genera URL di report per gli acquirenti e registra i beacon utilizzando la funzione definita dall'utente reportWin (si tratta della stessa funzione reportWin utilizzata per i segmenti di pubblico protetti). Il dispositivo invierà un ping a questo dopo che il client avrà eseguito il rendering dell'annuncio. La firma di questo metodo è quasi uguale alla versione di Protected Audience, ad eccezione dei due parametri aggiuntivi egressPayload e temporaryUnlimitedEgressPayload che vengono utilizzati per abilitare l'addestramento del modello e vengono completati 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 funzione definita dall'utente viene utilizzata dai venditori per selezionare gli annunci ricevuti dagli acquirenti che vinceranno l'asta.

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

Questa funzione definita dall'utente consente al venditore di (alla fine) creare 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à gestito dall'acquirente e ospitato e il servizio di offerte recupera i candidati annuncio da questo servizio. A partire da aprile 2024, il server di recupero degli annunci deve essere eseguito in un ambiente di esecuzione affidabile (Trusted Execution Environment) ed esporterà un'interfaccia GRPC/proto. Le società di ad tech devono configurare questo server e fornire il relativo URL come parte del deployment dello stack B&A. Un'implementazione di questo servizio in esecuzione in TEE è disponibile in GitHub Privacy Sandbox e nella parte restante della documentazione presumiamo che questo sia il codice utilizzato nel deployment.

A partire da aprile 2024, le versioni B&A supportano il recupero degli annunci del percorso contestuale. In questo caso, il server delle offerte riceverà un elenco di identificatori degli annunci inviati dal server RTB durante la parte contestuale dell'asta. Gli identificatori verranno inviati a un server TEE KV per recuperare tutte le informazioni relative agli annunci da utilizzare durante la fase di offerta (ad esempio ad-render-url, metadati e incorporamenti di annunci da utilizzare nella selezione top-k). Questo secondo percorso non richiede il deployment di una logica specifica, quindi documenteremo qui solo come configurare il caso d'uso del recupero degli annunci basato su TEE.

funzione definita dall'utente HandleRequest
function HandleRequest(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals) {
    return adsMetadataString;
}

Dove:

  • requestMetadata: JSON. Metadati del server a livello di richiesta alla funzione definita dall'utente. Per ora vuoto.
  • preparedDataForAdRetrieval: i contenuti di questo campo dipendono dalla strategia di recupero degli annunci. In caso di recupero di un annuncio contestuale, questo parametro conterrà gli indicatori non elaborati provenienti dal dispositivo e trasmessi dal servizio di offerta. In caso di recupero di un annuncio TEE mediante il server di recupero degli annunci, questo parametro conterrà il risultato della funzione definita dall'utente prepareDataForAdRetrieval. Nota: in questa fase i segnali dell'app protetti verranno decodificati e non criptati.
  • 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: 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 delle offerte contestuali gestito dalla stessa DSP. La funzione definita dall'utente dovrebbe essere in grado di decodificare la stringa e utilizzarla. Gli indicatori contestuali possono contenere informazioni quali le informazioni sulla versione del modello ML per l'incorporamento protetto trasmesso utilizzando gli indicatori di app protetti.

Se l'operazione è andata a buon fine, la funzione definita dall'utente dovrebbe restituire una stringa. La stringa viene restituita al server di offerte, che la passa poi alla funzione definita dall'utente generateBid. Anche se la stringa può essere solo una stringa semplice, molto probabilmente deve essere un oggetto serializzato il cui schema è definito da ogni ad tech. Non ci sono vincoli sullo schema, purché la logica generateBid dell'ad tech sia in grado di riconoscere e utilizzare la stringa.

Configura il sistema per lo sviluppo

Android

Per configurare l'ambiente di sviluppo Android, devi:

  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

Dopodiché seleziona l'opzione mostrata per acconsentire agli annunci suggeriti dalle app.

  1. Esegui questo comando per abilitare le API pertinenti. Potrebbe essere necessario eseguire nuovamente questa operazione di tanto in tanto perché la configurazione predefinita dell'opzione disabilitata 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. Esegui l'override delle chiavi d'asta del dispositivo in modo che rimandino al server delle chiavi d'asta. È importante eseguire questo passaggio prima di tentare di eseguire un'asta per evitare che chiavi errate vengano memorizzate nella cache.

Servizi di offerte e aste

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

Questo documento è incentrato su come configurare i server specifici per l'acquirente, in quanto non sono richieste modifiche per i venditori.

Prerequisiti

Prima di implementare uno stack di servizi B&A, l'acquirente ad tech deve:

  • Assicurati di aver implementato il proprio servizio di recupero degli annunci TEE (consulta la sezione pertinente).
  • Assicurati che la tecnologia pubblicitaria abbia tutte le funzioni definite dall'utente necessarie (prepareDataForAdRetrieval, generateBid, reportWin, HandleRequest) definite e ospitate.

Anche una comprensione del funzionamento dell'asta protetta con Protected Audience con B&A sarà utile, ma non obbligatoria.

Configurazione di Terraform

Per usare gli indicatori dell'app protetti, i tecnici pubblicitari devono:

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

Inoltre, questa guida presuppone che gli ad tech che desiderano utilizzare B&A per il remarketing continueranno a impostare tutti i flag di configurazione esistenti per l'asta di remarketing come di consueto.

Configurazione tecnologia pubblicitaria dell'acquirente

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

  • Abilita Protected App Signals: questa opzione è abilitata per raccogliere dati sugli indicatori di app protetti.
  • URL degli indicatori di app protetti: imposta gli URL dei server di Protected App Signals.

I tecnici pubblicitari 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 ad tech del venditore

Utilizzando questo file demo come esempio, i venditori devono impostare i flag seguenti. Nota: qui è evidenziata solo la configurazione relativa a Protected App Signals. I tecnici pubblicitari 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"

KV e servizi di recupero 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. Ci riferiremo all'istanza KV utilizzata per il recupero degli annunci basato su TEE come Ad Retrieval Server e all'istanza per supportare il recupero basato su percorso contestuale come KV Lookup Server.

In entrambi i casi, il deployment dei server segue la documentazione disponibile nell'GitHub del server KV; la differenza tra i due casi è che il caso di ricerca funziona immediatamente senza alcuna configurazione aggiuntiva, mentre quello di recupero richiede il deployment della funzione definita dall'utente HandleRequest per implementare la logica di recupero. Per ulteriori dettagli, consulta la guida all'onboarding del server KV. Tieni presente che B&A si aspetta che il deployment di entrambi i servizi sia eseguito nello stesso mesh di servizi del servizio di offerta.

Configurazione di esempio

Considera il seguente scenario: con l'API Protected App Signals, un ad tech memorizza gli indicatori pertinenti in base all'utilizzo dell'app utente. Nel nostro esempio, vengono memorizzati indicatori che rappresentano gli acquisti in-app da diverse app. Durante un'asta, gli indicatori criptati vengono raccolti e trasferiti a un'asta protetta in esecuzione in B&A. Le funzioni definite dall'utente dell'acquirente pubblicate in B&A utilizzano gli indicatori per recuperare i candidati dell'annuncio 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 di 1 e un valore di 2.

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

Esempio di encodeSignals per [Acquirente]

Codifica ogni segnale in due byte, dove il primo byte è il primo byte della chiave di segnale e il secondo byte è 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 preparazioneDataForAdRetrieval

/**
 * `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] UDF di esempio per il recupero degli annunci

Nel nostro esempio, il server di recupero degli annunci invia metadati (ovvero l'ID di ogni annuncio in questo esempio, ma può contenere altri dati per ciascuno che possono essere utili per generare offerte in seguito) per ciascuno dei primi k candidati.

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

[Acquirenti] Esempio di offerta generato

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

[Acquirenti] Esempio di reportWin

La funzione definita dall'utente reportWin segnala 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 degli indicatori di punteggio in modo che sia disponibile una mappatura dagli URL di rendering dell'annuncio agli indicatori di punteggio corrispondenti, ad esempio: se https:/buyer-domain.com/get-fitness-app e https:/buyer-domain.com/get-fastfood-app devono essere restituiti dall'acquirente, il venditore può avere una risposta agli indicatori di punteggio di esempio nel seguente modo quando viene interrogata 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 annuncio con punteggio di [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 per [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 usa un flusso semplice come descritto sopra, abbiamo creato un'app di esempio di Protected App Signals che puoi trovare in questo repository di esempio.