Indicadores de apps protegidos para oferecer suporte a anúncios relevantes de instalação de apps

Essa proposta está sujeita ao processo de registro e atestados do Sandbox de privacidade. Para mais informações sobre os atestados, consulte o link de atestado fornecido. As atualizações futuras dessa proposta vão descrever os requisitos para ter acesso a esse sistema.

Os anúncios de instalação de apps para dispositivos móveis, também conhecidos como anúncios de aquisição de usuários, são um tipo de publicidade para dispositivos móveis criada para incentivar os usuários a fazer o download de um app. Normalmente, esses anúncios são veiculados aos usuários com base nos interesses e informações demográficas, e costumam aparecer em outros apps para dispositivos móveis, como jogos, mídias sociais e apps de notícias. Quando um usuário clica em um anúncio de instalação de apps, ele é direcionado diretamente à app store para fazer o download.

Por exemplo, um anunciante que está tentando gerar instalações de um novo app de entrega de comida para dispositivos móveis nos Estados Unidos pode segmentar os anúncios para usuários localizados no país e que já interagiram com outros apps de serviço de entrega de comida.

Isso geralmente é implementado com a inclusão de indicadores contextuais, próprios e de terceiros entre as adtechs para criar perfis de usuário com base nos IDs de publicidade. Os modelos de machine learning de adtech usam essas informações como entradas para escolher anúncios relevantes para o usuário e com maior probabilidade de resultar em uma conversão.

As seguintes APIs foram propostas para oferecer suporte a anúncios eficazes de instalação de apps que melhoram a privacidade do usuário, eliminando a dependência de identificadores de usuários entre partes diferentes:

  1. API Protected App Signals: é centrada no armazenamento e na criação de recursos de engenharia de adtech que representam os possíveis interesses de um usuário. As adtechs armazenam indicadores de eventos por app definidos automaticamente, como instalações de apps, primeiros acessos, ações do usuário (níveis no jogo, conquistas), atividades de compra ou tempo no app. Os indicadores são gravados e armazenados no dispositivo para evitar vazamento de dados e são disponibilizados apenas para a lógica de adtech que armazenou o indicador específico durante um leilão protegido executado em um ambiente seguro.
  2. API Ad Selection: oferece uma API para configurar e executar um leilão protegido em um ambiente de execução confiável (TEE), em que as adtechs recuperam os candidatos de anúncios, executam inferência, calculam lances e fazem a pontuação para escolher um anúncio "vencedor" usando os indicadores de apps protegidos e as informações contextuais em tempo real fornecidas pelo editor.
Diagrama mostrando o fluxo de instalação do app com indicadores protegidos
Fluxograma que mostra os indicadores de apps protegidos e o fluxo de trabalho de seleção de anúncios no Sandbox de privacidade do Android.

Confira uma visão geral de alto nível sobre como os indicadores de apps protegidos oferecem suporte a anúncios de instalação de apps relevantes. As seções a seguir deste documento dão mais detalhes sobre cada uma dessas etapas.

  • Seleção de indicadores: à medida que os usuários usam apps para dispositivos móveis, as adtechs selecionam os indicadores armazenando eventos de apps definidos por adtechs para veicular anúncios relevantes usando a API Protected App Signals. Esses eventos são armazenados em um armazenamento protegido no dispositivo, semelhante aos públicos-alvo personalizados, e criptografados antes de serem enviados do dispositivo, de modo que somente os serviços de lances e leilões executados em ambientes de execução confiáveis com o controle de privacidade e segurança adequados possam descriptografá-los para lances e pontuação de anúncios.
  • Codificação de indicadores: os indicadores são preparados em uma cadência programada, por uma lógica personalizada de adtech. Um job do Android em segundo plano executa essa lógica para realizar a codificação no dispositivo e gerar um payload de indicadores de apps protegidos que podem ser usados posteriormente em tempo real para seleção de anúncios durante um leilão protegido. O payload é armazenado com segurança no dispositivo até ser enviado para um leilão.
  • Seleção de anúncios: para selecionar anúncios relevantes para o usuário, os SDKs do vendedor enviam um payload criptografado dos Indicadores de apps protegidos e configuram um leilão protegido. No leilão, a lógica personalizada do comprador prepara os Indicadores de apps protegidos com os dados contextuais fornecidos pelo editor (dados normalmente compartilhados em uma solicitação de anúncio de RTB) para criar recursos destinados à seleção de anúncios (extração de anúncios, inferência e geração de lances). De forma semelhante à Protected Audience, os compradores enviam anúncios ao vendedor para pontuação final em um leilão protegido.
    • Recuperação de anúncios: os compradores usam indicadores de apps protegidos e dados contextuais fornecidos pelo editor para enganar recursos relevantes para os interesses do usuário. Esses recursos são usados para corresponder anúncios que atendem a critérios de segmentação. Os anúncios que não estão dentro do orçamento são filtrados. Os anúncios Top k são, então, selecionados para lances.
    • Lances: a lógica de lances personalizados dos compradores prepara os dados contextuais fornecidos pelo editor e os indicadores de apps protegidos para criar recursos. Eles são usados como entrada para modelos do machine learning do comprador para inferência e lances em anúncios candidatos dentro de limites confiáveis que preservam a privacidade. O comprador vai retornar o anúncio escolhido ao vendedor.
    • Pontuação do vendedor: a lógica de pontuação personalizada do vendedor pontua os anúncios enviados pelos Compradores participantes e escolhe um anúncio vencedor para ser enviado de volta ao app para renderização.
  • Relatórios: os participantes do leilão recebem os relatórios de vitórias e de perdas aplicáveis. Estamos analisando mecanismos que preservam a privacidade para incluir dados para o treinamento de modelo no relatório vencedor.

Cronograma

