Guia do desenvolvedor Android para a API Protected Audience

Ao ler a documentação do Sandbox de privacidade do Android, use o botão Prévia para desenvolvedores ou Beta para selecionar a versão do programa com que você está trabalhando, porque as instruções podem variar.


Enviar feedback

A API Protected Audience no Android (anteriormente conhecida como FLEDGE) inclui a API Custom Audience e a API Ad Selection. As plataformas de adtech e os anunciantes podem usar essas APIs para veicular anúncios personalizados com base no engajamento anterior no app, limitando o compartilhamento de identificadores entre apps e o de informações sobre interações do usuário com terceiros.

A API Custom Audience tem como foco a abstração do "público-alvo personalizado", que representa um grupo de usuários com intenções em comum. Um anunciante pode registrar um usuário em um público-alvo personalizado e associar anúncios relevantes a ele. Essas informações são armazenadas localmente e podem ser usadas para informar lances de anunciantes, filtragem e renderização de anúncios.

A API Ad Selection oferece um framework para que vários desenvolvedores façam um leilão localmente para um público-alvo personalizado. Para isso, o sistema considera anúncios relevantes associados ao público-alvo personalizado e executa outros processamentos nos anúncios que uma plataforma de adtech retorna ao dispositivo.

As plataformas de tecnologias de publicidade podem integrar essas APIs para implementar o remarketing, que preserva a privacidade dos usuários. O suporte a outros casos de uso, incluindo anúncios de instalação de apps, está planejado para versões futuras. Consulte a proposta de design para saber mais sobre a API Protected Audience.

Este guia descreve como trabalhar com essa API no Android para fazer o seguinte:

  1. Gerenciar públicos-alvo personalizados
  2. Configurar e executar a seleção de anúncios em um dispositivo
  3. Gerar relatórios de impressões de anúncio

Antes de começar

Antes de começar, siga estas etapas:

  1. Configure seu ambiente de desenvolvimento para o Sandbox de privacidade do Android.
  2. Instale uma imagem do sistema em um dispositivo com suporte ou configure um emulador que inclua suporte ao Sandbox de privacidade do Android.
  3. Em um terminal, ative o acesso à API Protected Audience (desativada por padrão) com o seguinte comando adb:

      adb shell device_config put adservices ppapi_app_allow_list \"*\"
    
  4. Inclua uma permissão ACCESS_ADSERVICES_CUSTOM_AUDIENCE no manifesto do app:

      <uses-permission android:name="android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCE" />
    
  5. Faça referência a uma configuração de serviços de publicidade no elemento <application> do manifesto:

      <property android:name="android.adservices.AD_SERVICES_CONFIG"
                android:resource="@xml/ad_services_config" />
    
  6. Especifique o recurso XML dos serviços de publicidade referenciados no manifesto, como res/xml/ad_services_config.xml. Saiba mais sobre as permissões dos serviços de anúncios e o controle de acesso do SDK.

      <ad-services-config>
        <custom-audiences allowAllToAccess="true" />
      </ad-services-config>
    
  7. Por padrão, a API Ad Selection aplica limites na quantidade máxima de memória que um script de relatório de impressões ou de leilão pode alocar. O recurso de limitação de memória requer a versão 105.0.5195.58 ou mais recente do WebView. A plataforma aplica uma verificação de versão, e as chamadas para as APIs selectAds e reportImpression vão falhar se esse requisito não for atendido. Há duas opções para configurar esse recurso:

    • Opção 1: executar o seguinte comando adb para desativar essa verificação:

      adb device_config put fledge_js_isolate_enforce_max_heap_size false
      
    • Opção 2: instalar o WebView Beta pela Google Play Store, com uma versão igual ou maior que a indicada anteriormente.

Aderir a um público-alvo personalizado

Um público-alvo personalizado representa um grupo de usuários com intenções ou interesses em comum conforme decidido por um app de anunciante. Um app ou SDK pode usar um público-alvo personalizado para indicar um público específico, como alguém que deixou itens no carrinho de compras. Para criar ou fazer parte de um público-alvo personalizado de maneira assíncrona, siga estas etapas:

  1. Inicialize o objeto CustomAudienceManager.
  2. Crie um objeto CustomAudience especificando parâmetros importantes, por exemplo, o pacote do comprador e um nome relevante. Em seguida, inicialize o objeto JoinCustomAudienceRequest com o objeto CustomAudience.
  3. Chame o método joinCustomAudience() assíncrono com o objeto JoinCustomAudienceRequest e os objetos Executor e OutcomeReceiver relevantes.

Kotlin

val customAudienceManager: CustomAudienceManager =
    context.getSystemService(CustomAudienceManager::class.java)

// Initialize a custom audience.
val audience = CustomAudience.Builder()
    .setBuyer(buyer)
    .setName(name)
    ...
    .build()

// Initialize a custom audience request.
val joinCustomAudienceRequest: JoinCustomAudienceRequest =
    JoinCustomAudienceRequest.Builder().setCustomAudience(audience).build()

// Request to join a custom audience.
customAudienceManager.joinCustomAudience(joinCustomAudienceRequest,
    executor,
    outcomeReceiver)

Java

CustomAudienceManager customAudienceManager =
    context.getSystemService(CustomAudienceManager.class);

// Initialize a custom audience.
CustomAudience audience = new CustomAudience.Builder()
    .setBuyer(buyer)
    .setName(name)
    ...
    .build();

// Initialize a custom audience request.
JoinCustomAudienceRequest joinCustomAudienceRequest =
    new JoinCustomAudienceRequest.Builder().setCustomAudience(audience).build();

// Request to join a custom audience.
customAudienceManager.joinCustomAudience(joinCustomAudienceRequest,
    executor,
    outcomeReceiver);

A combinação dos parâmetros abaixo identifica cada objeto CustomAudience de forma exclusiva em um dispositivo:

  • owner: nome do pacote do app do proprietário, definido implicitamente como o nome do pacote do app autor da chamada.
  • buyer: identificador da rede de publicidade do comprador, que gerencia anúncios para o público-alvo personalizado.
  • name: um nome ou identificador arbitrário para o público-alvo personalizado.

Chamar joinCustomAudience() repetidamente com uma instância diferente de CustomAudience atualiza qualquer CustomAudience já existente com parâmetros owner, buyer e name correspondentes. Para preservar a privacidade, o resultado da API não distingue entre "criação" e "atualização".

Além disso, o CustomAudience precisa ser criado com estes parâmetros necessários:

  • URL de atualização diária: um URL HTTPS consultado diariamente em segundo plano para atualizar os indicadores de lances do usuário de um público-alvo personalizado e os dados de lances confiáveis, além de renderizar URLs e metadados de anúncios.
  • URL de lógica de lances: um URL HTTPS consultado durante a seleção de anúncios para buscar a lógica de lances JavaScript de um comprador. Confira as assinaturas de função necessárias no JavaScript.

Os parâmetros opcionais de um objeto CustomAudience podem incluir:

  • Momento de ativação: um público-alvo personalizado só pode participar da seleção de anúncios e das atualizações diárias após o momento da ativação. Isso pode ser útil para engajar usuários que não interagem mais com um app, por exemplo.
  • Prazo de validade: uma data futura para remoção do público personalizado do dispositivo.
  • Indicadores de lances do usuário: uma string JSON com indicadores do usuário, como localidade preferida, que o JavaScript da lógica de lances do comprador vai consumir para gerar lances durante o processo de seleção de anúncios. Esse formato permite que plataformas de adtech reutilizem o código em várias plataformas e facilita o consumo em funções JavaScript.
  • Dados de lances confiáveis: um URL HTTPS e uma lista de strings usadas durante o processo de seleção de anúncios para buscar indicadores de lances de um serviço de chave-valor confiável.
  • Anúncios: uma lista de objetos AdData correspondentes aos anúncios que participam da seleção. Cada objeto AdData consiste em:
    • URL de renderização: um URL HTTPS que é consultado para renderizar o anúncio final.
    • Metadados: um objeto JSON serializado como uma string que contém informações que vão ser consumidas pela lógica de lances do comprador durante o processo de seleção de anúncios.
    • Filtros de anúncios: uma classe que contém todas as informações necessárias para a filtragem de anúncios de instalação de apps e o limite de frequência durante a seleção de anúncios.

