Integracja z B&A jako sprzedawca

Usługi określania stawek i aukcji to zestaw usług dla kupujących i sprzedających reklamy, które działają w zaufanym środowisku wykonawczym (TEE), aby ułatwić przeprowadzenie aukcji z użyciem Protected Audience (PA). Z tego przewodnika dla deweloperów dowiesz się, jak sprzedawca może zintegrować się z aukcją Chrome PA na potrzeby B&A.

Przewodnik

Przepływ integracji sprzedawcy, w którym kod JavaScript pobiera ładunek aukcji B&A, który jest wysyłany do SAS, a SAS przekazuje żądanie do interfejsu sprzedawcy (SFE). SFE zwraca wynik, który SAS powinien przekazać do przeglądarki, a kod JavaScript sprzedawcy wywołuje funkcję runAdAuction.

Można je podsumować w ten sposób:

  1. Wywołaj funkcję getInterestGroupAdAuctionData(), aby pobrać zaszyfrowany ładunek z przeglądarki.
  2. Zadzwoń pod numer fetch('https://your-ad-server.example') i wyślij do SAS prośbę o przeprowadzenie aukcji ujednoliconej z zaszyfrowanym ładunkiem.
  3. Wywołaj operację SelectAd() SFE z SAS, aby przeprowadzić aukcję B&A
  4. Zwróć do strony wynik aukcji B&A wraz z haszem odpowiedzi.
  5. Wywołaj w przeglądarce funkcję runAdAuction(), aby przeprowadzić aukcję PA dla jednego sprzedawcy, w trybie mieszanym lub dla wielu sprzedawców, i przekaż do wywołania wynik aukcji B&A po stronie serwera.

Pobieranie zaszyfrowanych danych aukcji reklam

Ten sam diagram z wyróżnionym pierwszym krokiem, w którym kod JavaScript sprzedawcy wywołuje funkcję getInterestGroupAdAuctionData.

Aby uzyskać dane potrzebne do przeprowadzenia aukcji B&A po stronie serwera, kod JavaScript sprzedawcy na stronie wydawcy wywołuje 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;
Pole Opis
seller Wymagany. Kraj pochodzenia sprzedawcy prowadzącego aukcję. Ta wartość musi być zgodna z wartością seller w późniejszym wywołaniu runAdAuction().
requestSize Opcjonalnie. Ustawia maksymalny rozmiar ładunku wszystkich danych kupującego. Więcej informacji znajdziesz w sekcji rozmiar żądania w wyjaśnieniu.
perBuyerConfig Opcjonalnie. Ustawia konfiguracje dla każdego kupującego, a także określa, którzy kupujący biorą udział w aukcji typu „kup i zastosuj”.

Jeśli w perBuyerConfig wymienione są pochodzenia kupujących, w ładunku uwzględniane są tylko dane o grupach zainteresowań tych kupujących. Jeśli w sekcji perBuyerConfig nie ma żadnych kupujących, w ładunku zostaną uwzględnione wszystkie grupy zainteresowań użytkownika.

targetSize Opcjonalny, jeśli ustawiona jest wartość requestSize. Wymagany, jeśli w parametrze perBuyerConfig ustawiono pochodzenie kupującego, ale parametr requestSize nie jest ustawiony.

Określa maksymalny rozmiar ładunku danych tego kupującego. Więcej informacji znajdziesz w sekcji rozmiar żądania w wyjaśnieniu.

coordinatorOrigin Opcjonalny, ale w przyszłości będzie wymagany. Jeśli nie zostanie ustawiony, domyślna wartość to https://publickeyservice.pa.gcp.privacysandboxservices.com.

Ustawia koordynatora, który będzie używany do pobierania klucza do szyfrowania ładunku. Więcej informacji znajdziesz w sekcji koordynator w wyjaśnieniu.

Gdy wywołanie zostanie wykonane, przeglądarka odczytuje grupy zainteresowań kupujących wymienionych w perBuyerConfig i szyfruje dane kupujących. Dane kupującego zawierają informacje z różnych witryn, które mają być używane na potrzeby określania stawek. Nie można ich odszyfrować poza środowiskiem TEE. W przypadku optymalizacji ładunku w ładunku uwzględniane są tylko nazwa grupy zainteresowań, klucze zaufanych sygnałów do ustalania stawek i sygnały z przeglądarki.