Prévia para desenvolvedores Beta
Engenharia de 4º trimestre de 2023 1º trimestre de 2024 2º trimestre de 2024 3º trimestre de 2024
APIs Signal Curation APIs de armazenamento no dispositivo Lógica da cota de armazenamento no dispositivo

Atualizações diárias da lógica personalizada no dispositivo
N/A Disponível para 1% dos dispositivos T+
Servidor de recuperação de anúncios em um TEE MVP Disponível no GCP

Suporte à produção
de UDFs Top-K
Disponível na AWS

Depuração consentida, métricas e monitoramento
Serviço de inferência em um TEE

Suporte à execução de modelos de ML e ao uso deles para dar lances em um TEE
Em desenvolvimento Disponível no GCP

Capacidade de implantar e criar protótipos de modelos estáticos de ML usando o Tensorflow e o PyTorch
Disponível na AWS

Implantação de modelo em produção para modelos do Tensorflow e do PyTorch

Telemetria, depuração consentida e monitoramento
Suporte a lances e leilões em um TEE

Disponível no GCP Integração de recuperação de anúncios PAS-B&A e TEE (com criptografia gRPC e TEE<>TEE)

Suporte à recuperação de anúncios pelo caminho contextual (inclui suporte a B&A<>K/V no TEE)
Disponível na AWS

Relatórios de depuração

Depuração consentida, métricas e monitoramento

Selecionar indicadores de apps protegidos

Um indicador é uma representação das várias interações do usuário em um app. Elas são determinadas pela adtech como úteis para veicular anúncios relevantes. Um app ou o SDK integrado pode armazenar ou excluir os Indicadores de apps protegidos definidos por adtechs com base na atividade do usuário, como aberturas do app, conquistas, atividade de compra ou tempo no app. Os indicadores de apps protegidos são armazenados com segurança no dispositivo e criptografados antes de serem enviados para fora do dispositivo, para que apenas os serviços de lances e leilões em execução em ambientes de execução confiável com controle de privacidade e segurança adequados possam descriptografá-los para lances e pontuação de anúncios. Assim como na API Custom Audience, os indicadores armazenados em um dispositivo não podem ser lidos ou inspecionados por apps ou SDKs. Não há uma API para ler os valores dos indicadores, e as APIs foram criadas para evitar o vazamento da presença de indicadores. A lógica personalizada de adtech protege o acesso aos indicadores selecionados a fim de criar recursos que servem como base para a seleção de anúncios em um leilão protegido.

API Protected App Signals

A API Protected App Signals oferece suporte para o gerenciamento de indicadores usando um mecanismo de delegação semelhante ao usado para públicos-alvo personalizados. A API Protected App Signals permite o armazenamento de indicadores na forma de um único valor escalar ou como uma série temporal. Indicadores de série temporal podem ser usados para armazenar itens como a duração da sessão do usuário. Os indicadores de série temporal oferecem um utilitário para aplicar uma determinada duração usando uma regra de remoção por ordem de chegada. O tipo de dado de um indicador escalar ou cada um dos elementos de um indicador de série temporal é uma matriz de bytes. Cada valor é aprimorado com o nome do pacote do aplicativo que armazenou o indicador e o carimbo de data/hora de criação da chamada de API de armazenamento de indicadores. Essas informações extras estão disponíveis no JavaScript de codificação de indicadores. Este exemplo mostra a estrutura dos indicadores de uma determinada adtech:

Este exemplo demonstra um indicador escalar e um de série temporal associados a adtech1.com:

  • Um indicador escalar com a chave de valor base64 "A1c" e o valor "c12Z". O armazenamento de indicadores foi acionado por com.google.android.game_app em 1º de junho de 2023.
  • Uma lista de indicadores com a chave "dDE" que foram criados por dois aplicativos diferentes.

As adtechs recebem uma determinada quantidade de espaço para armazenar indicadores no dispositivo. Os indicadores terão um TTL máximo, a ser determinado.

Os indicadores de apps protegidos serão removidos do armazenamento se o aplicativo gerador for desinstalado, impedido de usar a API Protected App Signals ou se os dados do app forem apagados pelo usuário.

A API Protected App Signals é composta pelas seguintes partes:

  • APIs Java e JavaScript para adicionar, atualizar ou remover indicadores.
  • Uma API JavaScript para processar os sinais persistentes e prepará-los para mais engenharia de atributos em tempo real durante um leilão protegido executado em um ambiente de execução confiável (TEE).

Adicionar, atualizar ou remover indicadores

As adtechs podem adicionar, atualizar ou remover indicadores com a API fetchSignalUpdates(). Essa API oferece suporte para a delegação semelhante à delegação de público-alvo personalizado da API Protected Audience.

Para adicionar um indicador, as adtechs do comprador que não têm uma presença em relação a SDK em apps precisam colaborar com aquelas que têm uma presença no dispositivo, como parceiros de medição para dispositivos móveis (MMPs, na sigla em inglês) e plataformas de fornecimento (SSPs). O objetivo da API Protected App Signals é oferecer suporte a essas adtechs, fornecendo soluções flexíveis para o gerenciamento de indicadores de apps protegidos, permitindo que os autores de chamadas no dispositivo invoquem a criação desses indicadores em nome dos compradores. Esse processo é chamado de delegação e usa a API fetchSignalUpdates(). fetchSignalUpdates() usa um URI e recupera uma lista de atualizações de indicador. Para ilustrar, fetchSignalUpdates() emite uma solicitação GET para o URI fornecido para recuperar a lista de atualizações a serem aplicadas ao armazenamento de indicador local. O endpoint do URL, de propriedade do comprador, responde com uma lista JSON de comandos.

