Integrare la piattaforma con B&A come venditore

I servizi di offerte e aste sono un insieme di servizi per acquirenti e venditori di annunci che vengono eseguiti in un ambiente di esecuzione sicuro (TEE) per facilitare un'asta Protected Audience (PA). Questa guida per gli sviluppatori spiega come un venditore può eseguire l'integrazione con un'asta di pubblicità per app di Chrome per la vendita di prodotti e servizi.

Procedura dettagliata

Flusso di integrazione del venditore in cui il codice JavaScript riceve il payload dell'asta B&A inviato a SAS e SAS inoltra la richiesta al frontend del venditore (SFE). SFE restituisce il risultato che SAS deve inoltrare al browser e il codice JavaScript del venditore chiama runAdAuction

I passaggi possono essere riassunti come segue:

  1. Chiama getInterestGroupAdAuctionData() per recuperare il payload criptato dal browser
  2. Chiama fetch('https://your-ad-server.example') e invia la richiesta di asta unificata con il payload criptato al tuo fornitore SAS
  3. Chiama l'operazione SelectAd() dell'SFE dal tuo SAS per eseguire l'asta B&A
  4. Restituire il risultato dell'asta B&A alla pagina insieme all'hash della risposta
  5. Chiama runAdAuction() nel browser per eseguire un'asta PA con un solo venditore, in modalità mista o con più venditori e passa il risultato dell'asta B&A lato server alla chiamata

Ottenere dati criptati sulle aste di annunci

Lo stesso diagramma della procedura dettagliata con il primo passaggio evidenziato, ovvero quando il codice JavaScript del venditore chiama getInterestGroupAdAuctionData

Per ottenere i dati necessari per eseguire l'asta B&A lato server, il codice JavaScript del venditore nella pagina del publisher chiama navigator.getInterestGroupAdAuctionData().

const adAuctionData = await navigator.getInterestGroupAdAuctionData({
  seller: 'https://ssp.example', // Required
  requestSize: 51200,
  coordinatorOrigin: 'https://publickeyservice.pa.gcp.privacysandboxservices.com/',
  perBuyerConfig: {
    'https://dsp-x.example': { targetSize: 8192 },
    'https://dsp-y.example': { targetSize: 8192 }
  }
});

const { requestId, request } = adAuctionData;
Campo Descrizione
seller Required. Origine del venditore che gestisce l'asta. Questo valore deve corrispondere al valore seller nella chiamata runAdAuction() in un secondo momento.
requestSize Facoltativo. Imposta la dimensione massima del payload di tutti i dati dell'acquirente. Per saperne di più, consulta la sezione relativa alle dimensioni delle richieste della spiegazione.
perBuyerConfig Facoltativo. Imposta le configurazioni per ogni acquirente e controlla anche quali acquirenti partecipano all'asta B&A.

Se le origini acquirente sono elencate in perBuyerConfig, nel payload vengono inclusi solo i dati del gruppo di interesse dell'acquirente. Se in perBuyerConfig non sono elencati acquirenti, nel payload sono inclusi tutti i gruppi di interesse dell'utente.

targetSize Facoltativo se è impostato requestSize. Obbligatorio se in perBuyerConfig è impostata un'origine acquirente, ma requestSize non è impostato.

Imposta la dimensione massima del payload dei dati dell'acquirente. Per saperne di più, consulta la sezione relativa alle dimensioni delle richieste della spiegazione.

coordinatorOrigin Facoltativo, ma verrà richiesto in un secondo momento. Se non viene impostato, il valore predefinito è https://publickeyservice.pa.gcp.privacysandboxservices.com.

Imposta il coordinatore da utilizzare per recuperare la chiave per la crittografia del payload. Per saperne di più, consulta la sezione relativa al coordinatore della spiegazione.

Quando viene effettuata la chiamata, il browser legge i gruppi di interesse degli acquirenti elencati in perBuyerConfig e cripta i dati dell'acquirente. Questi dati dell'acquirente contengono informazioni su più siti da utilizzare per le offerte e non possono essere decriptati al di fuori di un TEE. Per l'ottimizzazione del payload, nel payload sono inclusi solo il nome del gruppo di interesse, le chiavi degli indicatori di aste attendibili e gli indicatori del browser.

