Integracja z B&A jako sprzedawca

Usługi określania stawek i usługi aukcyjne to zestaw usług dla kupujących i sprzedawców reklam, który działa w zaufanym środowisku wykonawczym (TEE), aby ułatwić przeprowadzanie aukcji Protected Audience (PA). Ten przewodnik dla deweloperów wyjaśnia, jak sprzedawca może zintegrować się z aukcją Chrome PA na potrzeby B&A.

Przewodnik

Proces integracji z usługą sprzedawcy, w którym kod JavaScript otrzymuje ładunek aukcji B&A, który jest wysyłany do SAS, a SAS przekazuje żądanie do interfejsu frontendowego sprzedawcy (SFE). SFE zwraca wynik, który SAS powinien przekazać przeglądarce, a kod JavaScript sprzedawcy wywołuje funkcję runAdAuction.

Proces ten można podsumować w ten sposób:

  1. Zadzwoń do getInterestGroupAdAuctionData(), aby uzyskać zaszyfrowany ładunek z przeglądarki.
  2. Zadzwoń pod numer fetch('https://your-ad-server.example') i prześlij do swojego SAS żądanie z zaszyfrowanym ładunkiem.
  3. Zadzwoń z SAS do SFE, aby wykonać operację SelectAd(), aby przeprowadzić aukcję B&A
  4. Przesyłanie na stronę wyniku aukcji B&A wraz z haszem odpowiedzi
  5. Wywołaj runAdAuction() w przeglądarce, aby przeprowadzić aukcję PA dla pojedynczego sprzedawcy, w trybie mieszanym lub dla wielu sprzedawców i przekazać wynik aukcji B&A po stronie serwera do wywołania.

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 funkcję 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. Źródło sprzedawcy przeprowadzającego aukcję. Ta wartość musi być zgodna z wartością seller w wywołaniu funkcji runAdAuction().
requestSize Opcjonalnie. Określa maksymalny rozmiar ładunku wszystkich danych kupującego. Więcej informacji znajdziesz w sekcji Rozmiar żądania w tym objaśnieniu.
perBuyerConfig Opcjonalnie. Ustawia konfiguracje dla każdego kupującego, a także decyduje, którzy kupujący biorą udział w aukcji B&A.

Jeśli w sekcji perBuyerConfig wymienione są źródła kupujących, w pliku danych uwzględnione są tylko dane o grupach zainteresowań kupujących. Jeśli w polu perBuyerConfig nie ma żadnych kupujących, w danych ładunku są uwzględniane wszystkie grupy zainteresowań użytkownika.

targetSize Opcjonalny, jeśli ustawiono wartość requestSize. Wymagany, jeśli w elementach perBuyerConfigrequestSize nie jest ustawiony parametr perBuyerConfig.

Określa maksymalny rozmiar danych kupującego. Więcej informacji znajdziesz w sekcji Rozmiar żądania w tym objaśnieniu.

coordinatorOrigin Opcjonalne, ale w przyszłości stanie się wymagane. Jeśli nie zostanie ustawiony, domyślna wartość to https://publickeyservice.pa.gcp.privacysandboxservices.com.

Określa koordynatora, którego należy użyć do pobierania klucza do szyfrowania danych. Więcej informacji znajdziesz w sekcji koordynator w tym objaśnieniu.

Gdy wywołanie zostanie wykonane, przeglądarka odczytuje grupy zainteresowań kupujących wymienione w perBuyerConfig i zaszyfruje ich dane. Te dane o kupującym zawierają informacje z różnych witryn, które są używane do określania stawek. Nie można ich odszyfrować poza TEE. W przypadku optymalizacji danych ładunku uwzględniane są tylko nazwa grupy odbiorców, klucze sygnałów zaufanego określania stawek i sygnały przeglądarki.

W obiekcie danych aukcji reklam zwracanym przez wywołanie getInterestGroupAdAuctionData() dostępne są ciąg znaków requestId i zaszyfrowany tablica bajtów request.