Os comandos JSON aceitos são:

  • put: insere ou substitui um valor escalar para a chave especificada.
  • put_if_not_present: insere um valor escalar para a chave especificada, se nenhum valor estiver armazenado. Essa opção pode ser útil, por exemplo, para definir um ID do experimento para um determinado usuário e evitar a substituição dele, caso ele já tenha sido definido por outro aplicativo.
  • append: adiciona um elemento à série temporal associada à chave especificada. O parâmetro maxSignals especifica o número máximo de sinais na série temporal. Se o tamanho for excedido, os elementos anteriores serão removidos. Se a chave tiver um valor escalar, ela será transformada automaticamente em uma série temporal.
  • remove: remove o conteúdo associado à chave especificada.
{
   "put": {
    "A1c": "c12Z",
    "dDE": "d23d",
  },
  "put_if_not_present": {
    "aA9": "a1zfC3"
  }
  "append": {
    "bB1": {"values": ["gh12D", "d45g"], "maxSignals": 20}
  },
  "remove": ["c0D"]
}

Todas as chaves e valores são expressos em Base64.

Os comandos listados acima visam fornecer semânticas de inserção, substituição e exclusão para indicadores escalares, além de inserção, anexação e substituição completa de séries para indicadores de séries temporais. A semântica de exclusão e substituição em elementos específicos de um indicador de série temporal precisa ser gerenciada durante o processo de codificação e compactação. Por exemplo, durante a codificação, ignore valores em uma série temporal que são substituídos ou corrigidos por erros mais recentes e os exclua durante o processo de compactação.

Os indicadores armazenados são associados automaticamente ao aplicativo que executa a solicitação de busca e ao responsável pela solicitação (o "site" ou a "origem" de uma adtech registrada), além do horário de criação da solicitação. Todos os indicadores estão sujeitos ao armazenamento em nome de uma adtech registrada no Sandbox de privacidade. O "site"ou a "origem" do URI precisa corresponder aos dados de uma adtech inscrita. Se a adtech solicitante não estiver inscrita, a solicitação será rejeitada.

Cota de armazenamento e remoção

Cada adtech tem um espaço limitado no dispositivo do usuário para armazenar indicadores. Essa cota é definida por adtech. Portanto, os indicadores selecionados de diferentes apps compartilham a cota. Se a cota for excedida, o sistema vai liberar espaço removendo valores de indicadores anteriores por ordem de chegada. Para evitar que a remoção seja executada com muita frequência, o sistema implementa uma lógica de lote para permitir uma quantidade limitada de cotas excedente e liberar algum espaço extra quando a lógica de remoção for acionada.

Codificação no dispositivo para transmissão de dados

Para preparar os indicadores para a seleção de anúncios, a lógica personalizada por comprador tem acesso protegido aos indicadores e eventos armazenados por app. Um job em segundo plano do sistema Android é realizado de hora em hora para executar a lógica de codificação personalizada por comprador, que é transferida por download para o dispositivo. A lógica de codificação personalizada por comprador codifica os indicadores por app e, em seguida, compacta esses indicadores em um payload que esteja em conformidade com a cota por comprador. O payload é criptografado dentro dos limites do armazenamento do dispositivo protegido e transmitido para os serviços de lances e leilões.

As adtechs definem o nível de processamento de indicador processado pela própria lógica personalizada. Por exemplo, é possível instrumentar sua solução para descartar indicadores anteriores e agregar os semelhantes ou de reforço de aplicativos diferentes em novos indicadores que usam menos espaço.

Se um comprador não tiver registrado um codificador, os indicadores não serão preparados, e nenhum dos indicadores selecionados no dispositivo será enviado aos serviços de lances e leilões.

Mais detalhes sobre armazenamento, payload e cotas de solicitação serão disponibilizados em uma atualização futura. Além disso, vamos apresentar mais informações sobre como fornecer funções personalizadas.

Fluxo de trabalho de seleção de anúncios

Com essa proposta, o código personalizado de adtechs só pode acessar os indicadores de apps em um leilão protegido (API Ad Selection) em execução em um TEE. Para atender ainda mais às necessidades do caso de uso de instalação do app, os anúncios candidatos são buscados durante o leilão protegido em tempo real. Isso contrasta com o caso de uso de remarketing, em que os anúncios candidatos são conhecidos antes do leilão.

Esta proposta usa um fluxo de trabalho de seleção de anúncios semelhante ao da proposta da API Protected Audience com atualizações para oferecer suporte ao caso de uso de instalação de apps. Para oferecer suporte aos requisitos de computação da engenharia de atributos e da seleção de anúncios em tempo real, os leilões de anúncios de instalação de apps precisam ser executados em serviços de lances e leilões em execução em TEEs. O acesso a indicadores de apps protegidos durante um leilão protegido não tem suporte em leilões no dispositivo.

Ilustração do fluxo de trabalho de seleção de anúncios.
O fluxo de trabalho de seleção de anúncios no Sandbox de privacidade do Android.

O fluxo de trabalho de seleção de anúncios é o seguinte:

  1. O SDK do vendedor envia o payload criptografado dos indicadores de app protegido no dispositivo.
  2. O servidor do vendedor cria uma configuração de leilão e a envia ao serviço de lances e leilões confiáveis do vendedor, junto com o payload criptografado, para iniciar um fluxo de trabalho de seleção de anúncios.
  3. O serviço de lances e leilões do vendedor transmite o payload para os servidores de front-end dos compradores confiáveis participantes.
  4. O serviço de lances do comprador executa a lógica de seleção de anúncios do lado do comprador
    1. Execução da lógica de recuperação de anúncios de compra.
    2. Execução da lógica de lances da compra.
  5. A lógica de pontuação da venda é executada.
  6. O anúncio é renderizado e a geração de relatórios é iniciada.

Iniciar o fluxo de trabalho da seleção de anúncios