W obiekcie danych aukcji reklam, który jest zwracany przez wywołanie getInterestGroupAdAuctionData(), dostępne są ciąg znaków requestId i zaszyfrowana tablica bajtów request.

Zrzut ekranu Narzędzi deweloperskich w Chrome, na którym widać, że w danych aukcji reklamowych dostępne są żądanie i jego identyfikator.

Ciąg znaków requestId jest używany później, gdy wywoływana jest funkcja runAdAuction(), aby zakończyć aukcję w przeglądarce. Zaszyfrowany ładunek request jest wysyłany do usługi reklamowej sprzedawcy w ramach żądania zunifikowanej aukcji.

Przykład tego wywołania znajdziesz w kodzie JavaScript sprzedawcy w lokalnej aplikacji testowej.

Wysyłanie do SAS żądania zunifikowanej aukcji

Ten sam schemat z wyróżnionym drugim krokiem, w którym kod JavaScript sprzedawcy wysyła do SAS ujednolicone żądanie aukcji.

Ujednolicone żądanie aukcji to żądanie, które zawiera ładunek aukcji kontekstowej w formacie zwykłego tekstu oraz ładunek aukcji PA B&A. Ładunek aukcji PA B&A to zaszyfrowane dane request wygenerowane przez przeglądarkę w wywołaniu getInterestGroupAdAuctionData(). To żądanie jest wysyłane do SAS, gdzie odbywają się aukcje kontekstowe i aukcje PA B&A.

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

Aby wysłać żądanie do SAS, ze strony jest wykonywane wywołanie fetch():

  • Wywołanie musi zawierać opcję adAuctionHeaders: true, która informuje przeglądarkę, że ma zweryfikować odpowiedź na to wywołanie w późniejszym czasie, gdy zostanie wywołana funkcja runAdAuction(), aby zakończyć aukcję w przeglądarce.
  • Źródło żądania pobierania musi być zgodne ze źródłem seller podanym w wywołaniach getInterestGroupAdAuctionData()runAdAuction().

Treść wywołania zawiera:

  1. Tekstowy ładunek aukcji kontekstowej, który ma być używany przez SAS do przeprowadzania aukcji kontekstowej.
  2. Zaszyfrowany ładunek aukcji Protected Audience API, który SAS ma wysłać do SFE, aby przeprowadzić aukcję B&A po stronie serwera.

Przykład tego wywołania znajdziesz w kodzie JavaScript sprzedawcy w lokalnej aplikacji testowej.

Kodowanie i dekodowanie Base64

Zaszyfrowany ładunek request zwracany przez wywołanie getInterestGroupAdAuctionData() jest instancją Uint8Array, czyli typu danych, którego JSON nie może obsługiwać. Aby wysłać tablicę bajtów w formacie JSON, możesz zastosować kodowanie base64 do danych binarnych, aby przekonwertować je na ciąg tekstowy.

Interfejs API JavaScript w przeglądarce udostępnia funkcje atob()btoa() w obiekcie window, które konwertują dane binarne na ciąg znaków ASCII zakodowany w formacie base64 i odwrotnie. (atob oznacza konwersję z ASCII na format binarny, a btoa – z formatu binarnego na ASCII).

Wywołanie funkcji btoa() w celu zakodowania danych binarnych w ciąg tekstowy z kodowaniem Base64 wygląda tak:

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

Zaszyfrowany wynik aukcji B&A zwrócony przez wywołanie fetch jest również zakodowany w formacie base64, więc musisz go zdekodować z powrotem do danych binarnych. Wywołaj funkcję atob(), aby zdekodować ciąg ASCII zakodowany w formacie base64 na dane binarne:

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

Ciąg tekstowy zakodowany w formacie base64 jest zwykle o około 33% większy niż oryginalne dane. Jeśli chcesz jeszcze bardziej zmniejszyć opóźnienie, do przesyłania danych binarnych użyj formatu innego niż JSON.