Nell'oggetto dati dell'asta dell'annuncio restituito dalla chiamata getInterestGroupAdAuctionData(), sono disponibili la stringa requestId e l'array di byte request criptato.

Screenshot di Chrome DevTools che mostra la richiesta e l'ID richiesta disponibili nei dati dell'asta di annunci

La stringa requestId viene utilizzata in un secondo momento quando viene chiamato runAdAuction() per completare l'asta nel browser. Il payload request criptato viene inviato al servizio di annunci del venditore nell'ambito della richiesta di asta unificata.

Per un esempio di questa chiamata, consulta il codice JavaScript del venditore dell'app di test locale.

Invia la richiesta di asta unificata a SAS

Lo stesso diagramma della procedura dettagliata con il secondo passaggio evidenziato, ovvero quando il codice JavaScript del venditore invia una richiesta di asta unificata al SAS

Una richiesta di asta unificata è una richiesta che contiene il payload dell'asta contestuale in testo normale e il payload dell'asta B&A PA. Il payload dell'asta B&A PA è costituito dai dati request criptati generati dal browser nella chiamata getInterestGroupAdAuctionData(). Questa richiesta viene inviata a SAS, dove vengono orchestrate l'asta contestuale e l'asta B&A di PA.

fetch('https://ssp.example/ad-auction', {
  method: 'POST',
  adAuctionHeaders: true,
  body: JSON.stringify({
    contextualAuctionPayload: { somePayload },
    protectedAudienceAuctionPayload: encodeBinaryData(request)
  }),
});

Per inviare la richiesta a SAS, viene effettuata una chiamata fetch() dalla pagina:

  • La chiamata deve includere l'opzione adAuctionHeaders: true, che indica al browser di verificare la risposta di questa chiamata in un secondo momento quando viene chiamato runAdAuction() per completare l'asta nel browser.
  • L'origine della richiesta di recupero deve corrispondere all'origine seller fornita alle chiamate getInterestGroupAdAuctionData() e runAdAuction().

Il corpo della chiamata contiene:

  1. Il payload dell'asta contestuale in testo non cifrato da utilizzare da SAS per eseguire l'asta contestuale.
  2. Il payload dell'asta Protected Audience criptato da inviare a SFE da SAS per eseguire l'asta B&A lato server.

Per un esempio di questa chiamata, consulta il codice JavaScript del venditore dell'app di test locale.

Codifica e decodifica Base64

Il payload request criptato restituito dalla chiamata getInterestGroupAdAuctionData() è un'istanza di Uint8Array, un tipo di dati che JSON non può gestire. Per inviare l'array di byte in formato JSON, puoi applicare una codifica base64 ai dati binari per convertirli in una stringa.

L'API browser JavaScript fornisce le funzioni atob() e btoa() su window che convertono i dati binari in stringa ASCII con codifica base64 e viceversa. (atob significa da ASCII a binario e btoa significa da binario ad ASCII).

La chiamata a btoa() per codificare i dati binari in una stringa con codifica base64 ha il seguente aspetto:

function encodeBinaryData(data) {
  return btoa(String.fromCharCode.apply(null, data));
}

Anche il risultato dell'asta B&A criptato restituito da questa chiamata fetch è in una codifica base64, quindi devi decodificarlo nuovamente in dati binari. Chiama atob() per decodificare la stringa ASCII con codifica base64 in dati binari:

function decodeBase64String(base64string) {
  return new Uint8Array(
    atob(base64string)
      .split('')
      .map((char) => char.charCodeAt(0))
  );
}

Tuttavia, una stringa con codifica base64 è in genere superiore del 33% rispetto ai dati originali. Per un ulteriore miglioramento della latenza, utilizza un formato diverso da JSON per inviare i dati binari.

Chiama SelectAd di SFE per eseguire l'asta B&A

Lo stesso diagramma della procedura dettagliata con il terzo passaggio evidenziato, ovvero quando la SAS invia una richiesta SelectAd all'SFE e quest'ultimo esegue un'asta B&A

Una volta che il servizio di annunci del venditore riceve la richiesta di asta unificata dalla pagina, viene eseguita prima l'asta contestuale per determinare il vincitore dell'asta contestuale e raccogliere gli indicatori dell'acquirente da passare all'asta B2B della PA. Quindi, l'asta B&A viene avviata chiamando l'operazione SelectAd dell'SFE da SAS con il payload della richiesta. Tieni presente che alcuni metadati della richiesta della pagina a SAS nel passaggio 2 vengono inoltrati a SFE.

