Интегрируйтесь с B&A в качестве продавца.

Службы торгов и аукционов (B&A) — это набор услуг для покупателей и продавцов рекламы, который работает в доверенной среде исполнения (TEE) для облегчения аукциона с защищенной аудиторией (PA). В этом руководстве разработчика объясняется, как продавец может интегрировать аукцион Chrome PA для B&A.

Прохождение

Процесс интеграции продавца, при котором код JavaScript получает полезную нагрузку аукциона B&A, которая отправляется в SAS, а SAS перенаправляет запрос на интерфейс продавца (SFE). SFE возвращает результат, который SAS должен переслать в браузер, а код JavaScript продавца вызывает runAdAuction.

Эти шаги можно резюмировать следующим образом:

  1. Вызовите getInterestGroupAdAuctionData() чтобы получить зашифрованные полезные данные из браузера.
  2. Вызовите fetch('https://your-ad-server.example') и отправьте запрос единого аукциона с зашифрованными полезными данными на свой SAS.
  3. Вызовите операцию SelectAd() вашего SFE из вашего SAS, чтобы запустить аукцион B&A.
  4. Верните на страницу результат аукциона B&A вместе с хешем ответа.
  5. Вызовите runAdAuction() в браузере, чтобы запустить аукцион PA с одним, смешанным или несколькими продавцами, и передайте результат аукциона B&A на стороне сервера в вызов.

Получите зашифрованные данные аукциона рекламы

Та же пошаговая диаграмма с выделенным первым шагом, когда код JavaScript продавца вызывает getInterestGroupAdAuctionData.

Чтобы получить данные, необходимые для запуска аукциона B&A на стороне сервера, код JavaScript продавца на странице издателя вызывает 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;
Поле Описание
seller Необходимый . Происхождение продавца, проводящего аукцион. Это значение должно совпадать со значением seller в вызове runAdAuction() позже.
requestSize Необязательный . Устанавливает максимальный размер полезных данных всех данных о покупателях. Дополнительную информацию см. в разделе «Размер запроса » пояснения.
perBuyerConfig Необязательный . Устанавливает конфигурации для каждого покупателя, а также контролирует, какие покупатели участвуют в аукционе B&A.

Если происхождение покупателя указано в perBuyerConfig , в полезные данные включаются только данные группы интересов покупателя. Если в perBuyerConfig не указано ни одного покупателя, то в полезные данные включаются все группы интересов пользователя.

targetSize Необязательно, если установлен requestSize . Требуется , если в perBuyerConfig указано происхождение покупателя, но не задан requestSize .

Устанавливает максимальный размер полезной нагрузки данных этого покупателя. Дополнительную информацию см. в разделе «Размер запроса » пояснения.

coordinatorOrigin Необязательно , но со временем станет обязательным. По умолчанию используется https://publickeyservice.pa.gcp.privacysandboxservices.com если не установлено.

Устанавливает координатора, который будет использоваться для получения ключа для шифрования полезных данных. Дополнительную информацию см. в разделе «Координатор» пояснения.

При выполнении вызова браузер считывает группы интересов покупателей, перечисленных в perBuyerConfig , и шифрует данные покупателя. Эти данные покупателя содержат межсайтовую информацию, которая будет использоваться для ставок, и не могут быть расшифрованы вне TEE. Для оптимизации полезных данных в полезные данные включаются только название группы интересов, ключи доверенных сигналов назначения ставок и сигналы браузера.

В объекте данных аукциона рекламы, возвращаемом вызовом getInterestGroupAdAuctionData() , доступна строка requestId и зашифрованный массив байтов request .

Скриншот Chrome DevTools, на котором показано, что запрос и идентификатор запроса доступны в данных аукциона рекламы.

Строка requestId используется позже, когда вызывается runAdAuction() для завершения аукциона в браузере. Зашифрованная полезная нагрузка request отправляется в рекламную службу продавца как часть единого запроса аукциона.

Пример этого вызова можно увидеть в коде JavaScript продавца локального приложения для тестирования .

Отправьте единый запрос на аукцион в SAS.

Та же пошаговая диаграмма с выделенным вторым шагом, когда код JavaScript продавца отправляет единый запрос аукциона в SAS.

Единый запрос аукциона — это запрос, который содержит полезные данные контекстного аукциона в виде открытого текста и полезные данные аукциона PA B&A. Полезная нагрузка аукциона PA B&A — это зашифрованные данные request , сгенерированные браузером при вызове getInterestGroupAdAuctionData() . Этот запрос отправляется в SAS, где организуются контекстный аукцион и аукцион PA B&A.

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