Wywołaj funkcję SelectAd SFE, aby przeprowadzić aukcję B&A.

Ten sam diagram z wyróżnionym trzecim krokiem, w którym SAS wysyła do SFE żądanie SelectAd, a SFE przeprowadza aukcję B&A.

Gdy Usługa reklam sprzedawcy otrzyma z strony żądanie ujednoliconej aukcji, najpierw przeprowadzi aukcję kontekstową, aby wyłonić jej zwycięzcę i zebrać sygnały kupującego, które zostaną przekazane do aukcji PA B&A. Następnie aukcja B&A jest inicjowana przez wywołanie operacji SelectAd SFE z SAS z ładunkiem żądania. Pamiętaj, że niektóre metadane z żądania strony do SAS w kroku 2 są przekazywane do SFE.

Utwórz ładunek SelectAdRequest

Ładunek żądania wywołania SelectAd można utworzyć w ten sposób:

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

Pamiętaj, że jeśli zaszyfrowane dane aukcji reklam z przeglądarki zostały zakodowane w formacie base64, należy je zdekodować z powrotem do danych binarnych, jeśli żądanie do SFE jest wysyłane przy użyciu gRPC. Jeśli żądanie jest wysyłane za pomocą protokołu HTTP, zaszyfrowane dane aukcji reklam mogą pozostać w formie zakodowanej w formacie base64.

Aby zobaczyć inne pola zdefiniowane w żądaniu SelectAd, zapoznaj się z definicją protokołu SelectAdRequest.

Ustawianie pola sprzedawcy najwyższego poziomu w przypadku aukcji w trybie mieszanym i aukcji komponentowych

Jeśli sprzedawca prowadzi aukcję w trybie mieszanym lub uczestniczy w aukcji wielu sprzedawców jako sprzedawca komponentów, w żądaniu musi być zdefiniowane pole top_level_seller.

Jeśli jesteś sprzedawcą w trybie mieszanym, wartość top_level_seller to Twój punkt początkowy:

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

Jeśli jesteś sprzedawcą komponentów, wartość top_level_seller to sprzedawca najwyższego poziomu na aukcji wielu sprzedawców:

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

Zadzwoń pod numer SelectAd SFE

Połączenie z SFE z SAS można nawiązać za pomocą gRPC lub HTTP.

Wywołanie gRPC

Żądanie gRPC do SFE wygląda tak, jak poniżej, przy użyciu Express w Node z klientem 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
});

Definicję protokołu klienta SFE znajdziesz w  repozytorium aplikacji do testowania lokalnego.

Wywołanie HTTP do serwera proxy Envoy

Żądanie HTTP POST do SFE jest wysyłane do /v1/selectAdścieżki i wygląda tak:

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

Przekazywanie metadanych

Do wywołania SFE z poziomu SAS należy dodać te metadane z wywołania SAS na stronie:SelectAd

Gdy metadane są wysyłane do SFE, muszą używać tych niestandardowych nagłówków, ponieważ gRPC może zmienić nagłówek User-Agent:

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

Poniżej znajdziesz przykład przekazywania metadanych za pomocą ExpressNodeklientem 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);
})

Oto przykład przekazywania metadanych za pomocą wywołania 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)
  });
})

Aukcja wielu sprzedawców koordynowana przez serwer

Jeśli jesteś sprzedawcą najwyższego poziomu, który prowadzi aukcję wielu sprzedawców koordynowaną przez serwer, wywołanie GetComponentAuctionCiphertexts jest kierowane do SFE przed wywołaniem SelectAd. Odpowiedź zawiera ponownie zaszyfrowane ładunki aukcji komponentów, które są wysyłane do usług reklamowych sprzedawcy komponentów. Wyniki aukcji reklamy B&A zwróconego komponentu są przekazywane do wywołania SelectAd w SFE sprzedawcy najwyższego poziomu.

Więcej informacji znajdziesz w wyjaśnieniu dotyczącym wielu sprzedawców w GitHubie.

Zwróć wynik aukcji B&A na stronę

