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
As etapas podem ser resumidas da seguinte forma:
- Chame
getInterestGroupAdAuctionData()
para receber o payload criptografado do navegador - Chame
fetch('https://your-ad-server.example')
e envie a solicitação de leilão unificado com o payload criptografado para seu SAS - Chamar a operação
SelectAd()
da SFE do SAS para executar o leilão de B&A - Retornar o resultado do leilão de B&A para a página com o hash da resposta
- 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
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 |
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.
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
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, quandorunAdAuction()
for chamado para concluir o leilão no navegador. - A origem da solicitação de busca precisa corresponder à origem
seller
fornecida às chamadasgetInterestGroupAdAuctionData()
erunAdAuction()
.
O corpo da chamada contém:
- O payload do leilão contextual em texto simples que será usado pelo SAS para executar o leilão contextual.
- 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
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:
Accept-Language
User-Agent
- Endereço IP
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
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
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
- Para entender melhor, consulte os seguintes vídeos explicativos no GitHub:
- Saiba mais sobre a arquitetura de B&A para a Web
- Teste a API Protected Audience com B&A seguindo o codelab de teste local de ponta a ponta.
Dúvidas?
- Se você tiver dúvidas sobre os serviços de lances e leilões, abra um problema no repositório de serviços de lances e leilões.
- Se você tiver dúvidas sobre o Sandbox de privacidade em geral, abra um problema no repositório privacy-sandbox-dev-support.