Confira um exemplo de instanciação do objeto CustomAudience:

Kotlin

// Minimal initialization of a CustomAudience object
val customAudience: CustomAudience = CustomAudience.Builder()
    .setBuyer(AdTechIdentifier.fromString("my.buyer.domain.name"))
    .setName("example-custom-audience-name")
    .setDailyUpdateUrl(Uri.parse("https://DAILY_UPDATE_URL"))
    .setBiddingLogicUrl(Uri.parse("https://BIDDING_LOGIC_URL"))
    .build()

Java

// Minimal initialization of a CustomAudience object
CustomAudience customAudience = CustomAudience.Builder()
    .setBuyer(AdTechIdentifier.fromString("my.buyer.domain.name"))
    .setName("example-custom-audience-name")
    .setDailyUpdateUrl(Uri.parse("https://DAILY_UPDATE_URL"))
    .setBiddingLogicUrl(Uri.parse("https://BIDDING_LOGIC_URL"))
    .build();

Processar resultados de joinCustomAudience()

O método joinCustomAudience() assíncrono usa o objeto OutcomeReceiver para informar o resultado da chamada de API.

  • O callback onResult() indica que o público-alvo personalizado foi criado ou atualizado.
  • O callback onError() indica duas condições possíveis.

Confira um exemplo de como processar o resultado de joinCustomAudience():

Kotlin

var callback: OutcomeReceiver<Void, AdServicesException> =
    object : OutcomeReceiver<Void, AdServicesException> {
    override fun onResult(result: Void) {
        Log.i("CustomAudience", "Completed joinCustomAudience")
    }

    override fun onError(error: AdServicesException) {
        // Handle error
        Log.e("CustomAudience", "Error executing joinCustomAudience", error)
    }
};

Java

OutcomeReceiver callback = new OutcomeReceiver<Void, AdServicesException>() {
    @Override
    public void onResult(@NonNull Void result) {
        Log.i("CustomAudience", "Completed joinCustomAudience");
    }

    @Override
    public void onError(@NonNull AdServicesException error) {
        // Handle error
        Log.e("CustomAudience", "Error executing joinCustomAudience", error);
    }
};

Sair de um público-alvo personalizado

Se o usuário não atender mais aos critérios comerciais de um determinado público-alvo personalizado, um app ou SDK vai poder chamar leaveCustomAudience() para remover o público-alvo do dispositivo. Para remover um CustomAudience com base nos parâmetros exclusivos, siga estas etapas:

  1. Inicialize o objeto CustomAudienceManager.
  2. Inicialize a LeaveCustomAudienceRequest com os elementos buyer e name do público-alvo personalizado. Para saber mais sobre esses campos de entrada, consulte Aderir a um público-alvo personalizado.
  3. Chame o método assíncrono leaveCustomAudience() com o objeto LeaveCustomAudienceRequest e os objetos Executor e OutcomeReceiver relevantes.

Kotlin

val customAudienceManager: CustomAudienceManager =
    context.getSystemService(CustomAudienceManager::class.java)

// Initialize a LeaveCustomAudienceRequest
val leaveCustomAudienceRequest: LeaveCustomAudienceRequest =
    JoinCustomAudienceRequest.Builder()
        .setBuyer(buyer)
        .setName(name)
        .build()

// Request to leave a custom audience
customAudienceManager.leaveCustomAudience(
    leaveCustomAudienceRequest,
    executor,
    outcomeReceiver)

Java

CustomAudienceManager customAudienceManager =
    context.getSystemService(CustomAudienceManager.class);

// Initialize a LeaveCustomAudienceRequest
LeaveCustomAudienceRequest leaveCustomAudienceRequest =
    new JoinCustomAudienceRequest.Builder()
        .setBuyer(buyer)
        .setName(name)
        .build();

// Request to leave a custom audience
customAudienceManager.leaveCustomAudience(
    leaveCustomAudienceRequest,
    executor,
    outcomeReceiver);

O OutcomeReceiver informa o final de uma chamada de API de maneira semelhante à chamada do método joinCustomAudience(). Para proteger a privacidade, um resultado de erro não faz distinção entre erros internos e argumentos inválidos. O callback onResult() é chamado quando a chamada de API é concluída, independente de um público-alvo personalizado correspondente ser removido ou não.

Executar a seleção de anúncios

Para usar a API Protected Audience na seleção de anúncios, chame o método selectAds():

  1. Inicialize um objeto AdSelectionManager.
  2. Crie um objeto AdSelectionConfig.
  3. Chame o método assíncrono selectAds() com o objeto AdSelectionConfig e os objetos Executor e OutcomeReceiver relevantes.

Kotlin

val adSelectionManager: AdSelectionManager =
  context.getSystemService(AdSelectionManager::class.java)

// Initialize AdSelectionConfig
val adSelectionConfig: AdSelectionConfig =
  AdSelectionConfig.Builder().setSeller(seller)
    .setDecisionLogicUrl(decisionLogicUrl)
    .setCustomAudienceBuyers(customAudienceBuyers)
    .setAdSelectionSignals(adSelectionSignals)
    .setSellerSignals(sellerSignals)
    .setPerBuyerSignals(perBuyerSignals)
    .setBuyerContextualAds(
      Collections.singletonMap(
        contextualAds.getBuyer(), contextualAds
      )
    ).build()

// Run ad selection with AdSelectionConfig
adSelectionManager.selectAds(
  adSelectionConfig, executor, outcomeReceiver
)

Java

AdSelectionManager adSelectionManager =
    context.getSystemService(AdSelectionManager.class);

// Initialize AdSelectionConfig
AdSelectionConfig adSelectionConfig =
  new AdSelectionConfig.Builder()
    .setSeller(seller)
    .setDecisionLogicUrl(decisionLogicUrl)
    .setCustomAudienceBuyers(customAudienceBuyers)
    .setAdSelectionSignals(adSelectionSignals)
    .setSellerSignals(sellerSignals)
    .setPerBuyerSignals(perBuyerSignals)
    .setBuyerContextualAds(
      Collections.singletonMap(contextualAds.getBuyer(), contextualAds)
    )
    .build();

// Run ad selection with AdSelectionConfig
adSelectionManager.selectAds(adSelectionConfig, executor, outcomeReceiver);

O método selectAds() requer uma entrada AdSelectionConfig, em que é preciso especificar os parâmetros abaixo:

  • Vendedor: o identificador da rede de publicidade do vendedor, que inicia a seleção de anúncios.
  • URL de lógica de decisão: um URL HTTPS consultado para receber a lógica JavaScript da rede de publicidade do vendedor.
    • URL HTTPS: consultado para receber a lógica JavaScript da rede de anúncios do vendedor. Consulte as assinaturas de função obrigatórias.
    • URI pré-criado: que segue o formato de seleção de anúncios do FLEDGE. Uma IllegalArgumentException será gerada se um URI pré-criado sem suporte ou malformado for transmitido.
  • Compradores de públicos-alvo personalizados: uma lista completa de identificadores das redes de publicidade de compradores aceitas pelo vendedor para participar do processo de seleção de anúncios. Esses identificadores de comprador correspondem ao método CustomAudience.getBuyer() dos públicos-alvo personalizados participantes.