Crea il payload SelectAdRequest

Il payload della richiesta della chiamata SelectAd può essere costruito come segue:

const selectAdRequest = {
  auction_config: {
    seller: 'https://ssp.example',
    auction_signals: '{"testKey":"someValue"}',
    seller_signals: '{"testKey":"someValue"}',
    buyer_list: [
      'https://dsp-x.example',
      'https://dsp-y.example',
    ],
    per_buyer_config: {
      'https://dsp-x.example': { buyer_signals: '{"testKey": "someValue"}' },
      'https://dsp-y.example': { buyer_signals: '{"testKey": "someValue"}' },
    },
  },
  client_type: 'CLIENT_TYPE_BROWSER',
  protected_auction_ciphertext: decodeBase64string(request)
};

Tieni presente che se i dati dell'asta degli annunci criptati del browser sono stati codificati in base64, devono essere decodificati nuovamente in dati binari se la richiesta all'SFE viene inviata utilizzando gRPC. Se la richiesta viene inviata utilizzando HTTP, i dati delle aste pubblicitarie criptati possono rimanere nel formato codificato base64.

Per visualizzare altri campi definiti nella richiesta SelectAd, consulta la definizione del proto di SelectAdRequest.

Impostare il campo del venditore di primo livello per le aste con modalità mista e componenti

Se il venditore pubblica un'asta in modalità mista o partecipa come venditore di componenti a un'asta multi-venditore, il campo top_level_seller deve essere definito nella richiesta.

Se sei un venditore in modalità mista, il valore top_level_seller è la tua origine:

const selectAdRequest = {
  auction_config: {
    seller: 'https://ssp-mix.example',
    top_level_seller: 'https://ssp-mix.example',
  }
}

Se sei un venditore di componenti, il valore top_level_seller è il venditore di primo livello dell'asta multi-venditore:

const selectAdRequest = {
  auction_config: {
    seller: 'https://ssp-mix.example',
    top_level_seller: 'https://ssp-top.example',
  }
}

Chiama il numero SelectAd di SFE

La chiamata a SFE da SAS può essere effettuata con gRPC o HTTP.

Chiamata gRPC

La richiesta gRPC a SFE è simile alla seguente se utilizzi Express in Node con un client gRPC:

import grpc from '@grpc/grpc-js';

// Load proto definition
const packageDefinition = protoLoader.loadSync(protoPath, { keepCase: true, enums: String });

const {
  privacy_sandbox: {
    bidding_auction_servers: { SellerFrontEnd }
  }
} = grpc.loadPackageDefinition(packageDefinition);

// Instantiate the gRPC client
const sfeGrpcClient = new SellerFrontEnd('192.168.84.104:50067', grpc.credentials.createInsecure());

// Send SelectAd request
sfeGrpcClient.selectAd(selectAdRequest,(error, response) => {
  // Handle SFE response
});

La definizione di proto per il client SFE è disponibile nel repository dell'app di test locale.

Chiamata HTTP al proxy Envoy

La richiesta POST HTTP a SFE viene inviata al percorso /v1/selectAd e ha il seguente aspetto:

fetch('https://ssp-ba.example/sfe/v1/selectAd', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(selectAdRequest),
});

Inoltra i metadati

I seguenti metadati della chiamata della pagina a SAS devono essere aggiunti alla chiamata SelectAd di SAS a SFE:

Quando i metadati vengono inviati a SFE, devono utilizzare le seguenti intestazioni non standard perché gRPC potrebbe modificare l'intestazione User-Agent:

  • X-Accept-Language
  • X-User-Agent
  • X-BnA-Client-IP

Di seguito è riportato un esempio di come i metadati possono essere inoltrati utilizzando Express in Node con un client gRPC:

sellerAdService.post('/ad-auction', (req, res) => {
  // …
  const metadata = new grpc.Metadata();
  metadata.add('X-Accept-Language', req.header('Accept-Language'));
  metadata.add('X-User-Agent', req.header('User-Agent'));
  metadata.add('X-BnA-Client-IP', req.ip);

  const sfeGrpcClient = createSfeGrpcClient();
  sfeGrpcClient.selectAd(selectAdRequest, metadata, callbackFn);
})

