Fazer a integração com o B&A como vendedor

Os serviços de lances e leilões (B&A) são um conjunto de serviços para compradores e vendedores de anúncios executados em um ambiente de execução confiável (TEE) para facilitar um leilão de público-alvo protegido (PA). Este guia para desenvolvedores explica como um vendedor pode fazer a integração com um leilão de PA do Chrome para B&A.

Tutorial

Fluxo de integração do vendedor em que o código JavaScript recebe o payload do leilão de B&A enviado ao SAS, e o SAS encaminha a solicitação para o front-end do vendedor (SFE). O SFE retorna o resultado que o SAS precisa encaminhar ao navegador, e o código JavaScript do vendedor chama runAdAuction.

As etapas podem ser resumidas da seguinte forma:

  1. Chame getInterestGroupAdAuctionData() para receber o payload criptografado do navegador
  2. Chame fetch('https://your-ad-server.example') e envie a solicitação de leilão unificado com o payload criptografado para seu SAS
  3. Chamar a operação SelectAd() da SFE do SAS para executar o leilão de B&A
  4. Retornar o resultado do leilão de B&A para a página com o hash da resposta
  5. Chame runAdAuction() no navegador para executar um leilão de PA de um único vendedor, de modo misto ou de vários vendedores e transmita o resultado do leilão de B&A do servidor para a chamada.

Receber dados criptografados do leilão de anúncios

O mesmo diagrama de instruções com a primeira etapa destacada, que é quando o código JavaScript do vendedor chama getInterestGroupAdAuctionData

Para receber os dados necessários para executar o leilão de B&A do lado do servidor, o código JavaScript do vendedor na página do editor chama 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 Descrição
seller Obrigatório. Origem do vendedor que está realizando o leilão. Esse valor precisa corresponder ao valor seller na chamada runAdAuction() mais tarde.
requestSize Opcional. Define o tamanho máximo do payload de todos os dados do comprador. Consulte a seção tamanho da solicitação do texto explicativo para saber mais.
perBuyerConfig Opcional. Define configurações para cada comprador e também controla quais compradores participam do leilão de B&A.

Se as origens do comprador estiverem listadas em perBuyerConfig, apenas os dados do grupo de interesse do comprador serão incluídos no payload. Se nenhum comprador estiver listado em perBuyerConfig, todos os grupos de interesse do usuário serão incluídos no payload.

targetSize Opcional se requestSize estiver definido. Obrigatório se a origem do comprador estiver definida no perBuyerConfig, mas o requestSize não estiver.

Define o tamanho máximo do payload dos dados do comprador. Consulte a seção tamanho da solicitação do texto explicativo para saber mais.

coordinatorOrigin Opcional, mas será obrigatório em algum momento. O padrão é https://publickeyservice.pa.gcp.privacysandboxservices.com quando não está definido.

Define o coordenador a ser usado para buscar a chave de criptografia do payload. Consulte a seção coordenador do explicativo para saber mais.

Quando a chamada é feita, o navegador lê os grupos de interesse dos compradores listados em perBuyerConfig e criptografa os dados do comprador. Esses dados do comprador contêm informações entre sites para serem usadas em lances e não podem ser descriptografadas fora de um TEE. Para a otimização de payload, apenas o nome do grupo de interesse, as chaves de indicador de lance confiável e os indicadores do navegador são incluídos no payload.

No objeto de dados do leilão de anúncios retornado pela chamada getInterestGroupAdAuctionData(), a string requestId e a matriz de bytes request criptografada estão disponíveis.

Captura de tela do Chrome DevTools que mostra a solicitação e o ID da solicitação disponíveis nos dados do leilão de anúncios

A string requestId é usada mais tarde quando runAdAuction() é chamada para concluir o leilão no navegador. O payload request criptografado é enviado ao serviço de publicidade do vendedor como parte da solicitação de leilão unificado.

Para conferir um exemplo dessa chamada, consulte o código JavaScript do vendedor do app de teste local.

Enviar a solicitação de leilão unificado para o SAS

O mesmo diagrama de instruções com a segunda etapa destacada, que é quando o código JavaScript do vendedor envia uma solicitação de leilão unificado para a SAS

Uma solicitação de leilão unificado é uma solicitação que contém o payload de leilão contextual em texto simples e o payload de leilão de B&A do público-alvo protegido. O payload do leilão de B&A do PA é o dado request criptografado que o navegador gerou na chamada getInterestGroupAdAuctionData(). Essa solicitação é enviada para o SAS, onde o leilão contextual e o leilão de B&A de PA são orquestrados.

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