Os parâmetros abaixo podem ser especificados para ter uma seleção de anúncios mais personalizada:

  • Indicadores de seleção de anúncios: um objeto JSON serializado como uma string que contém indicadores que vão ser consumidos pelo JavaScript da lógica de lances do comprador buscado por CustomAudience.getBiddingLogicUrl().
  • Indicadores de vendedor: um objeto JSON serializado como uma string que contém indicadores que vão ser consumidos pela lógica de decisão JavaScript do vendedor buscada por AdSelectionConfig.getDecisionLogicUrl().
  • Indicadores por comprador: um mapa de objetos JSON serializados como strings que contém indicadores a serem consumidos pelo JavaScript da lógica de lances de compradores específica buscada por CustomAudience.getBiddingLogicUrl(). Essas strings são identificadas pelos campos de comprador dos públicos-alvo personalizados participantes.
  • Anúncios contextuais: um conjunto de candidatos coletados diretamente de compradores durante um leilão que acontece fora de um leilão de da API Protected Audience.

Após a seleção de um anúncio, os resultados, lances e indicadores são armazenados internamente para relatórios. O callback OutcomeReceiver.onResult() retorna um AdSelectionOutcome que contém:

  • Um URL de renderização do anúncio vencedor, extraído de AdData.getRenderUrl().
  • Um ID de seleção de anúncios exclusivo para o usuário do dispositivo. O ID é usado para gerar relatórios sobre a impressão do anúncio.

Se a seleção de anúncios não for concluída por motivos como argumentos inválidos, tempos limite ou consumo excessivo de recursos, o callback OutcomeReceiver.onError() vai gerar uma AdServicesException com estes comportamentos:

  • Se a seleção de anúncios for iniciada com argumentos inválidos, a AdServicesException vai indicar uma IllegalArgumentException como causa.
  • Todos os outros erros vão receber uma AdServicesException com uma IllegalStateException como causa.

Filtragem do limite de frequência

A filtragem de limite de frequência permite que as adtechs limitem o número de vezes que um anúncio é exibido. A filtragem do limite de frequência reduz a superexposição do anúncio e otimiza a seleção de anúncios alternativos para determinada campanha.

Há dois componentes principais de um filtro de limite de frequência: o tipo de evento de anúncio e a chave do contador de anúncios. Os tipos de evento de anúncio que podem ser usados são os seguintes:

  • Vitória (em breve): um evento de vitória indica que o anúncio ganhou um leilão. Os eventos vencedores são atualizados automaticamente pela API Protected Audience e não podem ser chamados diretamente pelo desenvolvedor. Os dados de vitórias só são visíveis para anúncios em um determinado público-alvo personalizado.
  • Impressão: separada de reportImpression, o autor da chamada no dispositivo (SSP ou MMP) usa updateAdCounterHistogram() para invocar eventos de impressão no ponto escolhido no código. Os eventos de impressão são visíveis para todos os anúncios de um determinado DSP e não são limitados a anúncios no mesmo público-alvo personalizado.
  • Visualização: o evento é invocado pelo autor da chamada no dispositivo (SSP ou MMP) em um ponto escolhido no código usando uma chamada para updateAdCounterHistogram(). Os eventos de visualização são visíveis para todos os anúncios de um determinado DSP e não são limitados a anúncios no mesmo público-alvo personalizado.
  • Clique: o evento é invocado pelo autor da chamada no dispositivo (SSP ou MMP) em um ponto escolhido no código usando uma chamada para updateAdCounterHistogram(). Os eventos de clique são visíveis para todos os anúncios de um determinado DSP e não são limitados a anúncios no mesmo público-alvo personalizado.

No app do editor, uma SSP ou MMP que está presente no dispositivo invoca eventos de anúncio. Quando updateAdCounterHistogram() é chamado, o contador de um filtro de limite de frequência é incrementado para que os leilões futuros tenham informações atualizadas sobre a exposição de um usuário a determinado anúncio. Os tipos de evento de anúncio não são vinculados à ação do usuário correspondente e são diretrizes fornecidas para ajudar os autores da chamada a estruturar o sistema de eventos. Para incrementar os contadores de anúncios no momento de um evento, o ator no dispositivo oferece o ID de seleção de anúncios do leilão vencedor.

As chaves de contador de anúncio são números inteiros arbitrários de 32 bits atribuídos por uma adtech do comprador e correspondem a um determinado conjunto de anúncios, conforme definido pela DSP. Como as chaves de contador de anúncios são limitadas somente aos anúncios que pertencem a um determinado DSP, essas chaves podem ser selecionadas sem sobreposição com histogramas de outra adtech. As chaves de contador de anúncio são usadas para incrementar identificadores específicos do DSP em anúncios de um DSP ou em um determinado público-alvo personalizado para filtrar anúncios de leilões futuros.

As chaves de contador podem ser usadas para priorizar anúncios com maior probabilidade de serem interessantes para determinado usuário com base nas interações dele com outros anúncios de uma adtech. Por exemplo, um anúncio que recebeu um alto nível de engajamento por vitórias em leilões de anúncios, visualizações e cliques representa um ponto de dados inferido. Por exemplo: um anúncio de tacos de golf para canhotos pode indicar que o usuário não tem interesse em tacos para destros. Um filtro de limite de frequência definido para uma chave de contador atribuída a anúncios de "canhoto" pode eliminar anúncios para destros.

Para usar o limite de frequência no leilão, primeiro é necessário criar objetos KeyedFrequencyCap, conforme mostrado abaixo:

Kotlin

// Value used when incrementing frequency counter
val adCounterKey = 123

// Frequency cap exceeded after 2 counts
val keyedFrequencyCapForImpression: KeyedFrequencyCap = Builder(
  adCounterKey, 2, Duration.ofSeconds(10)
).build()

// Frequency cap exceeded after 1 counts
val keyedFrequencyCapForImpression: KeyedFrequencyCap = Builder(
  adCounterKey, 1, Duration.ofSeconds(10)
).build()

Java

// Value used when incrementing frequency counter
int adCounterKey = 123;

// Frequency cap exceeded after 2 counts
KeyedFrequencyCap keyedFrequencyCapForImpression =
  new KeyedFrequencyCap.Builder(
    adCounterKey, 2, Duration.ofSeconds(10)
  ).build();

// Frequency Cap exceeded after 1 counts
KeyedFrequencyCap keyedFrequencyCapForClick =
  new KeyedFrequencyCap.Builder(
    adCounterKey, 1, Duration.ofSeconds(10)
  ).build();

Após a criação, os objetos KeyedFrequencyCap podem ser transmitidos para um AdFilters.

Kotlin

val filters: AdFilters = Builder()
  .setFrequencyCapFilters(
    Builder()
      .setKeyedFrequencyCapsForImpressionEvents(
        ImmutableObject.of(keyedFrequencyCapForImpression)
      )
      .setKeyedFrequencyCapsForClickEvents(
        ImmutableObject.of(keyedFrequencyCapForClick)
      )
  ).build()

Java

AdFilters filters = new AdFilters.Builder()
    .setFrequencyCapFilters(new FrequencyCapFilters.Builder()
        .setKeyedFrequencyCapsForImpressionEvents(
            ImmutableObject.of(keyedFrequencyCapForImpression)
        )
        .setKeyedFrequencyCapsForClickEvents(
            ImmutableObject.of(keyedFrequencyCapForClick)
        )
    ).build();

Quando o objeto AdFilters é preenchido com filtros de limite de frequência, ele pode ser transmitido junto com o público-alvo personalizado:

Kotlin

