Para ajudar os desenvolvedores a começar a testar a API Protected App Signals, este documento descreve todas as APIs na plataforma da API, detalha como configurar um ambiente de teste e traz exemplos de scripts e configuração.
Histórico de versões
Janeiro de 2024
Primeira versão do guia para desenvolvedores com suporte ao lançamento de MVP do PAS
Março de 2024
Mudanças na API para oferecer suporte à versão M-2024-05 da API Android e a Versão de abril de 2024 dos componentes do lado do servidor. Mudanças mais importantes:
- Adição de detalhes sobre as permissões necessárias para a API no dispositivo
- Adição de detalhes sobre o gerenciamento de cotas de indicadores no dispositivo
- Assinatura
generateBid
atualizada com mudanças relacionadas a contexto recuperação de anúncios e suporte à saída - Atualização da documentação de
reportWin
, incluindo suporte de saída - Atualização da documentação da API Ad Retrieval sem suporte à recuperação de anúncios BYOS e documentar a UDF de recuperação de anúncios
Visão geral da API
A plataforma da API Protected Signals inclui diferentes subconjuntos de APIs em diferentes sistemas:
- APIs do Android:
- API Signal Curation, composta de:
- API Update Signals
- API Signals Encoding
- API Protected Auction Support: para ser usada por SDKs para executar o leilão protegido nos servidores de lances e leilões (B&A) usando indicadores de apps protegidos.
- APIs do servidor:
- API Protected Auction: uma série de scripts JS em execução nos servidores de lances e leilões. Essa API permite que vendedores e compradores criem a lógica para implementar o leilão protegido.
- API Ad Retrieval: responsável por fornecer uma lista de anúncios candidatos, de acordo com as informações contextuais e do usuário disponibilizadas para o servidor de lances do comprador.
Cliente Android
No lado do cliente, a plataforma da API Protected App Signals consiste em três APIs diferentes:
- Update Signals: uma API do sistema Android para ativar a seleção de indicadores no dispositivo.
- Signals Encoding: uma API do JavaScript para preparar os indicadores que serão enviados ao servidor durante o leilão.
- Protected Auction Support: uma API que oferece suporte à execução de um leilão protegido nos servidores de lances e leilões. Essa API não é específica para a Protected App Signals, sendo também usada para oferecer suporte a leilões da API Protected Audience.
API Update Signals
A API Update Signals permite às adtechs registrar indicadores relacionados ao usuário e ao app em nome de um comprador. Ela funciona em um modelo de delegação. O autor da chamada fornece um URI que o framework usa para buscar os indicadores correspondentes e a lógica para codificar esses indicadores para serem usados no leilão.
A API exige o android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS
permissão.
A API updateSignals()
vai recuperar um objeto JSON
do URI que descreve quais sinais adicionar ou remover e como se preparar
para o leilão.
Executor executor = Executors.newCachedThreadPool();
ProtectedSignalsManager protectedSignalsManager
= ProtectedSignalsManager.get(context);
// Initialize a UpdateSignalsRequest
UpdateSignalsRequest updateSignalsRequest = new
UpdateSignalsRequest.Builder(Uri.parse("https://example-adtech1.com/signals"))
.build();
OutcomeReceiver<Object, Exception> outcomeReceiver = new OutcomeReceiver<Object, Exception>() {
@Override
public void onResult(Object o) {
//Post-success actions
}
@Override
public void onError(Exception error) {
//Post-failure actions
};
// Call updateSignals
protectedSignalsManager.updateSignals(updateSignalsRequest,
executor,
outcomeReceiver);
A plataforma faz uma solicitação HTTPS ao URI fornecido na solicitação para buscar as atualizações de indicadores. Junto às atualizações de indicadores, a resposta pode incluir um endpoint que hospeda a lógica de codificação para converter os indicadores brutos em payloads codificados. As atualizações dos indicadores precisam estar no formato JSON e podem ter as chaves abaixo:
As chaves de nível superior do objeto JSON precisam corresponder a um destes cinco comandos:
Chave |
Descrição |
|
Adiciona um novo indicador, substituindo os indicadores existentes com a mesma chave. O valor para isso é um objeto JSON em que as chaves são strings de base 64 correspondentes à chave que será usada e os valores são uma string de base 64 correspondente ao valor que será usado. |
|
Anexa novos indicadores a uma série temporal de indicadores, removendo os mais antigos para dar espaço aos novos quando o tamanho da série excede o máximo determinado. O valor desse atributo é um objeto JSON em que as chaves são strings de base 64 correspondentes à chave que será anexada e os valores são objetos com dois campos: "values" e "maxSignals". "values": uma lista de strings de base 64 correspondentes a valores de indicadores que serão anexados à série temporal. "maxSignals": o número máximo de valores permitidos nessa série temporal. Se o número atual de indicadores associados à chave exceder "maxSignals", os indicadores mais antigos serão removidos. É possível anexar a uma chave adicionada por put. Adicionar mais do que o número máximo de valores causa um erro. |
|
Adiciona um novo indicador somente se não houver indicadores com a mesma chave. O valor para isso é um objeto JSON em que as chaves são strings de base 64 correspondentes à chave que será usada e os valores são uma string de base 64 correspondente ao valor que será usado. |
|
Remove o indicador de uma chave. O valor para isso é uma lista de strings de base 64 correspondentes às chaves dos indicadores que precisam ser excluídos. |
|
Oferece uma ação para atualizar o endpoint e um URI que pode ser usado para extrair uma lógica de codificação. A subchave para fornecer uma ação de atualização é "ação", e os valores aceitos atualmente são apenas "REGISTER", que vai registrar o endpoint do codificador se fornecido pela primeira vez ou vai substituir o endpoint atual pelo novo fornecido. É necessário fornecer o endpoint para a ação "REGISTER". A subchave para fornecer um endpoint do codificador é "endpoint", e o valor é a string do URI para o endpoint. |
Confira um exemplo de solicitação JSON:
{
"put": {
"AAAAAQ==": "AAAAZQ==",
"AAAAAg==": "AAAAZg=="
},
"append": {
"AAAAAw==": {
"values": [
"AAAAZw=="
],
"max_signals": 3
}
},
"put_if_not_present": {
"AAAABA==": "AAAAaQ==",
"AAAABQ==": "AAAAag=="
},
"update_encoder": {
"action": "REGISTER",
"endpoint": "https://adtech1.com/Protected App Signals_encode_script.js"
}
}
Os indicadores terão uma cota no dispositivo de 10 a 15 KB. Depois que a cota for excedido, a PPAPI vai remover os sinais usando uma estratégia FIFO. O processo de remoção permitirá que a cota seja ligeiramente excedida por curtos intervalos de vezes em a fim de reduzir a frequência de remoções.
API Signals Encoding
Os compradores precisam fornecer uma função de script Java para codificar os indicadores armazenados no dispositivo que serão enviados ao servidor durante o leilão protegido. Eles podem fornecer esse script adicionando o URL em que ele pode ser buscado com a chave "update_encoder" em qualquer uma das respostas a uma solicitação da API UpdateSignal. O script terá a assinatura abaixo:
function encodeSignals(signals, maxSize) {
let result = new Uint8Array(maxSize);
// first entry will contain the total size
let size = 1;
let keys = 0;
for (const [key, values] of signals.entries()) {
keys++;
// In this encoding we only care about the first byte
console.log("key " + keys + " is " + key)
result[size++] = key[0];
result[size++] = values.length;
for(const value of values) {
result[size++] = value.signal_value[0];
}
}
result[0] = keys;
return { 'status': 0, 'results': result.subarray(0, size)};
}
O parâmetro signals
é um mapa de chaves na forma de UInt8Arrays de tamanho 4
para listas de objetos da API Protected App Signals. Cada objeto da API tem
três campos:
signal_value
: um UInt8Array que representa o valor do indicador.creation_time
: um número que representa o horário de criação dos indicadores em segundos de época.package_name
: uma string que representa o nome do pacote que criou o indicador.
O parâmetro maxSize
é um número que descreve o maior tamanho de matriz permitido
para a saída.
A função precisa produzir um objeto com dois campos:
status
: precisa ser 0 se o script for executado.results
: precisa ser um UInt8Array de comprimento menor ou igual a maxSize. Essa matriz será enviada ao servidor durante os leilões e preparada pelo scriptprepareDataForAdRetrieval
.
A codificação oferece às adtechs um estágio inicial de engenharia de atributos, em que elas podem realizar transformações, como a compactação de indicadores brutos em versões concatenadas com base na própria lógica personalizada. Durante um leilão protegido em execução nos ambientes de execução confiáveis (TEE), a lógica personalizada das adtechs vai ter acesso de leitura aos payloads de indicadores gerados pela codificação. A lógica personalizada, conhecida como função definida pelo usuário (UDF) (link em inglês), executada no TEE de B&A do comprador vai ter acesso de leitura aos indicadores codificados e a outros indicadores de contexto fornecidos pelo app do editor para executar a seleção de anúncios (extração de anúncios e lances).
Codificação de indicadores
A cada hora, os indicadores dos compradores que forneceram lógica de codificação com os indicadores registrados serão codificados em um payload de leilão. A matriz de bytes do payload de leilão é mantida no dispositivo e criptografada para ser coletada pelos vendedores como parte dos dados da seleção de anúncios que serão incluídos como parte de um leilão protegido. Para o teste, é possível acionar essa codificação fora do período agendado executando este comando:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
Controle de versões da lógica do codificador
Quando é feita uma solicitação de download da lógica do codificador das adtechs, o endpoint pode responder com um número de versão nos cabeçalhos de resposta. Essa versão é mantida com a lógica do codificador no dispositivo. Quando os indicadores brutos são codificados, o payload codificado é mantido com a versão usada para codificação. Essa versão também é enviada ao servidor de B&A durante um leilão protegido para que as adtechs possam usá-la para alinhar a lógica de lances e codificação.
Response header for providing encoder version : X_ENCODER_VERSION
API Protected Auction Support
No lado do dispositivo, realizar um leilão para a API Protected App Signals é o mesmo que realizar um leilão para públicos-alvo protegidos.
Serviços de lances e leilões
Confira as APIs do servidor:
- API Protected Auction: uma série de funções JS ou UDFs que compradores e vendedores podem implantar nos componentes de B&A deles para determinar a lógica de lances e leilões.
- API Ad Retrieval: os compradores podem implementar essa API usando um endpoint REST como responsável por fornecer um conjunto de anúncios candidatos para o leilão da API Protected App Signals.
API Protected Auction
A API Protected Auction consiste em uma API de JS ou UDFs que compradores e vendedores podem usar para implementar a lógica de lances e leilões.
UDFs de adtech do comprador
UDF prepareDataForAdRetrieval
Antes que a API Protected App Signals possa ser usada para buscar candidatos a anúncios do TEE
serviço de recuperação de anúncios, os compradores precisam decodificar e preparar os indicadores de apps protegidos
e outros dados fornecidos pelo vendedor. A saída da UDF prepareDataForAdRetrieval
dos compradores é
transmitida ao serviço de extração de anúncios para
extrair os principais anúncios candidatos para lances.
// Inputs
// ------
// encodedOnDeviceSignals: A Uint8Array of bytes from the device.
// encodedOnDeviceSignalsVersion: An integer representing the encoded
// version of the signals.
// sellerAuctionSignals: Information about auction (ad format, size) derived
// contextually.
// contextualSignals: Additional contextual signals that could help in
// generating bids.
//
// Outputs
// -------
// Returns a JSON structure to be used for retrieval.
// The structure of this object is left to the adtech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
return {};
}
UDF generateBid
Depois que os principais anúncios candidatos são retornados, eles são transmitidos para a
lógica de lances personalizados do comprador, a UDF generateBid
(link em inglês):
// Inputs
// ------
// ads: Data string returned by the ads retrieval service. This can include Protected App Signals
// ads and related ads metadata.
// sellerAuctionSignals: Information about the auction (ad format, size),
// derived contextually
// buyerSignals: Any additional contextual information provided by the buyer
// preprocessedDataForRetrieval: This is the output of this UDF.
function generateBid(ads, sellerAuctionSignals, buyerSignals,
preprocessedDataForRetrieval,
rawSignals, rawSignalsVersion) {
return { "ad": <ad Value Object>,
"bid": <float>,
"render": <render URL string>,
'adCost': <optional float ad cost>,
"egressPayload": <limitedEgressPayload>,
"temporaryUnlimitedEgressPayload": <temporaryUnlimitedEgressPayload>
};
}
O resultado dessa função é um lance único para um candidato a anúncio, representado
como um JSON equivalente a
ProtectedAppSignalsAdWithBidMetadata
A função também pode retornar duas matrizes que serão transmitidas para reportWin
para ativar o treinamento de modelo (para mais detalhes sobre saída e treinamento de modelo
consulte a seção de relatórios na explicação do PAS)
UDF reportWin
Quando um leilão é concluído, o serviço de leilão gera URLs de relatório para
os compradores e registrar beacons usando reportWin
UDF (Esse é o mesmo
reportWin
usada para públicos-alvo protegidos).
O dispositivo receberá um ping no dispositivo assim que o anúncio for renderizado pelo cliente.
A assinatura desse método é quase a mesma da API Protected Audience
version, exceto por dois parâmetros extras egressPayload
e
temporaryUnlimitedEgressPayload
, que são usados para ativar o treinamento de modelo
preenchido com os resultados de generateBid
.
// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
buyerReportingSignals,
egressPayload, temporaryUnlimitedEgressPayload) {
// ...
}
UDFs de adtech do vendedor
UDF scoreAd
Essa UDF é usada pelos vendedores para selecionar quais anúncios recebidos dos compradores vão vencer o leilão.
function scoreAd(adMetadata, bid, auctionConfig,
trustedScoringSignals, bid_metadata) {
// ...
return {desirability: desirabilityScoreForThisAd,
allowComponentAuction: true_or_false};
}
UDF reportResult
Essa UDF (link em inglês) permite que o vendedor gere (depois de um tempo) relatórios no nível do evento com as informações sobre o anúncio vencedor.
function reportResult(auctionConfig, reporting_metadata) {
// ...
registerAdBeacon({"click", clickUrl,"view", viewUrl});
sendReportTo(reportResultUrl);
return signalsForWinner;
}
API Ad Retrieval
Na versão MVP , o serviço de extração de anúncios será um serviço gerenciado e hospedado pelo comprador e o de lances extrai desse serviço os candidatos a anúncio. A partir de abril de 2024, o servidor de recuperação de anúncios precisa ser executado em um ambiente de execução (TEE) e vai expor uma interface GRPC/proto. As empresas de adtech precisam configurar esse servidor e fornecer o URL dele como parte da implantação da pilha de B&A. Uma implementação desse serviço em execução no TEE está disponível no GitHub do Sandbox de privacidade e no restante da na documentação, presumimos que esse é o código usado na implantação.
A partir de abril de 2024, as versões de B&A são compatíveis com anúncios de caminho contextual recuperação. Nesse caso, o servidor de lances receberá uma lista de identificadores de anúncios enviados pelo servidor RTB durante a parte contextual do leilão. Os identificadores serão enviados a um servidor TEE KV para buscar todos os informações relacionadas a serem usadas durante a fase de lances (por exemplo, ad-render-url, metadados e embeddings do anúncio para serem usados na seleção top-k). Esse segundo caminho não precisa de nenhuma lógica específica para ser implantados. Portanto, vamos documentar aqui apenas como configurar o TEE com base de recuperação de anúncios.
UDF HandleRequest
function HandleRequest(requestMetadata, preparedDataForAdRetrieval,
deviceMetadata, contextualSignals) {
return adsMetadataString;
}
Em que:
requestMetadata
: JSON. Metadados do servidor por solicitação à UDF. Vazio por enquanto.preparedDataForAdRetrieval
: o conteúdo deste campo depende do anúncio de recuperação de desastres. No caso de recuperação de anúncios contextuais , esse parâmetro contêm os sinais brutos originados do dispositivo e transmitidos da no serviço de lances. No caso de recuperação de anúncios TEE usando o servidor de recuperação de anúncios, esse parâmetro conterá o resultado da UDFprepareDataForAdRetrieval
. Observação: neste estágio, os indicadores de apps protegidos seriam decodificados e descriptografados.deviceMetadata
: objeto JSON que contém metadados do dispositivo encaminhados pelo serviço de publicidade do vendedor. Consulte a documentação de B&A para mais detalhes.X-Accept-Language
: idioma usado no dispositivo.X-User-Agent
: user agent usado no dispositivo.X-BnA-Client-IP
: endereço IP do dispositivo.
contextualSignals
: string arbitrária originada dos lances contextuais operado pelo mesmo DSP. Espera-se que a UDF seja capaz de decodificar string e usá-la. Os indicadores de contexto podem conter informações, como ML informações da versão do modelo para o embedding protegido transmitido usando usando Indicadores de apps protegidos.
A UDF vai retornar uma string se for bem-sucedida. A string é retornada ao
servidor de lances, que o transmite para a UDF generateBid
. Embora o
pode ser uma string simples, provavelmente ela deve ser um
objeto serializado com um esquema definido para cada adtech por conta própria.
Não há restrição no esquema, desde que a generateBid
da adtech
lógica consegue reconhecer e usar a string.
Configurar o sistema para desenvolvimento
Android
Para configurar seu ambiente de desenvolvimento Android, siga estas etapas:
- Crie um emulador (recomendado) ou use um dispositivo físico com a imagem da prévia para desenvolvedores 10.
- Execute o comando abaixo:
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity
Em seguida, selecione a opção mostrada para consentir os anúncios sugeridos por apps.
- Execute o comando abaixo para ativar as APIs relevantes. Talvez seja necessário executar esse processo de novo de vez em quando, já que a configuração padrão de "desativado" será sincronizada periodicamente.
adb shell device_config put adservices fledge_custom_audience_service_kill_switch false; adb shell device_config put adservices fledge_select_ads_kill_switch false; adb shell device_config put adservices fledge_on_device_auction_kill_switch false; adb shell device_config put adservices fledge_auction_server_kill_switch false; adb shell "device_config put adservices disable_fledge_enrollment_check true"; adb shell device_config put adservices ppapi_app_allow_list '\*'; adb shell device_config put adservices fledge_auction_server_overall_timeout_ms 60000;
- Reinicie o dispositivo.
- Modifique as chaves de leilão do dispositivo para que elas apontem para seu servidor de chaves de leilão. É importante realizar essa etapa antes de tentar realizar um leilão para evitar que chaves incorretas sejam armazenadas em cache.
Serviços de lances e leilões
Para configurar os servidores de B&A, consulte a documentação de configuração de veiculação própria.
Este documento se concentra em como configurar os servidores específicos do comprador, já que não são necessárias mudanças para vendedores.
Pré-requisitos
Antes de implantar um conjunto de serviços de B&A, a adtech do comprador precisa:
- Confira se ele implantou o próprio serviço de recuperação de anúncios TEE (consulte a seção relevante).
- Conferir se a adtech tem todas as UDFs necessárias
(
prepareDataForAdRetrieval
,generateBid
,reportWin
eHandleRequest
) definidos e hospedados.
Também é útil ter uma compreensão de como o leilão protegido com a API Protected Audience funciona com B&A, mas não é necessário.
Configuração do Terraform
Para usar a API Protected App Signals, as adtechs precisam:
- Ativar o suporte à API Protected App Signals em B&A.
- Fornecer endpoints de URL em que as novas UDFs de
prepareDataForAdRetrieval, generateBid
ereportWin
possam ser buscadas.
Além disso, este guia presume que as adtechs que querem usar B&A para remarketing vão continuar definindo todas as flags de configuração atuais para o leilão de remarketing, como de costume.
Configuração da adtech do comprador
Usando este arquivo de demonstração como exemplo, os compradores precisam configurar estas flags:
- Enable Protected App Signals: ativada para coletar dados da API Protected App Signals.
- Protected App Signals URLs: definida para os URLs dos servidores da API Protected App Signals.
As adtechs precisam substituir os URLs corretos nos marcadores destes campos:
module "buyer" {
# ... More config here.
runtime_flags = {
# ... More config here.
ENABLE_PROTECTED_APP_SIGNALS = "true"
PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS = "60000"
TEE_AD_RETRIEVAL_KV_SERVER_ADDR = "<service mesh address of the instance>"
AD_RETRIEVAL_TIMEOUT_MS = "60000"
BUYER_CODE_FETCH_CONFIG = <<EOF
{
"protectedAppSignalsBiddingJsUrl": "<URL to Protected App Signals generateBid UDF>",
"urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
"urlFetchPeriodMs": 13000000,
"prepareDataForAdsRetrievalJsUrl": "<URL to the UDF>"
}
EOF
} # runtime_flags
} # Module "buyer"
Configuração da adtech do vendedor
Usando este arquivo de demonstração (link em inglês) como exemplo, os vendedores precisam definir estas flags. Observação: apenas as configurações relacionadas à API Protected App Signals estão destacadas. As adtechs precisam substituir os URLs corretos nos marcadores:
module "seller" {
# ... More config here.
runtime_flags = {
# ... More config here.
ENABLE_PROTECTED_APP_SIGNALS = "true"
SELLER_CODE_FETCH_CONFIG = <<EOF
{
"urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
"urlFetchPeriodMs": 13000000,
"protectedAppSignalsBuyerReportWinJsUrls": {"<Buyer Domain>": "URL to reportWin UDF"}
}
EOF
} # runtime_flags
} # Module "seller"
KV e serviços de recuperação de anúncios
Dependendo das estratégias escolhidas para oferecer suporte à recuperação de anúncios, o sistema
exigem a implantação de uma ou duas instâncias do serviço KV. Vamos indicar
instância KV usada para recuperação de anúncios baseada em TEE como a
Ad Retrieval Server
e à instância para oferecer suporte com base em caminho contextual
recuperação como KV Lookup Server
.
Em ambos os casos, a implantação dos servidores segue a documentação disponível no
KV server GitHub, a diferença entre os dois casos é que a consulta
inicial funciona sem qualquer configuração adicional, enquanto
A recuperação requer a implantação da UDF HandleRequest
para implementar
a lógica de recuperação. Para mais detalhes, confira o servidor KV
guia de integração (em inglês). A B&A espera que os dois serviços sejam
implantados na mesma malha de serviço que o serviço de lances.
Exemplo de configuração
Considere o seguinte cenário: usando a API Protected App Signals, uma adtech armazena indicadores relevantes com base no uso do app do usuário. No nosso exemplo, os indicadores são armazenados representando compras no app de vários apps. Durante um leilão, os indicadores criptografados são coletados e transmitidos para um leilão protegido em execução em B&A. As UDFs do comprador em execução em B&A usam os indicadores para buscar candidatos a anúncio e calcular um lance.
[Comprador] Exemplos de indicadores
Adiciona um indicador com uma chave de 0 e um valor de 1.
{
"put": {
"AA==": "AQ=="
},
"update_encoder": {
"action": "REGISTER",
"endpoint": "https://example.com/example_script"
}
}
Adiciona um indicador com uma chave de 1 e um valor de 2.
{
"put": {
"AQ==": "Ag=="
},
"update_encoder": {
"action": "REGISTER",
"endpoint": "https://example.com/example_script"
}
}
[Comprador] Exemplo de encodeSignals
Codifica cada indicador em dois bytes, sendo o primeiro o primeiro byte da chave de indicador e o segundo o primeiro byte do valor do indicador.
function encodeSignals(signals, maxSize) {
// if there are no signals don't write a payload
if (signals.size === 0) {
return {};
}
let result = new Uint8Array(signals.size * 2);
let index = 0;
for (const [key, values] of signals.entries()) {
result[index++] = key[0];
result[index++] = values[0].signal_value[0];
}
return { 'status': 0, 'results': result};
}
[Comprador] Exemplo de prepareDataForAdRetrieval
/**
* `encodedOnDeviceSignals` is a Uint8Array and would contain
* the app signals emanating from device. For purpose of the
* demo, in our sample example, we assume that device is sending
* the signals with pair of bytes formatted as following:
* "<id><In app spending>". Where id corresponds to an ad category
* that user uses on device, and the in app spending is a measure
* of how much money the user has spent in this app category
* previously. In our example, id of 0 will correspond to a
* fitness ad category and a non-zero id will correspond to
* food app category -- though this info will be useful
* later in the B&A pipeline.
*
* Returns a JSON object indicating what type of ad(s) may be
* most relevant to the user. In a real setup ad techs might
* want to decode the signals as part of this script.
*
* Note: This example script makes use of only encoded device signals
* but adtech can take other signals into account as well to prepare
* the data that will be useful down stream for ad retrieval and
* bid generation. The max length of the app signals used in this
* sample example is arbitrarily limited to 4 bytes.
*/
function prepareDataForAdRetrieval(encodedOnDeviceSignals,
encodedOnDeviceSignalsVersion,
sellerAuctionSignals,
contextualSignals) {
if (encodedOnDeviceSignals.length === 0 || encodedOnDeviceSignals.length > 4 ||
encodedOnDeviceSignals.length % 2 !== 0) {
throw "Expected encoded signals length to be an even number in (0, 4]";
}
var preparedDataForAdRetrieval = {};
for (var i = 0; i < encodedOnDeviceSignals.length; i += 2) {
preparedDataForAdRetrieval[encodedOnDeviceSignals[i]] = encodedOnDeviceSignals[i + 1];
}
return preparedDataForAdRetrieval;
}
[Compradores] Exemplo de UDF de recuperação de anúncios
No nosso exemplo, o servidor de extração de anúncios envia metadados (ou seja, o ID para cada anúncio no exemplo, mas pode conter outros dados para cada um que podem ser úteis na geração de lances mais tarde) para cada um dos principais candidatos a anúncio.
function HandleRequest(requestMetadata, protectedSignals, deviceMetadata,
contextualSignals) {
return "[{\"adId\":\"0\"},{\"adId\":\"1\"}]"
[Compradores] Exemplo de generateBid
/**
* This script receives the data returned by the ad retrieval service
* in the `ads` argument. This argument is supposed to contain all
* the Protected App Signals related ads and the metadata obtained from the retrieval
* service.
*
* `preparedDataForAdRetrieval` argument contains the data returned
* from the `prepareDataForAdRetrieval` UDF.
*
* This script is responsible for generating bids for the ads
* collected from the retrieval service and ad techs can decide to
* run a small inference model as part of this script in order to
* decide the best bid given all the signals available to them.
*
* For the purpose of the demo, this sample script assumes
* that ad retrieval service has sent us most relevant ads for the
* user and this scripts decides on the ad render URL as well as
* what value to bid for each ad based on the previously decoded
* device signals. For simplicity sake, this script only considers
* 2 types of app categories i.e. fitness and food.
*
* Note: Only one bid is returned among all the
* input ad candidates.
*/
function generateBid(ads, sellerAuctionSignals, buyerSignals, preparedDataForAdRetrieval) {
if (ads === null) {
console.log("No ads obtained from the ad retrieval service")
return {};
}
const kFitnessAd = "0";
const kFoodAd = "1";
const kBuyerDomain = "https://buyer-domain.com";
let resultingBid = 0;
let resultingRender = kBuyerDomain + "/no-ad";
for (let i = 0 ; i < ads.length; ++i) {
let render = "";
let bid = 0;
switch (ads[i].adId) {
case kFitnessAd:
render = kBuyerDomain + "/get-fitness-app";
bid = preparedDataForAdRetrieval[kFitnessAd];
break;
case kFoodAd:
render = kBuyerDomain + "/get-fastfood-app";
bid = preparedDataForAdRetrieval[kFoodAd];
break;
default:
console.log("Unknown ad category");
render = kBuyerDomain + "/no-ad";
break;
}
console.log("Existing bid: " + resultingBid + ", incoming candidate bid: " + bid);
if (bid > resultingBid) {
resultingBid = bid;
resultingRender = render;
}
}
return {"render": resultingRender, "bid": resultingBid};
}
[Compradores] Exemplo de reportWin
A UDF reportWin
informa ao comprador que ele venceu o leilão.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
buyerReportingSignals, directFromSellerSignals,
egressPayload,
temporaryUnlimitedEgressPayload) {
sendReportTo("https://buyer-controlled-domain.com/");
registerAdBeacon({"clickEvent":"https://buyer-controlled-domain.com/clickEvent"});
return;
}
[Vendedor] Configuração do servidor KV
Os vendedores precisam configurar um servidor KV de indicadores de pontuação para que haja um mapeamento
disponível dos URLs de renderização do anúncio para os indicadores de pontuação correspondentes. Por exemplo:
se https:/buyer-domain.com/get-fitness-app
e
https:/buyer-domain.com/get-fastfood-app
forem retornado pelo comprador,
o vendedor poderá receber este exemplo de resposta de indicador de pontuação quando consultado pelo
SFE usando um GET
em https://key-value-server-endpoint.com?client_type=1&renderUrls=<render-url-returned-by-the-buyer>
:
{
"renderUrls" : {
"https:/buyer-domain.com/get-fitness-app" : [
"1",
"2"
],
"https:/buyer-domain.com/get-fastfood-app" : [
"3",
"4"
]
}
}
[Vendedor] Exemplo de scoreAd
/**
* This module generates a random desirability score for the Protected App
* Signals ad in this example. In a production deployment,
* however, the sellers would want to use all the available signals to generate
* a score for the ad.
*/
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
function scoreAd(adMetadata, bid, auctionConfig,
trustedScoringSignals, deviceSignals,
directFromSellerSignals) {
return {
"desirability": getRandomInt(10000),
"allowComponentAuction": false
};
}
[Vendedor] Exemplo de reportResult
function reportResult(auctionConfig, sellerReportingSignals, directFromSellerSignals){
let signalsForWinner = {};
sendReportTo("https://seller-controlled-domain.com");
registerAdBeacon({"clickEvent":
"https://seller-controlled-domain.com/clickEvent"});
return signalsForWinner;
}
App de exemplo
Como exemplo de como a API pode ser usada para criar um app que usa um fluxo simples, conforme descrito acima, criamos um app de exemplo da API Protected App Signals, que pode ser encontrado neste repositório de exemplo (link em inglês).