Чтобы отправить запрос в SAS, со страницы выполняется вызов fetch() :

  • Вызов должен включать параметр adAuctionHeaders: true , который сигнализирует браузеру о необходимости проверить ответ на этот вызов позднее, когда будет вызван runAdAuction() для завершения аукциона в браузере.
  • Источник запроса на выборку должен совпадать с источником происхождения seller , указанным в вызовах getInterestGroupAdAuctionData() и runAdAuction() .

Тело вызова содержит:

  1. Полезная нагрузка контекстного аукциона в виде открытого текста, которая будет использоваться SAS для запуска контекстного аукциона.
  2. Зашифрованная полезная нагрузка аукциона Protected Audience, которая будет отправлена ​​в SFE компанией SAS для проведения серверного аукциона B&A.

Пример этого вызова можно увидеть в коде JavaScript продавца локального приложения для тестирования .

Кодирование и декодирование Base64

Зашифрованные полезные данные request , возвращаемые из вызова getInterestGroupAdAuctionData() являются экземпляром Uint8Array , который является типом данных, который JSON не может обработать. Чтобы отправить массив байтов в формате JSON, вы можете применить кодировку base64 к двоичным данным, чтобы преобразовать их в строку.

API браузера JavaScript предоставляет функции atob() и btoa() в window , которые преобразуют двоичные данные в строку ASCII в кодировке Base64. ( atob означает преобразование ASCII в двоичный код, а btoa означает преобразование двоичного кода в ASCII).

Вызов btoa() для кодирования двоичных данных в строку в кодировке Base64 выглядит следующим образом:

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

Зашифрованный результат аукциона B&A, возвращаемый этим fetch выборки, также имеет кодировку Base64, поэтому вам необходимо декодировать его обратно в двоичные данные. Вызовите atob() для декодирования строки ASCII в кодировке Base64 в двоичные данные:

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

Однако строка в кодировке Base64 обычно примерно на 33% больше исходных данных. Если вы хотите еще больше улучшить задержку, используйте для отправки двоичных данных формат, отличный от JSON.

Позвоните в SelectAd SFE, чтобы провести аукцион B&A.

Та же пошаговая диаграмма с выделенным третьим шагом, когда SAS отправляет запрос SelectAd в SFE, а SFE запускает аукцион B&A.

Как только служба объявлений продавца получает запрос на единый аукцион со страницы, сначала запускается контекстный аукцион, чтобы определить победителя контекстного аукциона и собрать сигналы покупателя, которые будут переданы на аукцион PA B&A. Затем аукцион B&A инициируется путем вызова операции SelectAd SFE из SAS с полезной нагрузкой запроса. Обратите внимание, что некоторые метаданные из запроса страницы к SAS на шаге 2 пересылаются в SFE.

Создайте полезную нагрузку SelectAdRequest

Полезная нагрузка запроса вызова SelectAd может быть построена следующим образом:

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

Обратите внимание: если зашифрованные данные рекламного аукциона из браузера были закодированы в формате Base64, их необходимо декодировать обратно в двоичные данные , если запрос к SFE отправляется с использованием gRPC. Если запрос отправляется по протоколу HTTP, зашифрованные данные аукциона рекламы могут оставаться в форме, закодированной в формате Base64.

Чтобы увидеть другие поля, определенные в запросе SelectAd , см. прототип определения SelectAdRequest .

Установите поле продавца верхнего уровня для смешанных аукционов и аукционов компонентов.

Если продавец проводит аукцион смешанного режима или участвует в аукционе с несколькими продавцами в качестве продавца компонентов, в запросе необходимо определить поле top_level_seller .

Если вы продавец смешанного режима, значение top_level_seller указывает на ваше происхождение:

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

Если вы являетесь продавцом компонентов, значение top_level_seller — это продавец верхнего уровня на аукционе с несколькими продавцами:

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

Позвоните SelectAd SFE

Вызов SFE из SAS можно выполнить с помощью gRPC или HTTP.

вызов gRPC

Запрос gRPC к SFE выглядит следующим образом при использовании Express в узле с клиентом 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
});

Определение прототипа для клиента SFE можно найти в локальном репозитории приложения для тестирования .

HTTP-вызов прокси-сервера Envoy

HTTP-запрос POST к SFE отправляется по пути /v1/selectAd и выглядит следующим образом:

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

Переслать метаданные