// Initialize a custom audience.
val audience: CustomAudience = Builder()
  .setBuyer(buyer)
  .setName(name)
  .setAds(
    listOf(
      Builder()
        .setRenderUri(renderUri)
        .setMetadata(JSONObject().toString())
        .setAdFilters(filters)
        .setAdCounterKeys(adCounterKeys)
        .build()
    )
  ).build()

Java

// Initialize a custom audience.
CustomAudience audience = new CustomAudience.Builder()
    .setBuyer(buyer)
    .setName(name)
    .setAds(Collections.singletonList(new AdData.Builder()
        .setRenderUri(renderUri)
        .setMetadata(new JSONObject().toString())
        .setAdFilters(filters)
        .setAdCounterKeys(adCounterKeys)
        .build()))
    .build();

Quando os filtros de limite de frequência são implementados em um público-alvo personalizado, o SSP pode invocar os eventos de clique, visualização ou impressão necessários.

Kotlin

val callerAdTech: AdTechIdentifier = mAdSelectionConfig.getSeller()

val request: UpdateAdCounterHistogramRequest = Builder(
  adSelectionId,
  FrequencyCapFilters.AD_EVENT_TYPE_CLICK,  //CLICK, VIEW, or IMPRESSION
  callerAdTech
).build()

Java

AdTechIdentifier callerAdTech = mAdSelectionConfig.getSeller();

UpdateAdCounterHistogramRequest request =
  new UpdateAdCounterHistogramRequest.Builder(
      adSelectionId,
      FrequencyCapFilters.AD_EVENT_TYPE_CLICK, //CLICK, VIEW, or IMPRESSION
      callerAdTech
).build();

Os anúncios que atingiram os limites de filtro de limite de frequência predefinidos são eliminados do leilão, com filtragem antes da execução da lógica de lances. Esse kit de ferramentas oferece às adtechs flexibilidade para usar as interações entre os usuários e os anúncios nos públicos-alvo personalizados para focar a segmentação e minimizar a exposição excessiva.

Gerar relatórios de impressões de anúncios

Depois que um anúncio vencedor for escolhido no fluxo de trabalho da seleção de anúncios, vai ser possível relatar a impressão de volta às plataformas de compra e venda participantes com o método AdSelectionManager.reportImpression(). Para gerar um relatório sobre uma impressão de anúncio, siga estas etapas:

  1. Inicialize um objeto AdSelectionManager.
  2. Crie um objeto ReportImpressionRequest com o ID de seleção de anúncios.
  3. Chame o método assíncrono reportImpression() com o objeto ReportImpressionRequest e os objetos Executor e OutcomeReceiver relevantes.

Java

AdSelectionManager adSelectionManager =
    context.getSystemService(AdSelectionManager.class);

// Initialize a ReportImpressionRequest
ReportImpressionRequest reportImpressionRequest =
        new ReportImpressionRequest.Builder()
                .setAdSelectionId(adSelectionId)
                .setAdSelectionConfig(adSelectionConfig)
                .build();

// Request to report the impression with the ReportImpressionRequest
adSelectionManager.reportImpression(
    reportImpressionRequest,
    executor,
    outcomeReceiver);

Kotlin

val adSelectionManager = context.getSystemService(AdSelectionManager::class.java)

// Initialize a ReportImpressionRequest
val adSelectionConfig: ReportImpressionRequest =
    ReportImpressionRequest.Builder()
        .setAdSelectionId(adSelectionId)
        .setAdSelectionConfig(adSelectionConfig)
        .build()

// Request to report the impression with the ReportImpressionRequest
adSelectionManager.reportImpression(
    reportImpressionRequest,
    executor,
    outcomeReceiver)

Inicialize o ReportImpressionRequest com os parâmetros necessários abaixo:

  • ID de seleção de anúncios: o ID exclusivo de um usuário de dispositivo e que identifica uma seleção de anúncios bem-sucedida.
  • Configuração de seleção de anúncios: a mesma configuração usada na chamada selectAds() identificada pelo ID de seleção de anúncios informado.

O método reportImpression() assíncrono usa o objeto OutcomeReceiver para informar o resultado da chamada de API.

  • O callback onResult() indica se os URLs de relatórios de impressão foram criados e se a solicitação foi agendada.
  • O callback onError() indica estas condições possíveis:
    • Se a chamada for inicializada com um argumento de entrada inválido, a AdServicesException vai indicar uma IllegalArgumentException como causa.
    • Todos os outros erros vão receber uma AdServicesException com uma IllegalStateException como causa.

Endpoints de relatórios de impressão

A API Report Impression emite solicitações GET HTTPS para os endpoints fornecidos pela plataforma de venda e pela plataforma de compra vencedora:

Endpoint da plataforma de compra:

  • A API usa o URL da lógica de lances especificado no público-alvo personalizado para buscar o JavaScript fornecido pelo comprador, que inclui uma lógica para retornar um URL de relatório de impressões.
  • Invoque a função reportWin() do JavaScript, que precisa retornar o URL de relatório de impressão do comprador.

Endpoint da plataforma de venda:

  • Use o URL da lógica de decisão especificado no objeto AdSelectionConfig para buscar o JavaScript da lógica de decisão do vendedor.
  • Invoque a função reportResult() do JavaScript, que precisa retornar o URL de relatório de impressão do comprador.

Melhor resultado de relatórios de impressão

O método reportImpression() foi projetado para oferecer a melhor conclusão de relatórios possível.

Gerar relatórios de interações com anúncios

A API Protected Audience oferece suporte para gerar relatórios sobre interações mais granulares para um anúncio renderizado. Isso pode incluir interações como tempo de visualização, cliques, passagem do cursor ou qualquer outra métrica útil que pode ser coletada. O processo para receber esses relatórios requer duas etapas. Primeiro, compradores e vendedores precisam se registrar para receber esses relatórios no JavaScript de relatórios. Em seguida, o cliente vai precisar informar esses eventos.

Como fazer o registro para receber eventos de interação

O registro de eventos de interação acontece no método reportWin() do comprador e nas funções JavaScript reportResult() do vendedor, usando uma função JavaScript fornecida pela plataforma: registerAdBeacon. Para fazer o registro para receber um relatório de eventos, basta chamar a função JavaScript da plataforma no JavaScript do relatório. O snippet abaixo usa o reportWin() de um comprador, mas a mesma abordagem se aplica a reportResult().

reportWin(
  adSelectionSignals,
  perBuyerSignals,
  signalsForBuyer,
  contextualSignals,
  customAudienceSignals) {
    ...
    // Calculate reportingUri, clickUri, viewUri, and hoverUri
    registerAdBeacon("click", clickUri)
    registerAdBeacon("view", viewUri)
    registerAdBeacon("hover", hoverUri)

    return reportingUrl;
}

Gerar relatórios de eventos de interação

Depois de informar uma impressão, os clientes podem relatar as interações para as plataformas de compra e venda vencedoras registradas anteriormente com o método AdSelectionManager.reportInteraction(). Para informar um evento de anúncio:

  1. Inicialize um objeto AdSelectionManager.
  2. Crie um objeto ReportInteractionRequest com o ID da seleção de anúncios, a chave de interação, os dados de interação e o destino do relatório.
  3. Chame o método assíncrono reportInteraction() com o objeto request e os objetos Executor e OutcomeReceiver relevantes.
AdSelectionManager adSelectionManager =
    context.getSystemService(AdSelectionManager.class);

// Initialize a ReportInteractionRequest
ReportInteractionRequest request =
  new ReportInteractionRequest.Builder()
    .setAdSelectionId(adSelectionId)
    .setInteractionKey("view")
    .setInteractionData("{ viewTimeInSeconds : 1 }") // Can be any string
    .setReportingDestinations(
      FLAG_REPORTING_DESTINATION_BUYER | FLAG_REPORTING_DESTINATION_SELLER
    )
    .build();