Ten sam diagram z wyróżnionym czwartym krokiem, w którym SAS wysyła wynik aukcji SelectAd z powrotem do przeglądarki

Po zakończeniu aukcji B&A zaszyfrowany wynik aukcji jest zwracany do SAS, a SAS odpowiada na żądanie ujednoliconej aukcji ze strony w kroku 2, przesyłając zaszyfrowany wynik aukcji. W odpowiedzi SAS na stronę w nagłówku odpowiedzi Ad-Auction-Result ustawiany jest zakodowany w formacie base64url hash SHA-256 zaszyfrowanego wyniku aukcji. Ten skrót jest używany przez przeglądarkę do weryfikowania ładunku po zakończeniu aukcji na urządzeniu klienta.

Tworzenie identyfikatora SHA-256 z kodowaniem base64 w Node wygląda tak:

import { createHash } from 'crypto';

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

Dołączenie skrótu w nagłówku odpowiedzi i zwrócenie wyniku aukcji na stronę wygląda tak:

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

Jest to odpowiedź na żądanie aukcji ujednoliconej wysłane ze strony w kroku 2, więc w odpowiedzi uwzględniono też wynik aukcji kontekstowej.

W nagłówku Ad-Auction-Result można umieścić wiele hashów, powtarzając nagłówek lub rozdzielając hashe. Te 2 nagłówki odpowiedzi są równoważne:

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

Przykład tego wywołania znajdziesz w kodzie serwera sprzedawcy aplikacji do testowania lokalnego.

Zadzwoń pod numer runAdAuction(), aby zakończyć aukcję

Ten sam diagram z wyróżnionym piątym krokiem, w którym kod JavaScript po stronie klienta przeprowadza aukcję i dostarcza odpowiedź serwera.

Odpowiedź z ujednoliconych aukcji zwrócona z SAS zawiera zaszyfrowany wynik aukcji B&A. Ten ładunek jest przekazywany do wywołania runAdAuction(), aby zakończyć aukcję w przeglądarce. Wartość requestId z wywołania getInterestGroupAdAuctionData()kroku 1 jest też przekazywana na aukcję.

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

Struktura konfiguracji aukcji przekazywanej do wywołania runAdAuction() różni się w zależności od konfiguracji aukcji wybranej przez sprzedawcę.

Aukcja pojedynczego sprzedawcy

W przypadku przeprowadzania aukcji B&A jednego sprzedawcy konfiguracja aukcji wywołania runAdAuction() jest tworzona w ten sposób:

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

Pole requestId akceptuje wartość requestId zwróconą przez wywołanie getInterestGroupAdAuctionData(). Pole serverResponse akceptuje tablicę bajtów z aukcji B&A, która została przeprowadzona w kroku 3.

Przykład tego wywołania znajdziesz w kodzie JavaScript sprzedawcy w lokalnej aplikacji testowej.

Aukcja w trybie mieszanym

W przypadku aukcji w trybie mieszanym, w której mogą brać udział kupujący korzystający z urządzenia i kupujący korzystający z funkcji B&A, konfiguracja aukcji w wywołaniu runAdAuction() wygląda tak:

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

Aby ułatwić przeprowadzenie aukcji w trybie mieszanym, wynik aukcji B&A i konfiguracja aukcji na urządzeniu są przekazywane do pola componentAuctions. W aukcji w trybie mieszanym wartość seller jest taka sama w przypadku konfiguracji najwyższego poziomu i konfiguracji komponentów.

Przykład tego wywołania znajdziesz w kodzie JavaScript sprzedawcy w lokalnej aplikacji testowej.

Aukcja wielu sprzedawców

Jeśli jesteś sprzedawcą najwyższego poziomu, który przeprowadza aukcję wielu sprzedawców koordynowaną przez urządzenie, każdy sprzedawca komponentów przesyła wynik aukcji B&A i konfiguracje aukcji na urządzeniu.

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',
    }
  ]
})

Przykład tego wywołania znajdziesz w kodzie JavaScript sprzedawcy w lokalnej aplikacji testowej.

Dalsze kroki

Po przeczytaniu tego przewodnika możesz wykonać te czynności:

Więcej informacji

Masz pytania?