Di seguito è riportato un esempio di come i metadati possono essere inoltrati utilizzando una chiamata HTTP:

sellerAdService.post('/ad-auction', (req, res) => {
  // …
  fetch('https://ssp-ba.example/sfe/v1/selectAd', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Accept-Language': req.header('Accept-Language'),
      'X-User-Agent': req.header('User-Agent'),
      'X-BnA-Client-IP': req.ip
    },
    body: JSON.stringify(selectAdRequest)
  });
})

Asta multi-venditore orchestrata dal server

Se sei un venditore di primo livello che gestisce un'asta multi-venditore orchestrata dal server, la chiamata GetComponentAuctionCiphertexts viene effettuata all'SFE prima della chiamata SelectAd. La risposta contiene i payload dell'asta dei componenti criptati di nuovo che vengono inviati ai servizi pubblicitari del venditore del componente. I risultati dell'asta degli annunci B&A del componente restituito vengono forniti alla chiamata SelectAd dell'entità SFE del venditore di primo livello.

Per saperne di più, consulta la guida ai venditori multipla su GitHub.

Ripristinare il risultato dell'asta B&A nella pagina

Lo stesso diagramma della procedura dettagliata con il quarto passaggio evidenziato, ovvero quando SAS invia il risultato dell'asta di SelectAd al browser

Al termine dell'asta B&A, il risultato dell'asta criptato viene restituito a SAS, che risponde alla richiesta di asta unificata dalla pagina del passaggio 2 con il risultato dell'asta criptato. Nella risposta SAS alla pagina, l'hash SHA-256 con codifica base64url del risultato dell'asta criptata è impostato nell'intestazione di risposta Ad-Auction-Result. Questo hash viene utilizzato dal browser per verificare il payload al termine dell'asta nel client.

La creazione di un hash SHA-256 con codifica base64 è simile al seguente in Node:

import { createHash } from 'crypto';

createHash('sha256')
  .update(binaryData, 'base64')
  .digest('base64url');

L'attacco dell'hash nell'intestazione della risposta e il ritorno del risultato dell'asta alla pagina sono i seguenti:

sellerAdService.post('/ad-auction', (req, res) => {
  // …
  sfeGrpcClient.selectAd(selectAdRequest, metadata, (error, response) => {
    const { auction_result_ciphertext } = response;

    const ciphertextShaHash = createHash('sha256')
      .update(auction_result_ciphertext, 'base64')
      .digest('base64url');

    res.set('Ad-Auction-Result', ciphertextShaHash);

    res.json({
      protectedAudienceAuctionResult: encodeBinaryData(auction_result_ciphertext),
      contextualAuctionResult: getContextualAuctionResult()
    });
  });
})

Poiché si tratta di una risposta alla richiesta di asta unificata effettuata dalla pagina nel passaggio 2, nella risposta è incluso anche il risultato dell'asta contestuale.

È possibile includere più hash in Ad-Auction-Result ripetendo l'intestazione o separando gli hash. Le seguenti due intestazioni di risposta sono equivalenti:

Ad-Auction-Result: ungWv48Bz-pBQUDeXa4iI7ADYaOWF3qctBD_YfIAFa0=,9UTB-u-WshX66Xqz5DNCpEK9z-x5oCS5SXvgyeoRB1k=
Ad-Auction-Result: ungWv48Bz-pBQUDeXa4iI7ADYaOWF3qctBD_YfIAFa0=
Ad-Auction-Result: 9UTB-u-WshX66Xqz5DNCpEK9z-x5oCS5SXvgyeoRB1k=

Per un esempio di questa chiamata, consulta il codice del server del venditore dell'app di test locale.

Chiama runAdAuction() per completare l'asta

Lo stesso diagramma della procedura dettagliata con il quinto passaggio evidenziato, ovvero quando il codice JavaScript lato client esegue l'asta e fornisce la risposta del server

La risposta all'asta unificata restituita da SAS include il risultato dell'asta B&A criptato. Questo payload viene passato alla chiamata runAdAuction() per completare l'asta nel browser. Anche il valore requestId della chiamata getInterestGroupAdAuctionData() nel passaggio 1 viene passato all'asta.

// Get the encrypted ad auction data (Step #1)
const { requestId, request } = navigator.getInterestGroupAdAuctionData(adAuctionDataConfig)