// Request to report the impression with the ReportImpressionRequest
adSelectionManager.reportInteraction(
  reportImpressionRequest,
  executor,
  outcomeReceiver);

Inicialize o ReportInteractionRequest com os parâmetros necessários abaixo:

  • ID de seleção de anúncios: um ID extraído de um AdSelectionOutcome retornado anteriormente.
  • Chave de interação: uma chave de string definida pelo cliente que descreve a ação informada. Ela precisa corresponder à chave que foi registrada pelo vendedor ou pelo comprador nas funções JavaScript de relatórios.
  • Dados de interação: uma string que contém dados a serem incluídos no relatório de eventos de teste automático de inicialização (POST) enviado para os servidores de relatórios.
  • Relatórios de destino: uma bitmask que especifica se os eventos precisam ser informados ao comprador, ao vendedor ou a ambos. Essas sinalizações são fornecidas pela plataforma e a máscara de destino final pode ser criada usando operações bit a bit. Para informar um destino, você pode usar a flag fornecida pela plataforma diretamente. Para informar vários destinos, você pode usar o operador bit a bit OR (|) para combinar os valores de sinalização.

O método reportInteraction() assíncrono usa o objeto OutcomeReceiver para informar o resultado da chamada de API.

  • O callback onResult() indica que a chamada de interação de relatório é válida.
  • O callback onError() indica estas condições possíveis:
    • Se a chamada for feita quando o app estiver sendo executado em segundo plano, uma IllegalStateException com uma descrição da falha será retornada.
    • Se o cliente for impedido de chamar reportInteraction(), uma LimitExceededException será retornada.
    • Se o pacote não estiver inscrito para chamar as APIs de preservação de privacidade, uma SecurityException() será retornada.
    • Se as interações de relatórios do app forem diferentes do app que chamou selectAds(), uma IllegalStateException será retornada.
  • Se o usuário não consentir com a ativação das APIs do Sandbox de privacidade, a chamada vai falhar silenciosamente.

Endpoints de relatórios de interação

A API de interação de relatório emite solicitações HTTPS POST para endpoints fornecidos pela plataforma de venda e pela plataforma de compra vencedora. A API Protected Audience vai fazer a correspondência das chaves de interação com os URIs declarados no JavaScript de relatórios e vai emitir uma solicitação POST para cada endpoint em cada interação relatada. O tipo de conteúdo da solicitação é texto simples, com o corpo sendo os dados de interação.

Melhor resultado de relatórios de interação

O método reportInteraction() foi criado para oferecer uma conclusão de relatório de melhor resultado por HTTP POST.

Atualização diária em segundo plano

Ao criar um público-alvo personalizado, seu app ou SDK pode inicializar metadados de público-alvo personalizado. Além disso, a plataforma pode atualizar as seguintes partes dos metadados de público personalizado com um processo diário de atualização em segundo plano.

  • Indicadores de lances do usuário
  • Dados confiáveis de lances
  • Lista AdData

Esse processo consulta o URL de atualização diária definido no público-alvo personalizado, e o URL pode retornar uma resposta JSON.

  • A resposta JSON pode conter qualquer um dos campos de metadados com suporte que precisam ser atualizados.
  • Cada campo JSON é validado de forma independente. O cliente ignora os campos incorretos que não resultam em atualizações para esse campo específico na resposta.
  • Uma resposta HTTP vazia ou um objeto JSON vazio "{}" não resulta em atualizações de metadados.
  • A resposta precisa ter no máximo 10 KB.
  • Todos os URIs precisam usar HTTPS.
  • É necessário que trusted_bidding_uri compartilhe o mesmo ETLD+1 que o comprador.

Exemplo: resposta JSON para atualização diária em segundo plano

{
    "user_bidding_signals" : { ... },  // Valid JSON object
    "trusted_bidding_data" : {
        "trusted_bidding_uri" : 'example-dsp1-key-value-service.com',
        "trusted_bidding_keys" : [ 'campaign123', 'campaign456', ... ]
    },
    'ads' : [
        {
            "render_uri" : 'www.example-dsp1.com/.../campaign123.html',
            'metadata' : { ... }  // Valid JSON object
        },
        {
            "render_uri" : 'www.example-dsp1.com/.../campaign456.html',
            'metadata' : { ... }  // Valid JSON object
        },
        ...
    ]
}

JavaScript para seleção de anúncios

O fluxo de trabalho da seleção de anúncios orquestra a execução do JavaScript fornecido pelo comprador e pelo vendedor.

O JavaScript fornecido pelo comprador é buscado no URL da lógica de lances especificado no público-alvo personalizado. O JavaScript retornado precisa incluir estas funções:

O JavaScript fornecido pelo vendedor é buscado do URL da lógica de decisão especificado no parâmetro AdSelectionConfig da API Ad Selection. O JavaScript retornado precisa incluir as funções abaixo:

generateBid()

function generateBid(
  ad,
  auction_signals,
  per_buyer_signals,
  trusted_bidding_signals,
  contextual_signals,
  user_signals,
  custom_audience_bidding_signals) {
  return {'status': 0, 'ad': ad, 'bid': ad.metadata.result };
}

Parâmetros de entrada:

  • ad: um objeto JSON com o formato var ad = { 'render_url': url, 'metadata': json_metadata };.
  • auction_signals, per_buyer_signals: objetos JSON especificados no objeto de configuração do leilão.
  • custom_audience_bidding_signals: objeto JSON gerado pela plataforma. O formato desse objeto JSON é:

    var custom_audience_signals = {
      "owner":"ca_owner",
      "buyer":"ca_buyer",
      "name":"ca_name",
      "activation_time":"ca_activation_time_epoch_ms",
      "expiration_time":"ca_expiration_time_epoch_ms",
      "user_bidding_signals":"ca_user_bidding_signals"
    }
    

    em que:

    • owner, buyer e name são strings extraídas das propriedades com o mesmo nome do público-alvo personalizado que participa da seleção de anúncios.
    • activation_time e expiration_time são os momentos da ativação e de expiração do público-alvo personalizado, expressos em segundos desde a era Unix (link em inglês).
    • ca_user_bidding_signals é uma string JSON especificada no campo userBiddingSignals da CustomAudience no momento da criação.
    • trusted_bidding_signals, contextual_signals e user_signals são objetos JSON. No momento, eles são transmitidos como objetos vazios e serão preenchidos em versões futuras. O formato deles não é aplicado pela plataforma e é gerenciado pelas tecnologias de publicidade.

Resultado:

  • ad: é o anúncio a que o lance se refere. O script pode retornar uma cópia do anúncio recebido com metadados diferentes. A propriedade render_url do anúncio não vai mudar.
  • bid: um valor flutuante que representa o valor do lance do anúncio.
  • status: um valor inteiro que pode ser:
    • 0: para uma execução bem-sucedida.
    • 1: (ou qualquer valor diferente de zero) caso algum dos indicadores de entrada seja inválido. Caso um valor diferente de zero seja retornado por generate-bid, o processo de lances vai ser invalidado para todos os anúncios de CA.

scoreAd()

function scoreAd(
  ad,
  bid,
  ad_selection_config,
  seller_signals,
  trusted_scoring_signals,
  contextual_signal,
  user_signal,
  custom_audience_signal) {
    return {'status': 0, 'score': score };
}