Quando um aplicativo estiver pronto para mostrar um anúncio, o SDK de adtechs (normalmente SSPs) inicia o fluxo de trabalho de seleção de anúncios enviando todos os dados contextuais relevantes do editor e dos payloads criptografados por comprador que serão incluídos na solicitação a ser enviada ao leilão protegido usando a chamada getAdSelectionData. Essa é a mesma API usada para o fluxo de trabalho de remarketing e descrita na proposta Integração de lances e leilões para Android.

Para iniciar a seleção de anúncios, o vendedor transmite uma lista de compradores participantes e o payload criptografado dos indicadores de apps protegidos no dispositivo. Com essas informações, o servidor de anúncios do lado do vendedor prepara uma SelectAdRequest para o serviço SellerFrontEnd confiável.

O vendedor define o seguinte:

Execução da lógica de seleção de anúncios de compra

Em um alto nível, a lógica personalizada do comprador usa dados contextuais fornecidos pelo editor e pelos indicadores de apps protegidos para selecionar e aplicar um lance aos anúncios relevantes para a solicitação de anúncio. A plataforma permite que os compradores restrinjam um grande conjunto de anúncios disponíveis aos mais relevantes (os Top-K), para os quais os lances são calculados antes dos anúncios serem retornados ao vendedor para a seleção final.

Ilustração da lógica de execução da seleção de anúncios da compra.
Lógica de execução da seleção de anúncios de compra no Sandbox de privacidade do Android.

Antes de dar lances, os compradores começam com um grande conjunto de anúncios. Calcular um lance para cada anúncio é muito lento. Por isso, os compradores precisam selecionar os candidatos Top-K do grande conjunto. Em seguida, os compradores precisam calcular os lances para cada um desses candidatos Top-K. Então, esses anúncios e lances são retornados ao vendedor para a seleção final.

  1. O serviço BuyerFrontEnd recebe uma solicitação de anúncio.
  2. O serviço BuyerFrontEnd envia uma solicitação ao serviço de lances do comprador. O serviço de lances do comprador executa uma UDF chamada prepareDataForAdRetrieval(), que cria uma solicitação para receber os principais k candidatos do serviço de recuperação de anúncios. O serviço de lances envia essa solicitação para o endpoint do servidor de recuperação configurado.
  3. O serviço de recuperação de anúncios executa a UDF getCandidateAds(), que filtra o conjunto de principais anúncios candidatos, que são enviados ao serviço de lances do comprador.
  4. O serviço de lances do comprador executa a UDF generateBid(), que escolhe o melhor candidato, calcula o lance e o retorna ao serviço BuyerFrontEnd.
  5. O serviço BuyerFrontEnd retorna os anúncios e os lances ao vendedor.

Há vários detalhes importantes sobre esse fluxo, especialmente em relação a como as peças se comunicam entre si e como a plataforma fornece recursos como a capacidade de fazer previsões de machine learning para recuperar os anúncios Top-K e calcular os lances.

Antes de analisarmos mais detalhadamente as partes, há algumas observações importantes sobre a arquitetura dos TEEs no diagrama acima.

O serviço de lances do comprador contém internamente um serviço de inferência. As adtechs podem fazer upload de modelos de machine learning para o serviço de lances do comprador. Vamos fornecer APIs JavaScript para que as adtechs façam previsões ou gerem embeddings desses modelos nas UDFs em execução no serviço de lances do comprador. Ao contrário do serviço de recuperação de anúncios, o serviço de lances do comprador não tem um serviço de chave-valor para armazenar metadados de anúncios.

O serviço de recuperação de anúncios inclui internamente um serviço de chave-valor. As adtechs podem materializar pares de chave-valor nesse serviço usando os próprios servidores, fora do limite de privacidade. Vamos fornecer uma API JavaScript para que as adtechs leiam esse serviço de chave-valor nas UDFs em execução no serviço de recuperação de anúncios. Ao contrário do serviço de lances do comprador, o serviço de recuperação de anúncios não contém um serviço de inferência.

Uma pergunta central que esse design aborda é como fazer previsões no momento da recuperação e do lance. A resposta para ambos pode envolver uma solução chamada fatoração de modelo.

Fatoração de modelos

A fatoração de modelos é uma técnica que permite dividir um único modelo em várias partes e, em seguida, combiná-las em uma previsão. No caso de uso de instalação de apps, os modelos geralmente usam três tipos de dados: dados do usuário, contextuais e de anúncios.

No caso não fatorado, um único modelo é treinado nos três tipos de dados. No caso fatorado, dividimos o modelo em várias partes. Apenas a parte que contém os dados do usuário é confidencial. Isso significa que apenas o modelo com a parte do usuário precisa ser executado dentro do limite de confiança, no serviço de inferência do serviço de lances do comprador.

Isso possibilita o seguinte design:

  1. Dividir o modelo em uma parte particular (os dados do usuário) e uma ou mais partes não particulares (os dados contextuais e do anúncio).
  2. Transmitir algumas ou todas as partes não particulares como argumentos para uma UDF que precisa fazer previsões. Por exemplo, os embeddings contextuais são transmitidos para UDFs no per_buyer_signals.
  3. As adtechs podem criar modelos para partes não particulares e materializar os embeddings desses modelos no armazenamento de chave-valor do serviço de recuperação de anúncios. As UDFs no serviço de recuperação de anúncios podem buscar esses embeddings no ambiente de execução.
  4. Para fazer uma previsão durante uma UDF, combine embeddings particulares do serviço de inferência com embeddings não particulares de argumentos de função da UDF ou do armazenamento de chave-valor com uma operação como um produto escalar. Esta é a previsão final.

Com isso explicado, podemos analisar cada UDF em mais detalhes. Vamos explicar o que elas fazem, como se integram e como podem fazer as previsões necessárias para escolher os anúncios Top-K e calcular os lances.

A UDF prepareDataForAdRetrieval()