Zrzut ekranu z Narzędzi deweloperskich w Chrome, który pokazuje, że żądanie i identyfikator żądania są dostępne w danych aukcji reklamowej

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 do testowania.

Wysyłanie żądania zunifikowanej aukcji do SAS

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

Ujednolicony żądanie aukcji to żądanie zawierające ładunek aukcji kontekstowej w postaci tekstu zwykłego i ładunek aukcji z użyciem parametrów B&A. Ładunek danych aukcji PA B&A to zaszyfrowane dane request wygenerowane przez przeglądarkę w wywołaniu getInterestGroupAdAuctionData(). To żądanie jest wysyłane do SAS, gdzie przeprowadzana jest aukcja kontekstowa i aukcja B&A z użyciem PA.

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

Aby wysłać żądanie do SAS, na stronie:fetch()

  • Wywołanie musi zawierać opcję adAuctionHeaders: true, która sygnalizuje przeglądarce, że należy zweryfikować odpowiedź tego wywołania w późniejszym czasie, gdy wywołanie runAdAuction() zostanie wywołane, 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. Treść ładunku kontekstowej aukcji w postaci zwykłego tekstu, która ma służyć SAS do przeprowadzania aukcji kontekstowej.
  2. Zaszyfrowany ładunek aukcji Protected Audience, który SAS wysyła do SFE w celu przeprowadzenia aukcji B&A po stronie serwera.

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

kodowanie i dekodowanie Base64,

Zaszyfrowany ładunek request zwracany przez wywołanie getInterestGroupAdAuctionData() jest wystąpieniem typu Uint8Array, który jest typem danych, którego nie można przetwarzać w formacie JSON. Aby wysłać tablicę bajtów w formacie JSON, możesz zastosować kodowanie base64 do danych binarnych, aby przekonwertować je na ciąg znaków.

Interfejs JavaScript browser API udostępnia funkcje window atob()btoa(), które konwertują dane binarne na ciągi znaków ASCII z kodowaniem Base64. (atob oznacza konwersję ASCII na binarną, a btoa – binarną na ASCII).

Wywołanie btoa() do zakodowania danych binarnych w ciągu z kodowaniem base64 wygląda tak:

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

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

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

Jednak ciąg tekstowy zakodowany w formacie Base64 jest zwykle o około 33% większy od pierwotnych danych. Jeśli chcesz jeszcze bardziej skrócić czas oczekiwania, przesyłaj dane binarne w formacie innym niż JSON.

Zadzwoń do SFE SelectAd, aby przeprowadzić aukcję B&A

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

Gdy usługa reklamowa sprzedawcy otrzyma żądanie ujednoliconej aukcji od strony, najpierw przeprowadza aukcję kontekstową, aby określić zwycięzcę aukcji kontekstowej i zebrać sygnały kupujących, które zostaną przekazane do aukcji PA B&A. Następnie wywołuje się aukcję B&A, wywołując operację SelectAd w SFE z użytkownikiem SAS i dane żądania. Pamiętaj, że niektóre metadane z zapytania strony do SAS w kroku 2 są przekazywane do SFE.

Utwórz SelectAdRequest.

Ładunek żądania wywołania SelectAd może mieć postać:

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 na dane binarne, jeśli żądanie do SFE jest wysyłane za pomocą gRPC. Jeśli żądanie jest wysyłane za pomocą HTTP, zaszyfrowane dane aukcji reklam mogą pozostać w formie zaszyfrowanej za pomocą kodu base64.

Aby zobaczyć inne pola zdefiniowane w żądaniu SelectAd, zapoznaj się z protodefinicją SelectAdRequest.

Konfigurowanie najwyższego pola sprzedawcy w przypadku aukcji w trybie mieszanym i aukcji komponentów

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

Jeśli jesteś sprzedawcą w trybie mieszanym, wartość top_level_seller to Twoje źródło:

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

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

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

Zadzwoń do zespołu SFE: SelectAd

Wywołanie SFE z SAS może być wykonane za pomocą gRPC lub HTTP.

Wywołanie gRPC

