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óre działają w zaufanym środowisku wykonawczym (TEE), aby ułatwić przeprowadzanie aukcji Protected Audience (PA). Z tego przewodnika dla deweloperów dowiesz się, jak sprzedawca może zintegrować się z aukcją Chrome PA w ramach 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. Uruchom z SAS operację SelectAd() SFE, aby przeprowadzić aukcję B&A
  4. Przesyłanie na stronę wyników 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 parametrze perBuyerConfig ustawiono pochodzenie kupującego, ale nie ustawiono parametru requestSize.

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 dane kupujących. 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 ładunku tylko nazwa grupy zainteresowań, klucze sygnałów zaufanego określania stawek i sygnały przeglądarki są uwzględniane w ładunku.

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 Chrome pokazujący, ż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 kontekstowej aukcji w formie tekstu zwykłego i ładunek aukcji z uwzględnieniem 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 jest wykonywane wywołanie 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 użyte do zakończenia aukcji 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 tekstu zwykłego, 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 zwrócony 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 atob()btoa() w obiekcie window, które umożliwiają konwersję między danymi binarnymi a ciągiem ASCII zakodowanym w formacie 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 żądania 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ą protokołu 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ą komponentów, 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 postać:

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ą Expressa w Node z klienta 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 reklamowej 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 w nagłówku odpowiedzi Ad-Auction-Result jest ustawiony zakodowany w formacie base64url hash SHA-256 zaszyfrowanego wyniku aukcji. 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()
    });
  });
})

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

W wartości 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 lokalnej aplikacji do testowania.

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

Ten sam diagram z wyróżnionym 5 krokiem, w którym kod JavaScript po stronie klienta przeprowadza licytację i przekazuje odpowiedź serwera.

Odpowiedź z SAS w ramach aukcji zjednoczonej 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,
});

Pole requestId akceptuje 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 w przypadku konfiguracji najwyższego poziomu 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 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 do testowania.

Dalsze kroki

Po przeczytaniu tego przewodnika wykonaj te czynności:

Więcej informacji

Masz pytania?