A prepareDataForAdRetrieval() em execução no serviço de lances do comprador é responsável por criar o payload da solicitação que será enviado ao serviço de recuperação de anúncios para buscar os anúncios candidatos Top-K.

A prepareDataForAdRetrieval() recebe as seguintes informações:

A prepareDataForAdRetrieval() faz duas coisas:

  • Caracterização: se a inferência no tempo de recuperação for necessária, ela vai transformar os indicadores de entrada em atributos para uso durante chamadas ao serviço de inferência e receber embeddings particulares para recuperação.
  • Calcula embeddings particulares para recuperação: se forem necessárias previsões de recuperação, ele faz a chamada no serviço de inferência usando os atributos acima e recebe um embedding particular para previsões de tempo de recuperação.

A prepareDataForAdRetrieval() retorna:

  • Indicadores de apps protegidos: payload de indicadores selecionados por adtechs.
  • Indicadores específicos de leilão: indicadores do vendedor específicos da plataforma e informações contextuais, como auction_signals e per_buyer_signals, (incluindo embeddings contextuais) de SelectAdRequest. Isso é semelhante à API Protected Audience.
  • Indicadores adicionais: informações extras, como embeddings particulares recuperados do serviço de inferência.

Essa solicitação é enviada ao serviço de recuperação de anúncios, que faz a correspondência de candidatos e executa a UDF getCandidateAds().

A UDF getCandidateAds()

A getCandidateAds() é executada no serviço de recuperação de anúncios. Recebe a solicitação criada por prepareDataForAdRetrieval() no serviço de lances do comprador. O serviço executa getCandidateAds(), que busca os candidatos Top-K para lances convertendo a solicitação em uma série de consultas definidas, buscas de dados e executando lógica de negócios personalizada e outra lógica de recuperação personalizada.

A getCandidateAds() recebe as seguintes informações:

  • Indicadores de apps protegidos: payload de indicadores selecionados por adtechs.
  • Indicadores específicos de leilão: indicadores do vendedor específicos da plataforma e informações contextuais, como auction_signals e per_buyer_signals, (incluindo embeddings contextuais) de SelectAdRequest. Isso é semelhante à API Protected Audience.
  • Indicadores adicionais: informações extras, como embeddings particulares recuperados do serviço de inferência.

A getCandidateAds() realiza as seguintes ações:

  1. Buscar um conjunto inicial de candidatos de anúncios: buscados usando critérios de segmentação, como idioma, região geográfica, tipo e tamanho do anúncio ou orçamento, para filtrar os candidatos.
  2. Busca de embedding de recuperação: se os embeddings do serviço de chave-valor forem necessários para fazer uma previsão do tempo de recuperação para a seleção do Top-K, eles precisarão ser recuperados do serviço de chave-valor.
  3. Seleção de candidato Top-K: calcule uma pontuação leve para o conjunto filtrado de candidatos de anúncios com base nos metadados buscados no armazenamento de chave-valor e nas informações enviadas do serviço de lances do comprador para escolher os candidatos Top-K com base nessa pontuação. Por exemplo, a pontuação pode ser a chance de instalar um app de acordo com o anúncio.
  4. Busca de incorporação de lances: se os embeddings do serviço de chave-valor forem necessários pelo código de lances para fazer previsões no momento dos lances, eles poderão ser recuperados do serviço de chave-valor.

A pontuação de um anúncio pode ser o resultado de um modelo preditivo, que, por exemplo, prevê a probabilidade de um usuário instalar um app. Esse tipo de geração de pontuação envolve um tipo de fatoração do modelo: como getCandidateAds() é executada no serviço de recuperação de anúncios e ela não tem um serviço de inferência, as previsões podem ser geradas com a combinação de:

  • Embeddings contextuais transmitidos usando a entrada de indicadores específicos do leilão.
  • Os embeddings particulares são transmitidos usando a entrada de indicadores adicionais.
  • Todas as adtechs de embeddings não particulares foram materializadas dos servidores para o serviço de chave-valor do serviço de recuperação de anúncios.

A UDF generateBid() executada no serviço de lances do comprador também pode aplicar o próprio tipo de fatoração de modelos para fazer previsões de lances. Caso seja necessário algum embedding de um serviço de chave-valor para fazer isso, ele precisa ser buscado agora.

A getCandidateAds() retorna:

  • Anúncios candidatos: os anúncios Top-K a serem transmitidos para a generateBid(). Cada anúncio é composto pelo seguinte:
    • URL de renderização: o endpoint para renderizar o criativo do anúncio.
    • Metadados: metadados de anúncios para compra específicos de tecnologias de publicidade. Por exemplo, isso pode incluir informações sobre a campanha publicitária e critérios de segmentação, como local e idioma. Os metadados podem incluir incorporações opcionais usadas quando a fatoração de modelos é necessária para executar a inferência durante os lances.
  • Indicadores adicionais: opcionalmente, o serviço de recuperação de anúncios pode incluir informações extras, como embeddings ou indicadores de spam extras, a serem usados no generateBid().

Estamos investigando outros métodos para fornecer anúncios que recebem pontuação, incluindo a disponibilização deles como parte da chamada SelectAdRequest. Esses anúncios podem ser recuperados com uma solicitação de lance de RTB. Nesses casos, os anúncios precisam ser recuperados sem os indicadores de apps protegidos. As adtechs vão avaliar as compensações antes de escolher a melhor opção, incluindo o tamanho do payload da resposta, a latência, o custo e a disponibilidade dos indicadores.

A UDF generateBid()

Depois de recuperar o conjunto de anúncios candidatos e os embeddings durante a recuperação, é possível prosseguir para os lances, que são executados no serviço de lances do comprador. Esse serviço executa a UDF generateBid() fornecida pelo comprador para selecionar o anúncio para dar lances no Top-K e o retornar com o lance.