Żądanie gRPC do SFE wygląda tak, jak pokazano 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ę prototypu klienta SFE znajdziesz w  repozytorium lokalnej aplikacji testowej.

Wywołanie HTTP do serwera proxy Envoy

Żądanie HTTP POST do SFE jest wysyłane na ścieżkę /v1/selectAd i ma taki format:

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

Przesyłanie metadanych

Do wywołania SFE w komponencie SelectAd komponentu SAS należy dodać te metadane z wywołania SAS w komponencie strony:

Gdy metadane są wysyłane do SFE, muszą zawierać te niestandardowe nagłówki, ponieważ gRPC może zmienić nagłówek User-Agent:

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

Poniżej znajdziesz przykład tego, jak metadane można przekazywać za pomocą Express w Node z klientami 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);
})

Poniżej znajdziesz przykład tego, jak metadane można przekazywać 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 sterowana po stronie serwera

Jeśli jesteś sprzedawcą najwyższego poziomu i prowadzisz aukcji wielu sprzedawców sterowaną przez serwer, wywołanie GetComponentAuctionCiphertexts jest wysyłane 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. Zwracane wyniki aukcji reklam komponentu B&A są dostarczane do wywołania SelectAd w ramach SFE sprzedawcy najwyższego poziomu.

Aby dowiedzieć się więcej, zapoznaj się z tłumaczeniem na temat bestsellerów na GitHub.

Zwracanie na stronie wyniku aukcji B&A

Ten sam diagram z wyróżnionym 4 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 z jednolitej aukcji z strony w kroku 2, podając zaszyfrowany wynik aukcji. W odpowiedzi SAS na stronie kod SHA-256 zaszyfrowanego wyniku aukcji zakodowany w formacie base64url jest ustawiony w nagłówku odpowiedzi Ad-Auction-Result. Ten skrót jest używany przez przeglądarkę do weryfikacji ładunku podczas kończenia aukcji na kliencie.

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

import { createHash } from 'crypto';

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

Dołączanie hasha w nagłówku odpowiedzi i zwracanie wyniku aukcji na stronie 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()
    });
  });
})

Ponieważ jest to odpowiedź na żądanie ujednoliconej aukcji przesłane ze strony w kroku 2, zawiera ona również wynik aukcji kontekstowej.

W tagu Ad-Auction-Result można podać wiele haszy, powtarzając nagłówek lub rozdzielając hasze. 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 przejściami, w których wyróżniono 5 krok, czyli moment, w którym kod JavaScript po stronie klienta przeprowadza licytację i przekazuje odpowiedź serwera

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

// 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 przekazywana do wywołania runAdAuction() różni się w zależności od konfiguracji aukcji wybranej przez sprzedawcę.

Aukcja pojedynczego sprzedawcy

W przypadku aukcji B&A z jednym sprzedawcą konfiguracja aukcji wywołania runAdAuction() jest skonstruowana w ten sposób:

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

W polu requestId można umieścić wartość requestId zwracaną 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 do testowania.

Aukcja w trybie mieszanym

W przypadku aukcji B&A w trybie mieszanym, w której mogą brać udział kupujący na urządzeniu i kupujący B&A, konfiguracja aukcji wywołania runAdAuction() jest konstruowana w ten sposób:

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ć aukcję w trybie mieszanym, do pola componentAuctions przekazywany jest wynik aukcji B&A i konfiguracja aukcji na urządzeniu. W aukcji w trybie mieszanym wartość seller jest taka sama zarówno w przypadku konfiguracji najwyższego poziomu, jak i konfiguracji komponentów.

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

Aukcja wielu sprzedawców

Jeśli jesteś sprzedawcą najwyższego poziomu, który przeprowadza aukcję z udziałem wielu sprzedawców na urządzeniu, każdy sprzedawca komponentów przesyła wynik aukcji B&A oraz konfigurację 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 do testowania.

Dalsze kroki

Po przeczytaniu tego przewodnika wykonaj te czynności:

Więcej informacji

Masz pytania?