Parâmetros de entrada:

  • ad: consulte a documentação de generateBid.
  • bid: o valor do lance do anúncio.
  • ad_selection_config: um objeto JSON que representa o parâmetro AdSelectionConfig da API selectAds. O formato é:

    var ad_selection_config = {
      'seller': 'seller',
      'decision_logic_url': 'url_of_decision_logic',
      'custom_audience_buyers': ['buyer1', 'buyer2'],
      'auction_signals': auction_signals,
      'per_buyer_signals': per_buyer_signals,
      'contextual_ads': [ad1, ad2]
    }
    
  • seller_signals: objetos JSON lidos no parâmetro sellerSignals da API AdSelectionConfig.

  • trusted_scoring_signal: lido no campo adSelectionSignals do parâmetro da API AdSelectionConfig.

  • contextual_signals, user_signals: objetos JSON. No momento, eles são transmitidos como objetos vazios e vão ser preenchidos em versões futuras. O formato deles não é aplicado pela plataforma e é gerenciado pela adtech.

  • per_buyer_signals: objeto JSON lido do mapa perBuyerSignal do parâmetro da API AdSelectionConfig usando como chave o comprador atual do público-alvo personalizado. Vai ser vazio se o mapa não tiver nenhuma entrada para o comprador em questão.

Resultado:

  • score: um valor flutuante que representa o valor da pontuação do anúncio.
  • status: um valor inteiro que pode ser:
    • 0: para uma execução bem-sucedida.
    • 1: caso o indicador customAudienceSignals seja inválido.
    • 2: caso o indicador AdSelectionConfig seja inválido.
    • 3: caso algum dos outros indicadores seja inválido.
    • Qualquer valor diferente de zero causa a falha do processo. O valor determina o tipo de exceção gerada.

reportResult()

function reportResult(ad_selection_config, render_url, bid, contextual_signals) {
   return {
      'status': status,
      'results': {'signals_for_buyer': signals_for_buyer, 'reporting_url': reporting_url }
   };
}

Parâmetros de entrada:

  • ad_selection_config: consulte a documentação de scoreAds.
  • render_url: o URL de renderização do anúncio vencedor.
  • bid: o lance oferecido para o anúncio vencedor.
  • contextual_signals: consulte a documentação de generateBid.

Resultado:

  • status: 0 para sucesso e valores diferentes de zero para falhas.
  • results: um objeto JSON que contém:
    • signals_for_buyer: um objeto JSON transmitido para a função reportWin.
    • reporting_url: um URL usado pela plataforma para notificar a impressão ao comprador.

reportWin()

function reportWin(
   ad_selection_signals,
   per_buyer_signals,
   signals_for_buyer,
   contextual_signals,
   custom_audience_signals) {
   return {'status': 0, 'results': {'reporting_url': reporting_url } };
}

Parâmetros de entrada:

  • ad_selection_signals, per_buyer_signals: consulte a documentação de scoreAd.
  • signals_for_buyer: um objeto JSON retornado por reportResult.
  • contextual_signals, custom_audience_signals: consulte a documentação de generateBid.

Resultado:

  • status: 0 para sucesso e valores diferentes de zero para falhas.
  • results: um objeto JSON contendo:
    • reporting_url: um URL usado pela plataforma para notificar a impressão ao vendedor.

registerAdBeacon()

function registerAdBeacon(
  interaction_key,
  reporting_uri
)

Parâmetros de entrada:

  • interaction_key: uma string que representa o evento. É usada pela plataforma mais tarde ao relatar interações de eventos para procurar o reporting_uri que precisa ser notificado. Essa chave precisa corresponder ao que o comprador ou o vendedor registra e ao que o vendedor informa.
  • reporting_uri: um URI para receber relatórios de eventos. Precisa ser específico para o tipo de evento que está sendo informado. Ele precisa aceitar uma solicitação POST para processar todos os dados informados com o evento.

URIs pré-criados da seleção de anúncios

Com os URIs pré-criados, as adtechs podem indicar funções JavaScript para a lógica de decisão da seleção de anúncios nas classes AdSelectionConfig e AdSelectionFromOutcomesConfig. URIs pré-criados não exigem chamadas de rede para fazer o download do JavaScript correspondente. As adtechs podem usar URIs pré-criados sem precisar configurar um domínio registrado para hospedar o JavaScript.

Um URI pré-criado é construído usando este formato:

ad-selection-prebuilt:<use-case>/<name>?<required-script-generation-parameters>

A plataforma do Sandbox de privacidade fornece JavaScript usando as informações desse URI no ambiente de execução.

Uma IllegalArgumentException será gerada se:

  • Algum dos parâmetros obrigatórios não estiver presente no URI.
  • Houver parâmetros não reconhecidos no URI.

Casos de uso e nomes de URI pré-criados com suporte

Caso de uso 1: seleção de anúncios

Os URIs pré-criados no caso de uso ad-selection possuem suporte do fluxo selectAds(AdSelectionConfig).

Nome do URI pré-criado: highest-bid-wins

Esse URI pré-criado fornece um JavaScript que escolhe o anúncio com o lance mais alto após o leilão. Ele também fornece uma função básica de relatórios para informar o render_uri e o bid do vencedor.

Parâmetros obrigatórios

reportingUrl: o URL de relatório básico parametrizado com o render_uri e o bid do anúncio vencedor:

<reportingUrl>?render_uri=<renderUriOfWinnigAd>&bid=<bidOfWinningAd>

Uso

Se o URL de relatório base for https://www.ssp.com/reporting, o URI pré-criado será:

`ad-selection-prebuilt://ad-selection/highest-bid-wins/?reportingUrl=https://www.ssp.com/reporting`

Caso de uso 2: ad-selection-from-outcomes

Os URIs pré-criados no caso de uso ad-selection-from-outcomes possuem suporte do fluxo de trabalho selectAds(AdSelectionFromOutcomesConfig).

Nome do URI pré-criado: waterfall-mediation-truncation

O URI pré-criado waterfall-mediation-truncation fornece um JavaScript que implementa a lógica de truncamento da mediação em hierarquia, em que o JavaScript retornará um anúncio primário se o bid for maior ou igual a bid floor. Caso contrário, retornará null.

Parâmetros obrigatórios

bidFloor: a chave do valor mínimo do lance transmitido no método getSelectionSignals(), que é comparada com o anúncio do SDK de mediação.

Uso

Se os indicadores de seleção de anúncios forem semelhantes a {"bid_floor": 10}, o URI pré-criado resultante será:

`ad-selection-prebuilt://ad-selection-from-outcomes/waterfall-mediation-truncation/?bidFloor=bid_floor`

Testes

Para ajudar você a começar a usar a API Protected Audience, criamos apps de exemplo em Kotlin e Java que podem ser encontrados no GitHub (link em inglês).

Pré-requisitos

A API Protected Audience exige algum conhecimento de JavaScript durante a seleção de anúncios e a geração de relatórios de impressões. Há duas formas de fornecer esse JavaScript em um ambiente de teste:

  • Executar um servidor com os endpoints de HTTPS necessários que retornam o JavaScript.
  • Substituir a busca remota fornecendo o código necessário de uma fonte local.

Ambas as abordagens exigem a configuração de um endpoint de HTTPS para processar os relatórios de impressões.

Endpoints de HTTPS

Para testar a seleção de anúncios e os relatórios de impressão, configure sete endpoints de HTTPS que o dispositivo de teste ou emulador possa acessar:

  1. Endpoint do comprador, que mostra o JavaScript da lógica de lances.
  2. Um endpoint que disponibiliza indicadores de lances.
  3. Endpoint do vendedor, que mostra o JavaScript da lógica de decisão.
  4. Um endpoint que disponibiliza sinais de pontuação.
  5. Endpoint de relatórios de impressão do comprador vencedor.
  6. Endpoint de relatórios de impressão do vendedor.
  7. Um endpoint para disponibilizar as atualizações diárias de um público-alvo personalizado.

Por conveniência, o repositório do GitHub fornece um código JavaScript básico para fins de teste. Ele também inclui definições de serviço da OpenAPI, que podem ser implantadas em uma plataforma de simulação ou microsserviços com suporte. Para mais detalhes, consulte o arquivo README (link em inglês) do projeto.