A generateBid() recebe as seguintes informações:

  • Anúncios candidatos: os anúncios Top-K retornados pelo serviço de recuperação de anúncios.
  • Indicadores específicos de leilão: indicadores do vendedor específicos da plataforma e informações contextuais, como auction_signals e per_buyer_signals, (incluindo embeddings contextuais) de SelectAdRequest.
  • Indicadores adicionais: informações extras a serem usadas no momento dos lances.

A implementação da generateBid() do comprador faz três coisas:

  • Destaque: transforma sinais em atributos para uso durante a inferência.
  • Inferência: gera previsões usando modelos de machine learning para calcular valores como taxas de cliques e de conversão previstas.
  • Lances: combinação de valores inferidos com outras entradas para calcular o lance de um anúncio candidato.

A generateBid() retorna:

  • O anúncio candidato.
  • O valor do lance calculado.

A generateBid() usada para anúncios de instalação de apps e o usado para anúncios de remarketing são diferentes.

As seções a seguir descrevem a funcionalidades, a inferência e os lances em mais detalhes.

Caracterização

Os indicadores de leilão podem ser preparados em recursos pela generateBid(). Esses recursos podem ser usados durante a inferência para prever dados como taxas de cliques e de conversão. Também estamos analisando mecanismos de preservação de privacidade para transmitir alguns deles no relatório de ganhos para uso no treinamento de modelo.

Inferência

Ao calcular um lance, é comum realizar inferências em um ou mais modelos de machine learning. Por exemplo, cálculos de eCPM eficazes geralmente usam modelos para prever as taxas de cliques e de conversão.

Os clientes podem fornecer vários modelos de machine learning com a implementação da generateBid(). Também vamos fornecer uma API JavaScript na generateBid() para que os clientes possam realizar inferência no momento da execução.

A inferência é executada no serviço de lances do comprador. Isso pode afetar a latência e o custo de inferência, especialmente porque os aceleradores ainda não estão disponíveis nos TEEs. Alguns clientes vão perceber que as necessidades deles foram atendidas com modelos individuais em execução no serviço de lances do comprador. Outros clientes, por exemplo, aqueles com modelos muito grandes, podem querer considerar opções como fatoração de modelos para minimizar o custo de inferência e a latência no momento do lance.

Mais informações sobre recursos de inferência, como formatos de modelo com suporte e tamanhos máximos, serão fornecidas em uma atualização futura.

Implementar fatoração de modelos

Anteriormente, explicamos a fatoração de modelos. No momento do lance, a abordagem específica é:

  1. Dividir o modelo único em uma parte particular (os dados do usuário) e uma ou mais partes não particulares (os dados contextuais e do anúncio).
  2. Transmitir partes não particulares para generateBid(). Elas podem vir de per_buyer_signals ou de embeddings que as adtechs calculam externamente, se materializam no armazenamento de chave-valor do serviço de recuperação, buscam no momento da recuperação e retornam como parte dos indicadores. Isso não inclui embeddings particulares, porque eles não podem ser provenientes de fora do limite de privacidade.
  3. Em generateBid():
    1. Realizar a inferência em modelos para receber embeddings particulares do usuário.
    2. Combinar embeddings particulares de usuários com contextuais de per_buyer_signals ou anúncios não particulares e embeddings contextuais do serviço de recuperação usando uma operação como um produto escalar. Essa é a previsão final que pode ser usada para calcular lances.

Com essa abordagem, é possível realizar inferências no momento do lance em modelos que seriam muito grandes ou lentos para execução no serviço de lances do comprador.

Lógica de pontuação de venda

Nessa etapa, os anúncios com lances recebidos de todos os compradores participantes são pontuados. O resultado da generateBid() é transmitido ao serviço de leilão do vendedor para executar scoreAd() e que scoreAd() considera apenas um anúncio por vez. Com base na pontuação, o vendedor escolhe um anúncio vencedor para retornar ao dispositivo para renderização.

A lógica de pontuação é a mesma usada para o fluxo de remarketing da API Protected Audience, e consegue selecionar um vencedor entre os candidatos à instalação de apps e remarketing. A função é chamada uma vez para cada anúncio candidato enviado no leilão protegido. Consulte a explicação sobre Lances e leilão para mais detalhes.

Tempo de execução do código de seleção de anúncios

Na proposta, o código de seleção de anúncios para a instalação de apps é especificado da mesma maneira que o fluxo de remarketing da API Protected Audience. Para ver mais detalhes, consulte a Configuração de lances e leilões. O código de lances vai estar disponível no mesmo local de armazenamento em nuvem usado para remarketing.

Relatório

Essa proposta usa as mesmas APIs Reporting que a proposta de relatório da Protected Audience (link em inglês), por exemplo, reportImpression(), que aciona a plataforma para enviar relatórios de vendedor e comprador.

Um caso de uso comum para gerar relatórios no lado da compra é conseguir os dados de treinamento para modelos usados durante a seleção de anúncios. Além das APIs atuais, a plataforma vai fornecer um mecanismo específico para enviar dados de evento da plataforma para os servidores de adtechs. Esses payloads de saída podem incluir determinados dados do usuário.

A longo prazo, estamos investigando soluções que preservam a privacidade para abordar o treinamento de modelos com dados usados em leilões protegidos sem enviar dados do usuário no nível do evento para fora dos serviços executados em TEEs. Vamos divulgar mais detalhes em uma atualização futura.

A curto prazo, forneceremos uma maneira temporária de saída de dados com ruído do generateBid(). Confira abaixo nossa proposta inicial para isso (incluindo possíveis mudanças incompatíveis com versões anteriores) em resposta ao feedback do setor.