// Send unified auction request (Step #2)
const response = await fetch('https://ssp-ba.example/ad-auction', {
  method: 'POST',
  body: JSON.stringify({
    adAuctionRequest: encodeBinaryData(request),
  }),
});

const { protectedAudienceAuctionResult } = await response.json();

// Finish the auction in the browser
await navigator.runAdAuction({
  // pass in "requestId" and "protectedAudienceAuctionResult"
  // the config structure will differ based on the auction configuration
});

La struttura della configurazione dell'asta passata alla chiamata runAdAuction() varia in base alla configurazione dell'asta scelta dal venditore.

Asta con un solo venditore

Per eseguire un'asta B&A con un solo venditore, la configurazione dell'asta della chiamata runAdAuction() è costruita come segue:

await navigator.runAdAuction({
  seller: 'https://ssp-ba.example',
  requestId,
  serverResponse: protectedAudienceAuctionResult,
});

Il campo requestId accetta il requestId restituito dalla chiamata getInterestGroupAdAuctionData(). Il campo serverResponse accetta un array di byte dell'asta B&A eseguita nel passaggio 3.

Per un esempio di questa chiamata, consulta il codice JavaScript del venditore dell'app di test locale.

Asta mista

Per eseguire un'asta B&A in modalità mista a cui possono partecipare sia gli acquirenti on-device sia quelli B&A, la configurazione dell'asta della chiamata runAdAuction() è costruita come segue:

await navigator.runAdAuction({
  seller: 'https://ssp-mix.example',
  decisionLogicURL: 'https://ssp-mix.example/score-ad.js',
  componentAuctions: [
    // B&A auction result
    {
      seller: 'https://ssp-mix.example',
      requestId,
      serverResponse: protectedAudienceAuctionResult,
    },
    // On-device auction config
    {
      seller: 'https://ssp-mix.example',
      decisionLogicURL: 'https://ssp-mix.example/on-device-score-ad.js',
      interestGroupBuyers: [
        'https://dsp-a.example', // On-device buyer
        'https://dsp-a.example', // On-device buyer
      ],
    },
  ]
});

Per facilitare un'asta in modalità mista, il risultato dell'asta B&A e la configurazione dell'asta sul dispositivo vengono passati al campo componentAuctions. In un'asta in modalità mista, il valore seller è lo stesso sia per la configurazione di primo livello sia per le configurazioni dei componenti.

Per un esempio di questa chiamata, consulta il codice JavaScript del venditore dell'app di test locale.

Asta multi-venditore

Se sei un venditore di primo livello che gestisce un'asta multi-venditore orchestrata per dispositivo, ogni venditore componente invia il risultato dell'asta B&A e le configurazioni dell'asta sul dispositivo.

await navigator.runAdAuction({
  seller: 'https://ssp-top.example',
  decisionLogicURL: 'https://ssp-top.example/score-ad.js',
  componentAuctions: [
    // SSP-BA's B&A-only auction result
    {
      seller: 'https://ssp-ba.example',
      requestId: 'g8312cb2-da2d-4e9b-80e6-e13dec2a581c',
      serverResponse: Uint8Array(560) [193, 120, 4, ] // Encrypted B&A auction result
    },
    // SSP-MIX's B&A auction result
    {
      seller: 'https://ssp-mix.example',
      requestId: 'f5135cb2-da2d-4e9b-80e6-e13dec2a581c',
      serverResponse: Uint8Array(560) [133, 20, 4, ] // Encrypted B&A auction result
    }.
    // SSP-MIX's on-device auction config
    {
      seller: 'https://ssp-mix.example',
      interestGroupBuyers: ['https://dsp-a.example', 'https://dsp-b.example'],
      decisionLogicURL: 'https://ssp-mix.example/score-ad.js',
    }
    // SSP-OD's on-device auction config
    {
      seller: 'https://ssp-od.example',
      interestGroupBuyers: ['https://dsp-a.example', 'https://dsp-b.example'],
      decisionLogicURL: 'https://ssp-od.example/score-ad.js',
    }
  ]
})

Per un esempio di questa chiamata, consulta il codice JavaScript del venditore dell'app di test locale.

Passaggi successivi

Dopo aver letto questa guida, puoi procedere nel seguente modo:

Scopri di più

Domande?