Substituir a busca remota de JavaScript

Esse recurso é destinado a testes completos. Para substituir a busca remota, o app precisa ser executado no modo de depuração com as opções do desenvolvedor ativadas.

Para ativar o modo de depuração no aplicativo, adicione a linha abaixo ao atributo do aplicativo no AndroidManifest.xml:

<application
  android:debuggable="true">

Consulte o app de amostra da API Protected Audience (em inglês) no GitHub para saber como usar essas substituições.

Você precisa adicionar seu próprio JavaScript personalizado para processar rotinas de seleção de anúncios, como lances, decisões de pontuação e relatórios. Acesse o repositório do GitHub (em inglês) para conferir exemplos básicos de código JavaScript que processam todas as solicitações necessárias. O aplicativo de exemplo da API Protected Audience mostra como ler o código desse arquivo e prepará-lo para uso como substituição.

É possível substituir a busca do JavaScript de venda e compra de forma independente, embora seja necessário ter um endpoint de HTTPS para mostrar qualquer JavaScript para que você não está fornecendo substituições. Consulte o README (em inglês) para saber como configurar um servidor que processa esses casos.

Só é possível substituir a busca em JavaScript por públicos-alvo personalizados que pertencem ao seu pacote.

Substituir o JavaScript de venda

Para configurar uma substituição do JavaScript de venda, faça o seguinte, conforme demonstrado neste exemplo de código:

  1. Inicialize um objeto AdSelectionManager.
  2. Receba uma referência a TestAdSelectionManager no objeto AdSelectionManager.
  3. Crie um objeto AdSelectionConfig.
  4. Crie uma AddAdSelectionOverrideRequest com o objeto AdSelectionConfig e uma String que representa o JavaScript que você quer usar como substituição.
  5. Chame o método assíncrono overrideAdSelectionConfigRemoteInfo() com o objeto AddAdSelectionOverrideRequest e os objetos Executor e OutcomeReceiver correspondentes.

Kotlin

val testAdSelectionManager: TestAdSelectionManager =
  context.getSystemService(AdSelectionManager::class.java).getTestAdSelectionManager()

// Initialize AdSelectionConfig =
val adSelectionConfig = new AdSelectionConfig.Builder()
    .setSeller(seller)
    .setDecisionLogicUrl(decisionLogicUrl)
    .setCustomAudienceBuyers(customAudienceBuyers)
    .setAdSelectionSignals(adSelectionSignals)
    .setSellerSignals(sellerSignals)
    .setPerBuyerSignals(perBuyerSignals)
    .build()

// Initialize AddAddSelectionOverrideRequest
val request = AddAdSelectionOverrideRequest.Builder()
    .setAdSelectionConfig(adSelectionConfig)
    .setDecisionLogicJs(decisionLogicJS)
    .build()

// Run the call to override the JavaScript for the given AdSelectionConfig
// Note that this only takes effect in apps marked as debuggable
testAdSelectionManager.overrideAdSelectionConfigRemoteInfo(
    request,
    executor,
    outComeReceiver)

Java

TestAdSelectionManager testAdSelectionManager =
  context.getSystemService(AdSelectionManager.class).getTestAdSelectionManager();

// Initialize AdSelectionConfig =
AdSelectionConfig adSelectionConfig = new AdSelectionConfig.Builder()
    .setSeller(seller)
    .setDecisionLogicUrl(decisionLogicUrl)
    .setCustomAudienceBuyers(customAudienceBuyers)
    .setAdSelectionSignals(adSelectionSignals)
    .setSellerSignals(sellerSignals)
    .setPerBuyerSignals(perBuyerSignals)
    .build();

// Initialize AddAddSelectionOverrideRequest
AddAdSelectionOverrideRequest request = AddAdSelectionOverrideRequest.Builder()
    .setAdSelectionConfig(adSelectionConfig)
    .setDecisionLogicJs(decisionLogicJS)
    .build();

// Run the call to override the JavaScript for the given AdSelectionConfig
// Note that this only takes effect in apps marked as debuggable
testAdSelectionManager.overrideAdSelectionConfigRemoteInfo(
    request,
    executor,
    outComeReceiver);

Consulte a seção Executar a seleção de anúncios para mais informações sobre o que cada um dos campos na AdSelectionConfig representa. A principal diferença é que o decisionLogicUrl pode ser definido como um valor do marcador que será ignorado.

Para substituir o JavaScript usado durante a seleção de anúncios, o decisionLogicJs precisa conter as assinaturas de função adequadas do lado do vendedor. Confira como ler um arquivo JavaScript como uma string no app de exemplo da API Protected Audience no GitHub (link em inglês).

O método overrideAdSelectionConfigRemoteInfo() assíncrono usa o objeto OutcomeReceiver para informar o resultado da chamada de API.

O callback onResult() indica que a substituição foi aplicada. Futuras chamadas para selectAds() vão usar a lógica de decisões e relatórios que você transmitiu como a substituição.

O callback onError() indica duas condições possíveis:

  • Se ocorrer uma tentativa de substituição com argumentos inválidos, a AdServiceException vai indicar uma IllegalArgumentException como causa.
  • Se ocorrer uma tentativa de substituição com um app que não está sendo executado no modo de depuração com as opções do desenvolvedor ativadas, a AdServiceException vai indicar IllegalStateException como causa.

Redefinir substituições de venda

Esta seção pressupõe que você substituiu o JavaScript de venda e tem uma referência ao TestAdSelectionManager e à AdSelectionConfig usados na seção anterior.

Para redefinir as substituições de todas as AdSelectionConfigs, faça o seguinte:

  1. Chame o método resetAllAdSelectionConfigRemoteOverrides() assíncrono com o objeto OutcomeReceiver adequado.

Kotlin

// Resets overrides for all AdSelectionConfigs
testAadSelectionManager.resetAllAdSelectionConfigRemoteOverrides(
  outComeReceiver)

Java

// Resets overrides for all AdSelectionConfigs
testAdSelectionManager.resetAllAdSelectionConfigRemoteOverrides(
    outComeReceiver);

Após redefinir as substituições do lado do vendedor, as chamadas para selectAds() usam qualquer decisionLogicUrl armazenado na AdSelectionConfig para tentar buscar o JavaScript necessário.

Se a chamada para resetAllAdSelectionConfigRemoteOverrides() falhar, o callback OutComeReceiver.onError() vai fornecer uma AdServiceException. Se ocorrer uma tentativa de remoção de substituições com um app que não está sendo executado no modo de depuração com as opções do desenvolvedor ativadas, AdServiceException vai indicar IllegalStateException como causa.

Substituir o JavaScript de compra

  1. Siga as etapas para aderir a um público-alvo personalizado.
  2. Crie uma AddCustomAudienceOverrideRequest com o comprador e o nome do público-alvo personalizado que você quer substituir, além da lógica de lances e os dados que você quer usar como substituição.
  3. Chame o método assíncrono overrideCustomAudienceRemoteInfo() com o objeto AddCustomAudienceOverrideRequest e os objetos Executor e OutcomeReceiver correspondentes.

Kotlin

val testCustomAudienceManager: TestCustomAudienceManager =
  context.getSystemService(CustomAudienceManager::class.java).getTestCustomAudienceManager()

// Join custom audience

// Build the AddCustomAudienceOverrideRequest
val request = AddCustomAudienceOverrideRequest.Builder()
    .setBuyer(buyer)
    .setName(name)
    .setBiddingLogicJs(biddingLogicJS)
    .setTrustedBiddingSignals(trustedBiddingSignals)
    .build()

// Run the call to override JavaScript for the given custom audience
testCustomAudienceManager.overrideCustomAudienceRemoteInfo(
    request,
    executor,
    outComeReceiver)