Tecnicamente, a maneira como isso funciona é:

  1. As adtechs definem um esquema para os dados que querem transmitir.
  2. Em generateBid(), eles criam o payload de saída desejado.
  3. A plataforma valida o payload de saída em relação ao esquema e aplica limites de tamanho.
  4. A plataforma adiciona ruído ao payload de saída.
  5. O payload de saída é incluído no relatório de vitórias em formato eletrônico, é recebido em servidores de adtechs, decodificado e usado para treinamento de modelo.

Definir o esquema de payloads de saída

Para que a plataforma aplique os requisitos de privacidade em evolução, os payloads de saída precisam ser estruturados de maneira que a plataforma possa entender. As adtechs vão definir a estrutura dos payloads de saída fornecendo um arquivo JSON de esquema. Esse esquema será processado pela plataforma e mantido em sigilo pelos serviços de lances e leilões usando os mesmos mecanismos de outros recursos de adtech, como UDFs e modelos.

Fornecemos um arquivo CDDL que define a estrutura desse JSON. O arquivo CDDL inclui um conjunto de tipos de recursos compatíveis (por exemplo, recursos booleanos, números inteiros, buckets e assim por diante). O arquivo CDDL e o esquema fornecido terão controle de versão.

Por exemplo, um payload de saída que consiste em um único recurso booleano seguido por um recurso de bucket de tamanho dois seria semelhante a:

egressPayload = {
  features : [
    {
      type: "boolean_feature",
      value: false
    },
    {
      type: "bucket_feature",
      size: 2,
      value: [
        {
          value: false
        },
        {
          value: true
        }
      ]
    }
  ]
}

Detalhes sobre o conjunto de tipos de recursos compatíveis estão disponíveis no GitHub (em inglês).

Crie payloads de saída em generateBid()

Todos os indicadores de apps protegidos de um determinado comprador estão disponíveis para a UDF generateBid() dele. Depois de recursos, as adtechs criam o payload no formato JSON. Esse payload de saída vai ser incluído no relatório de ganhos do comprador para transmissão aos servidores de adtechs.

Uma alternativa a esse design é que o cálculo do vetor de saída ocorra em reportWin() em vez de generateBid(). Há vantagens e desvantagens em cada abordagem, e vamos finalizar essa decisão em resposta ao feedback do setor.

Validar o payload de saída

A plataforma valida qualquer payload de saída criado pela adtech. A validação garante que os valores dos recursos sejam válidos para os tipos deles, as restrições de tamanho sejam atendidas e que os agentes mal-intencionados não estejam tentando burlar os controles de privacidade ao incluir mais informações nos payloads de saída.

Se um payload de saída for inválido, ele será descartado silenciosamente das entradas enviadas ao relatório de vitórias. Isso ocorre porque não queremos fornecer informações de depuração a qualquer usuário de má-fé que tente burlar a validação.

Forneceremos uma API JavaScript para adtechs para garantir que o payload de saída que criam em generateBid() seja aprovado na validação da plataforma:

validate(payload, schema)

Essa API JavaScript serve exclusivamente para que os autores de chamadas determinem se um payload específico será aprovado na validação da plataforma. A validação real precisa ser feita na plataforma para proteger contra UDFs generateBid() maliciosas.

Fazer ruído no payload de saída

A plataforma fará o ruído dos payloads de saída antes de incluí-los no relatório vencedor. O limite de ruído inicial será de 1%, e esse valor pode evoluir com o tempo. A plataforma não fornecerá indicação se um payload de saída específico recebeu ruído.

O método de ruído é:

  1. A plataforma carrega a definição do esquema para o payload de saída.
  2. 1% dos payloads de saída serão escolhidos para ruído.
  3. Se um payload de saída não for escolhido, todo o valor original será mantido.
  4. Se um payload de saída for escolhido, o valor de cada recurso será substituído por um valor válido aleatório para esse tipo de recurso. Por exemplo, 0 ou 1 para um recurso booleano.

Como transmitir, receber e decodificar o payload de saída para treinamento de modelo

O payload de saída com ruído e validado será incluído nos argumentos para reportWin() e transmitido aos servidores de adtechs do comprador fora do limite de privacidade para o treinamento do modelo. O payload de saída vai estar no formato de ligação.

Detalhes sobre o formato de fio para todos os tipos de recursos e para o próprio payload de saída estão disponíveis no GitHub (link em inglês).

Determinar o tamanho do payload de saída

O tamanho do payload de saída em bits equilibra a utilidade e a minimização de dados. Vamos trabalhar com o setor para determinar o tamanho adequado por testes. Enquanto realizamos esses experimentos, sairemos temporariamente dos dados sem limitação no tamanho de bits. Esses dados de saída adicionais sem limitação de tamanho de bits serão removidos quando os experimentos forem concluídos.

O método para determinar o tamanho é:

  1. Inicialmente, dois payloads de saída serão aceitos em generateBid():
    1. egressPayload: o payload de saída de tamanho limitado descrito até agora neste documento. Inicialmente, o tamanho desse payload de saída será 0 bits (ou seja, ele sempre será removido durante a validação).
    2. temporaryUnlimitedEgressPayload: um payload de saída temporário com tamanho ilimitado para experimentos de tamanho. A formatação, a criação e o processamento desse payload de saída usam os mesmos mecanismos que egressPayload.
  2. Cada um desses payloads de saída terá o próprio arquivo JSON de esquema: egress_payload_schema.json e temporary_egress_payload_schema.json.
  3. Fornecemos um protocolo de experimento e um conjunto de métricas para determinar a utilidade do modelo em vários tamanhos de payload de saída (por exemplo, 5, 10, ... bits).
  4. Com base nos resultados do experimento, determinamos o tamanho do payload de saída com as compensações corretas de utilidade e privacidade.
  5. Definimos o tamanho de egressPayload de 0 bits para o novo tamanho.
  6. Após um período de migração definido, removemos temporaryUnlimitedEgressPayload, deixando apenas egressPayload com o novo tamanho.