Para enviar a solicitação ao SAS, uma chamada fetch() é feita na página:

  • A chamada precisa incluir a opção adAuctionHeaders: true, que sinaliza o navegador para verificar a resposta dessa chamada mais tarde, quando runAdAuction() for chamado para concluir o leilão no navegador.
  • A origem da solicitação de busca precisa corresponder à origem seller fornecida às chamadas getInterestGroupAdAuctionData() e runAdAuction().

O corpo da chamada contém:

  1. O payload do leilão contextual em texto simples que será usado pelo SAS para executar o leilão contextual.
  2. O payload criptografado do leilão da Protected Audience que será enviado ao SFE pelo SAS para executar o leilão de B&A do lado do servidor.

Para conferir um exemplo dessa chamada, consulte o código JavaScript do vendedor do app de teste local.

Como codificar e decodificar em base64

O payload request criptografado retornado da chamada getInterestGroupAdAuctionData() é uma instância de Uint8Array, que é um tipo de dados que o JSON não pode processar. Para enviar a matriz de bytes em um formato JSON, aplique uma codificação base64 aos dados binários para convertê-los em uma string.

A API JavaScript do navegador fornece as funções atob() e btoa() em window que convertem entre dados binários e string ASCII codificada em base64. atob significa ASCII para binário, e btoa significa binário para ASCII.

Chamar btoa() para codificar dados binários em uma string codificada em base64 é semelhante ao seguinte:

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

O resultado do leilão de B&A criptografado retornado por essa chamada fetch também está em uma codificação base64. Portanto, é necessário decodificá-lo para dados binários. Chame atob() para decodificar a string ASCII codificada em base64 em dados binários:

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

No entanto, uma string codificada em base64 geralmente é cerca de 33% maior que os dados originais. Se você quiser melhorar ainda mais a latência, use um formato diferente de JSON para enviar os dados binários.

Chamar SelectAd da SFE para executar o leilão de B&A

O mesmo diagrama de instruções com a terceira etapa destacada, que é quando o SAS envia uma solicitação de SelectAd para o SFE, e o SFE executa um leilão de B&A

Depois que o serviço de publicidade do vendedor recebe a solicitação de leilão unificado da página, o leilão contextual é executado primeiro para determinar o vencedor do leilão contextual e coletar os indicadores do comprador que serão transmitidos ao leilão de B&A do PA. Em seguida, o leilão de B&A é iniciado chamando a operação SelectAd do SFE do SAS com o payload de solicitação. Alguns metadados da solicitação da página para o SAS na etapa 2 são encaminhados para a SFE.

Criar o payload SelectAdRequest

O payload de solicitação da chamada SelectAd pode ser construído da seguinte maneira:

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

Se os dados criptografados do leilão de anúncios do navegador tiverem codificação base64, eles vão precisar ser decodificados para dados binários se a solicitação para o SFE for enviada usando o gRPC. Se a solicitação for enviada usando HTTP, os dados criptografados do leilão de anúncios poderão permanecer no formato codificado em base64.

Para conferir outros campos definidos na solicitação SelectAd, consulte a definição de proto de SelectAdRequest.

Definir o campo do vendedor de nível superior para leilões de componentes e do modo misto

Se o vendedor estiver executando um leilão de modo misto ou participando como um vendedor de componentes em um leilão de vários vendedores, o campo top_level_seller precisa ser definido na solicitação.

Se você for um vendedor de modo misto, o valor top_level_seller será sua origem:

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

Se você for um vendedor de componentes, o valor de top_level_seller será o vendedor de nível superior do leilão multivendedor:

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

Chamar SelectAd do SFE

A chamada para a SFE do SAS pode ser feita com gRPC ou HTTP.

Chamada gRPC

A solicitação gRPC para o SFE é semelhante a esta, usando o Express no Node com um cliente 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
});

A definição de proto do cliente SFE pode ser encontrada no repositório do app de teste local.

Chamada HTTP para o proxy Envoy

A solicitação POST HTTP para a SFE é enviada para o caminho /v1/selectAd e tem a seguinte aparência:

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

Encaminhar metadados

Os seguintes metadados da chamada da página para o SAS precisam ser adicionados à chamada SelectAd do SAS para a SFE:

Quando os metadados são enviados para a SFE, eles precisam usar os cabeçalhos não padrão a seguir, porque o gRPC pode alterar o cabeçalho User-Agent:

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

Confira a seguir um exemplo de como os metadados podem ser encaminhados usando o Express no Node com um cliente 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);
})

Confira a seguir um exemplo de como os metadados podem ser encaminhados usando uma chamada 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)
  });
})

Leilão de vários vendedores orquestrado pelo servidor

Se você for um vendedor de nível superior que executa um leilão de vários vendedores orquestrado pelo servidor, a chamada GetComponentAuctionCiphertexts será feita para o SFE antes da chamada SelectAd. A resposta contém os payloads do leilão de componentes criptografados novamente que são enviados aos serviços de anúncios do vendedor do componente. Os resultados do leilão de anúncios de B&A do componente retornado são fornecidos à chamada SelectAd do SFE do vendedor de nível superior.

Consulte o explicativo sobre o multivendedor no GitHub para saber mais.

Retorna o resultado do leilão de B&A para a página

O mesmo diagrama de instruções com a quarta etapa destacada, que é quando o SAS envia o resultado do leilão do SelectAd de volta ao navegador

Depois que o leilão de B&A é concluído, o resultado criptografado é retornado ao SAS, que responde à solicitação de leilão unificado da página na etapa 2 com o resultado criptografado. Na resposta do SAS à página, o hash SHA-256 codificado em base64url do resultado do leilão criptografado é definido no cabeçalho de resposta Ad-Auction-Result. Esse hash é usado pelo navegador para verificar o payload ao finalizar o leilão no cliente.

A criação de um hash SHA-256 com codificação base64 é semelhante ao seguinte no Node:

import { createHash } from 'crypto';

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

O hash anexado ao cabeçalho de resposta e o retorno do resultado do leilão para a página têm esta aparência:

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

Como essa é uma resposta à solicitação de leilão unificado feita na página na etapa 2, o resultado do leilão contextual também é incluído na resposta.

É possível incluir vários hashes no Ad-Auction-Result repetindo o cabeçalho ou separando os hashes. Os dois cabeçalhos de resposta a seguir são equivalentes:

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

Para conferir um exemplo dessa chamada, consulte o código do servidor do vendedor do app de teste local.

Chame runAdAuction() para concluir o leilão

O mesmo diagrama de instruções com a quinta etapa destacada, que é quando o código JavaScript do lado do cliente executa o leilão e fornece a resposta do servidor

A resposta do leilão unificado retornada pelo SAS inclui o resultado criptografado do leilão de B&A. Esse payload é transmitido para a chamada runAdAuction() para concluir o leilão no navegador. O valor requestId da chamada getInterestGroupAdAuctionData() na etapa 1 também é transmitido para o leilão.

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

A estrutura da configuração do leilão transmitida para a chamada runAdAuction() varia de acordo com a configuração do leilão escolhida pelo vendedor.

Leilão de vendedor único

Para executar um leilão de B&A de um único vendedor, a configuração do leilão da chamada runAdAuction() é construída da seguinte maneira:

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

O campo requestId aceita o requestId retornado pela chamada getInterestGroupAdAuctionData(). O campo serverResponse aceita uma matriz de bytes do leilão de B&A executado na etapa 3.

Para conferir um exemplo dessa chamada, consulte o código JavaScript do vendedor do app de teste local.

Leilão de modo misto

Para realizar um leilão de B&A no modo misto em que os compradores no dispositivo e de B&A podem participar, a configuração do leilão da chamada runAdAuction() é construída da seguinte maneira:

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

Para facilitar um leilão no modo misto, o resultado do leilão de B&A e a configuração do leilão no dispositivo são transmitidos para o campo componentAuctions. Em um leilão de modo misto, o valor de seller é o mesmo para a configuração de nível superior e as configurações de componentes.

Para conferir um exemplo dessa chamada, consulte o código JavaScript do vendedor do app de teste local.

Leilão de vários vendedores

Se você é um vendedor de nível superior que realiza um leilão de vários vendedores orquestrado pelo dispositivo, cada vendedor de componentes envia o resultado do leilão de B&A e as configurações do leilão no 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',
    }
  ]
})

Para conferir um exemplo dessa chamada, consulte o código JavaScript do vendedor do app de teste local.

Próximas etapas

Depois de ler este guia, siga estas etapas:

Saiba mais

Dúvidas?