Java

TestCustomAudienceManager testCustomAudienceManager =
  context.getSystemService(CustomAudienceManager.class).getTestCustomAudienceManager();

// Join custom audience

// Build the AddCustomAudienceOverrideRequest
AddCustomAudienceOverrideRequest request =
    AddCustomAudienceOverrideRequest.Builder()
        .setBuyer(buyer)
        .setName(name)
        .setBiddingLogicJs(biddingLogicJS)
        .setTrustedBiddingSignals(trustedBiddingSignals)
        .build();

// Run the call to override JavaScript for the given custom audience
testCustomAudienceManager.overrideCustomAudienceRemoteInfo(
    request,
    executor,
    outComeReceiver);

Os valores de comprador e nome são os mesmos usados para criar o público-alvo personalizado. Saiba mais sobre esses campos.

Além disso, é possível especificar dois outros parâmetros:

  • biddingLogicJs: JavaScript que contém a lógica do comprador usada durante a seleção do anúncio. Confira as assinaturas de função necessárias no JavaScript.
  • trustedBiddingSignals: indicadores de lance a serem usados durante a seleção do anúncio. Para fins de testes, essa pode ser uma string vazia.

O método overrideCustomAudienceRemoteInfo() assíncrono usa o objeto OutcomeReceiver para informar o resultado da chamada de API.

O callback onResult() indica que a substituição foi aplicada. As próximas chamadas para selectAds() usam a lógica de lances e relatórios que você transmitiu como a substituição.

O callback onError() indica duas condições possíveis.

  • Se ocorrer uma tentativa de substituição com argumentos inválidos, a AdServiceException vai indicar uma IllegalArgumentException como causa.
  • Se ocorrer uma tentativa de substituição com um app que não está sendo executado no modo de depuração com as opções do desenvolvedor ativadas, a AdServiceException vai indicar IllegalStateException como causa.

Redefinir substituições de compra

Esta seção pressupõe que você substituiu o JavaScript de compra e tem uma referência ao TestCustomAudienceManager usado na seção anterior.

Para redefinir substituições de todos os públicos-alvo personalizados, faça o seguinte:

  1. Chame o método resetAllCustomAudienceOverrides() assíncrono com os objetos Executor e OutcomeReceiver correspondentes.

Kotlin

// Resets overrides for all custom audiences
testCustomAudienceManager.resetCustomAudienceRemoteInfoOverride(
    executor,
    outComeReceiver)

Java

// Resets overrides for all custom audiences
testCustomAudienceManager.resetCustomAudienceRemoteInfoOverride(
    executor,
    outComeReceiver)

Após redefinir as substituições de compra, todas as próximas chamadas para selectAds() vão usar qualquer biddingLogicUrl e trustedBiddingData armazenados no CustomAudience para tentar buscar o JavaScript necessário.

Se a chamada para resetCustomAudienceRemoteInfoOverride() falhar, o callback OutComeReceiver.onError() vai fornecer uma AdServiceException. Se ocorrer uma tentativa de remoção de substituições com um app que não está sendo executado no modo de depuração com as opções do desenvolvedor ativadas, a AdServiceException vai indicar IllegalStateException como causa.

Configurar um servidor de relatórios

Ao usar substituições de busca remota, você ainda vai precisar configurar um servidor que o dispositivo ou emulador pode acessar para responder a eventos de relatórios. Um endpoint simples que retorna 200 é suficiente para realizar testes. O repositório do GitHub inclui definições de serviço da OpenAPI, que podem ser implantadas em uma plataforma de simulação ou microsserviços com suporte. Para conferir mais detalhes, consulte o arquivo README (em inglês) do projeto.

Ao procurar pelas definições da OpenAPI, também procure pelo reporting-server.json. Esse arquivo contém um endpoint simples que retorna 200, representando um código de resposta HTTP. Esse endpoint é usado durante selectAds() e indica à API Protected Audience que o relatório de impressões foi concluído.

Funcionalidade para testes

  • Faça exercícios para aderir ou sair e configurar um público-alvo personalizado com base em ações anteriores do usuário.
  • Inicie a seleção de anúncios no dispositivo usando JavaScripts hospedados remotamente.
  • Observe como a associação de um app a configurações de públicos-alvo personalizados pode afetar os resultados da seleção de anúncios.
  • Use os relatórios de impressão após a seleção de anúncios.

Limitações

A tabela abaixo lista as limitações de processamento da API Protected Audience. Os limites apresentados podem estar sujeitos a mudanças com base no feedback. Para recursos em desenvolvimento, leia as notas da versão.

Componente Descrição do limite Valor do limite
Público-alvo (CA) personalizado Número máximo de anúncios por CA 100
Número máximo de CAs por aplicativo 1000
Número máximo de apps que podem criar um CA 1000
Tempo de atraso máximo para ativação de um CA a partir do horário de criação 60 dias
Tempo de expiração máximo de um CA a partir do tempo de ativação 60 dias
Número máximo de CAs no dispositivo 4000
Tamanho máximo do nome do CA 200 bytes
Tamanho máximo do URI de busca diária 400 bytes
Tamanho máximo do URI da lógica de lances 400 bytes
Tamanho máximo dos dados de lances confiáveis 10 KB
Tamanho máximo dos indicadores de lances do usuário 10 KB
Taxa máxima de chamada de leaveCustomAudience por comprador 1 por segundo
Taxa máxima de chamada de joinCustomAudience por comprador 1 por segundo
Busca em segundo plano de CA Tempo limite da conexão 5 segundos
Tempo limite de leitura HTTP 30 segundos
Tamanho total máximo do download 10 KB
Duração máxima de uma iteração de busca 5 minutos
Número máximo de CAs atualizadas por job 1000
Seleção de anúncios Número máximo de compradores A confirmar
Número máximo de CAs por comprador A confirmar
Número máximo de anúncios em um leilão A confirmar
Tempo limite da conexão inicial 5 segundos
Tempo limite de leitura da conexão 5 segundos
Tempo máximo de execução da AdSelection geral 10 segundos
Tempo máximo de execução de lances por CA na AdSelection 5 segundos
Tempo máximo de execução da pontuação na AdSelection 5 segundos
Tempo máximo de execução da AdSelection por comprador A confirmar
Tamanho máximo dos indicadores de seleção de anúncio/vendedor/por comprador A confirmar
Tamanho máximo de scripts de vendedor/comprador A confirmar
Tarifa máxima de chamadas para selectAds 1 QPS
Relatórios de impressão Tempo mínimo antes de remover a seleção de anúncios da persistência 24 horas
Número máximo de seleções de anúncios de armazenamento A confirmar
Tamanho máximo do URL de saída do relatório A confirmar
Tempo máximo para relatórios de impressão A confirmar
Número máximo de novas tentativas para chamadas de notificação A confirmar
Tempo limite de conexão 5 segundos
Tempo total de execução máximo para reportImpression 2 segundos
Tarifa máxima de chamadas para reportImpressions 1 QPS
Relatórios de eventos Número máximo de beacons por comprador por leilão 10

Número máximo de beacons por vendedor por leilão

10

Tamanho máximo da chave de evento

40 bytes

Tamanho máximo dos dados do evento

64 KB

Anúncios Tamanho máximo da lista de anúncios 10 KB compartilhados por todos os AdData em um único CA para contexto
URLs Tamanho máximo de qualquer string de URL aceita como entrada A confirmar
JavaScript Tempo máximo de execução 1 segundo para lances e pontuação para o relatório de impressão
Memória máxima usada 10 MB

Informar bugs e problemas

Seu feedback é uma parte crucial do Sandbox de privacidade no Android. Avise nossa equipe sobre problemas encontrados ou ideias para melhorar o Sandbox de privacidade do Android.