Estamos investigando outras proteções técnicas para gerenciar essa mudança, por exemplo, criptografar egressPayload quando aumentarmos o tamanho dele de 0 bits. Esses detalhes, além do cronograma do experimento e da remoção de temporaryUnlimitedEgressPayload, serão incluídos em uma atualização futura.

Em seguida, explicaremos um possível protocolo de experimento para finalizar o tamanho de egressPayload. Nosso objetivo é trabalhar com a indústria para encontrar um tamanho que equilibre utilidade e minimização de dados. O artefato que esses experimentos produzirão é um gráfico em que o eixo x é o tamanho do payload de treinamento em bits e o eixo y é a porcentagem de receita gerada por um modelo nesse tamanho em comparação com um valor de referência ilimitado de tamanho.

Vamos supor que estamos treinando um modelo de pInstall e que nossas fontes de dados de treinamento são nossos registros e o conteúdo dos temporaryUnlimitedegressPayloads que recebemos quando vencemos leilões. O protocolo para adtechs envolve experimentos off-line primeiro:

  1. Determine a arquitetura dos modelos que eles vão usar com os indicadores de apps protegidos. Por exemplo, eles precisarão determinar se usarão ou não a fatoração de modelos.
  2. Defina uma métrica para medir a qualidade do modelo. As métricas sugeridas são Perda de AUC e Log.
  3. Defina o conjunto de atributos que serão usados durante o treinamento do modelo.
  4. Usando essa arquitetura de modelo, métrica de qualidade e conjunto de recursos de treinamento, execute estudos de ablação para determinar a utilidade atribuída por bit para cada modelo que eles querem usar no PAS. O protocolo sugerido para o estudo de ablação é:
    1. Treine o modelo com todos os recursos e meça a utilidade. Essa é a referência para comparação.
    2. Treine o modelo com todos os recursos usados para produzir o valor de referência, exceto esse.
    3. Meça a utilidade resultante. Divida o delta pelo tamanho do atributo em bits. Esse é o utilitário esperado por bit para o atributo.
  5. Determine os tamanhos de payload de treinamento de interesse para experimentação. Sugerimos [5, 10, 15, ..., size_of_all_training_features_for_baseline] bits. Cada um deles representa um tamanho possível para egressPayload que o experimento vai avaliar.
  6. Para cada tamanho possível, selecione um conjunto de atributos menor ou igual a esse tamanho que maximize a utilidade por bit, usando os resultados do estudo de ablação.
  7. Treine um modelo para cada tamanho possível e avalie a utilidade dele como uma porcentagem da utilidade do modelo de referência treinado em todos os recursos.
  8. Coloque os resultados em um gráfico em que o eixo x é o tamanho do payload de treinamento em bits e o eixo y é a porcentagem de receita gerada por esse modelo em comparação com o valor de referência.

Em seguida, as adtechs podem repetir as etapas de 5 a 8 em experimentos de tráfego em tempo real usando dados de recursos enviados por temporaryUnlimitedEgressPayload. As adtechs podem optar por compartilhar os resultados dos experimentos de tráfego off-line e em tempo real com o Sandbox de privacidade para tomar decisões sobre o tamanho de egressPayload.

O cronograma desses experimentos, bem como o de definição do tamanho de egressPayload como o valor resultante, está além do escopo deste documento e será atualizado em uma atualização futura.

Medidas de proteção de dados

Aplicaremos uma série de proteções aos dados de saída, incluindo:

  1. egressPayload e temporaryUnlimitedEgressPayload vão receber ruído.
  2. Para minimização e proteção de dados, temporaryUnlimitedEgressPayload vai estar disponível apenas durante os experimentos de tamanho, em que vamos determinar o tamanho correto para egressPayload.

Permissões

Controle do usuário

  • A proposta tem o objetivo de oferecer aos usuários acesso à lista de apps instalados que armazenaram pelo menos um indicador de app protegido ou um público-alvo personalizado.
  • Os usuários podem bloquear e remover apps dessa lista. O bloqueio e a remoção fazem o seguinte:
    • Limpa todos os indicadores de apps protegidos e públicos-alvo personalizados associados ao app.
    • Impedem que os apps armazenem novos públicos-alvo personalizados e indicadores de app protegidos.
  • Os usuários podem redefinir completamente os indicadores de apps protegidos e a API Protected Audience. Quando isso acontece, todos os indicadores de apps protegidos e públicos-alvo personalizados existentes no dispositivo são apagados.
  • Os usuários podem desativar completamente o Sandbox de privacidade do Android, que inclui a API Protected App Signals e a API Protected Audience. Quando esse é o caso, as APIs Protected Audience e Protected App Signals retornam uma mensagem de exceção padrão: SECURITY_EXCEPTION.

Permissões e controle do app

A proposta tem como objetivo oferecer aos apps controle sobre os indicadores de apps protegidos:

  • Um app pode gerenciar as próprias associações com os indicadores de apps protegidos.
  • Um app pode conceder permissões a plataformas de adtech terceirizadas para gerenciar indicadores de apps protegidos em nome dele.

Controle da plataforma de adtech

Esta proposta descreve maneiras que as adtechs podem usar para controlar os indicadores de apps protegidos:

  • Todas as adtechs precisam se inscrever no Sandbox de privacidade e fornecer um domínio "site" ou "origem" que corresponda a todos os URLs para indicadores de apps protegidos.
  • As adtechs podem fazer parcerias com apps ou SDKs para fornecer tokens de verificação usados para conferir a criação de indicadores de apps protegidos. Quando esse processo é delegado a um parceiro, a criação de indicadores de apps protegidos pode ser configurada para exigir confirmação da adtech.