Следующие метаданные из вызова страницы в SAS должны быть добавлены в вызов SAS SelectAd в SFE:

Когда метаданные отправляются в SFE, они должны использовать следующие нестандартные заголовки, поскольку gRPC может изменить заголовок User-Agent :

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

Ниже приведен пример того, как метаданные можно пересылать с помощью Express in Node с клиентом 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);
})

Ниже приведен пример того, как метаданные могут быть перенаправлены с помощью 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)
  });
})

Аукцион с участием нескольких продавцов, управляемый сервером

Если вы являетесь продавцом верхнего уровня, проводящим аукцион с несколькими продавцами, управляемый сервером , вызов GetComponentAuctionCiphertexts выполняется в SFE до выполнения вызова SelectAd . Ответ содержит повторно зашифрованные полезные данные аукциона компонентов, которые отправляются в рекламные службы продавца компонентов. Возвращенные результаты рекламного аукциона компонентов B&A передаются в вызов SelectAd SFE продавца верхнего уровня.

Дополнительную информацию см . в пояснении к мультипродавцам на GitHub.

Вернуть результат аукциона B&A на страницу

Та же пошаговая диаграмма с выделенным четвертым шагом, когда SAS отправляет результат аукциона SelectAd обратно в браузер.

После завершения аукциона B&A зашифрованный результат аукциона возвращается в SAS, и SAS отвечает на запрос единого аукциона со страницы на шаге 2 с зашифрованным результатом аукциона. В ответе SAS на страницу хеш SHA-256 в кодировке Base64url зашифрованного результата аукциона устанавливается в заголовке ответа Ad-Auction-Result . Этот хэш используется браузером для проверки полезной нагрузки при завершении аукциона в клиенте.

Создание хеша SHA-256 с кодировкой base64 в Node выглядит следующим образом:

import { createHash } from 'crypto';

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

Прикрепление хэша в заголовке ответа и возврат результата аукциона на страницу выглядит следующим образом:

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

Поскольку это ответ на запрос единого аукциона, сделанный со страницы на шаге 2 , в ответ также включается результат контекстного аукциона.

В Ad-Auction-Result можно включить несколько хешей, повторяя заголовок или разделяя хэши. Следующие два заголовка ответа эквивалентны:

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

Пример этого вызова можно увидеть в коде сервера продавца локального приложения для тестирования .

Вызовите runAdAuction() чтобы завершить аукцион.

Та же пошаговая диаграмма с выделенным пятым шагом, когда код JavaScript на стороне клиента запускает аукцион и предоставляет ответ сервера.

Ответ на единый аукцион, возвращенный из SAS, включает зашифрованный результат аукциона B&A. Эта полезная нагрузка передается в вызов runAdAuction() для завершения аукциона в браузере. Значение requestId из вызова getInterestGroupAdAuctionData() на шаге 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
});

Структура конфигурации аукциона, передаваемая в вызов runAdAuction() различается в зависимости от конфигурации аукциона, выбранной продавцом.

Аукцион с одним продавцом

Для проведения аукциона B&A с одним продавцом конфигурация аукциона вызова runAdAuction() строится следующим образом:

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

Поле requestId принимает requestId , возвращаемый вызовом getInterestGroupAdAuctionData() . Поле serverResponse принимает массив байтов аукциона B&A, который проводился на шаге №3 .

Пример этого вызова можно увидеть в коде JavaScript продавца локального приложения для тестирования .

Смешанный аукцион

Для проведения аукциона B&A в смешанном режиме, в котором могут участвовать как покупатели на устройстве, так и покупатели B&A, конфигурация аукциона вызова runAdAuction() строится следующим образом:

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

Для облегчения проведения аукциона в смешанном режиме результаты аукциона B&A и конфигурация аукциона на устройстве передаются в componentAuctions . На аукционе смешанного режима стоимость seller одинакова как для конфигурации верхнего уровня, так и для конфигурации компонента.

Пример этого вызова можно увидеть в коде JavaScript продавца локального приложения для тестирования .

Аукцион с несколькими продавцами

Если вы являетесь продавцом высшего уровня и проводите аукцион с несколькими продавцами, организованный устройством, то каждый продавец компонентов отправляет результаты своего аукциона B&A и конфигурации аукциона на устройстве.

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

Пример этого вызова можно увидеть в коде JavaScript продавца локального приложения для тестирования .

Следующие шаги

Прочитав это руководство, вы можете предпринять следующие шаги:

Узнать больше

Есть вопросы?