API TURTLEDOVE RTB Simulation

Como parte do Sandbox de privacidade, o Chrome propôs a TURTLEDOVE, uma API no navegador que permite que os anunciantes e as empresas de tecnologias de publicidade mostrem anúncios segmentados por grupos de interesse sem depender de cookies de terceiros, protegendo os usuários de rastreamento entre sites. Antes de o Chrome implementar a TURTLEDOVE, a equipe do RTB do Google oferece uma simulação da API TURTLEDOVE do lado do servidor que permite que os parceiros de RTB (Authorized Buyers e parceiros do Open Bidding) testem a API. Com a simulação, os parceiros e o Google aprendem sobre a eficácia do fluxo no estilo TURTLEDOVE, geram feedback relevante sobre possíveis melhorias na API em fóruns públicos e facilitam a transição para o suporte à publicidade personalizada sem depender de cookies de terceiros.

Na primeira fase da simulação, os bidders hospedam a associação ao grupo de interesse. Os bidders também oferecem funções de lances ao Google antecipadamente por meio de uma API. No momento da veiculação, o Google divide cada solicitação de lance no escopo da simulação em duas solicitações: uma contextual e uma com base em interesses. A solicitação contextual será semelhante à solicitação de lance atual, mas sem identificadores de usuário (como campos google_user_id e hosted_match_data) disponíveis. As solicitações do grupo de interesse não contêm informações contextuais e contêm apenas campos de identificação do usuário (sujeitos aos controles de privacidade existentes). Os lances de grupo de interesse não contêm um valor de CPM, mas fazem referência a uma função de lances que o Google executa no lado do servidor em um ambiente sandbox. O leilão normalmente é executado com lances contextuais e lances calculados pelas funções de lance.

Durante a primeira fase da simulação, o Google envia IDs de usuários pseudônimos nas solicitações baseadas em interesses. O objetivo é minimizar o trabalho de implementação em ambos os lados para que possamos iniciar os experimentos antes. A presença de identificadores de usuário em solicitações com base em interesses vai estar sujeita às proteções e controles de privacidade atuais, por exemplo, quando um usuário desativa a publicidade personalizada.

Fluxo

fluxograma

  1. O bidder em RTB trabalha com anunciantes para criar, manter e hospedar grupos de interesse para cada anunciante e associação de usuários nesses grupos.
  2. Quando o usuário visita uma página da Web do editor, o navegador dele faz o download da tag de anúncio do Google. O navegador do usuário solicita um anúncio da plataforma do editor do Google.
  3. O bidder de RTB fornece ao Google uma ou mais funções de lance (como funções JavaScript) com antecedência. Consulte a seção Funções de lances.
  4. Para a pequena fração de solicitações no escopo do experimento, o Google envia solicitações de lance contextuais e solicitações de lance com base em interesses separadas para cada bidder que participa do experimento. Consulte a seção Solicitações de lance.
  5. O bidder usa o ID de usuário pseudônimo disponível na solicitação de lance do grupo de interesses e o mapeia para os grupos de interesse correspondentes. O bidder de RTB retornará respostas de lance contextual e respostas de lance com base em interesses. Consulte a seção Respostas do lance.
    1. As respostas de lances contextuais serão semelhantes à resposta de lance de hoje com zero ou mais lances contextuais. Além disso, a resposta do lance contextual pode carregar indicadores de contexto personalizados do bidder que serão fornecidos à função de lances como entrada.
    2. As respostas de lances com base em interesses não especificam um lance, mas sim o nome da função de lances. O Google executará a função de lances para receber um lance.
  6. O Google realiza um leilão do lado do servidor com os seguintes candidatos:

    1. Lances da resposta contextual.
    2. Lances da resposta do grupo de interesse com preços de lance calculados executando as funções de lance.
    3. Lances regulares de outros bidders.

    Este é o mesmo leilão de hoje.

  7. O Google retorna um anúncio vencedor para o navegador do usuário, que é renderizado normalmente.

Funções de lances

As funções de lances são aquelas fornecidas pelos bidders que retornam um valor de lance para um determinado anúncio com base em um grupo de interesse e um espaço . Na proposta TURTLEDOVE original, essa função será armazenada no navegador do usuário. Nesta simulação, os bidders fazem upload das funções de lances para o Google usando uma API antes da veiculação do anúncio. Durante a veiculação do anúncio, a resposta do grupo de interesse especifica um nome de função de lance. O Google vai executar essa função de lances em um ambiente de sandbox para receber um valor de lance. Esse valor de lance com base em interesses participará do mesmo leilão que o lance contextual.

Interface da função de lances

A função de lances precisa ser uma função sem efeitos colaterais pura implementada em JavaScript e executada em um sandbox fornecido pela troca. Uma função de lance não tem acesso à rede, ao armazenamento ou a outras formas de E/S e não pode manter nenhum estado entre as invocações para diferentes solicitações de lance. A função de lances calcula e retorna um CPM de preço de lance para um determinado candidato por algoritmo com base na combinação de dados contextuais e dados do grupo de interesse.

Uma função de lance precisa aceitar e ser executada com um objeto vazio como parâmetro de entrada. Uma entrada vazia é fornecida às funções de lance durante a inicialização única. No momento da inicialização, um snapshot da função de lances é criado e invocado algumas vezes para permitir que o compilador JIT (just-in-time) otimize os pontos de acesso no código.

/**
 * Returns a bid price CPM for a given ad candidate.
 *
 * @param {Object} inputs an object with the
 *                 following named fields:
 *                   - openrtbContextualBidRequest or googleContextualBidRequest
 *                   - customContextualSignal
 *                   - interestBasedBidData
 */
function biddingFunction(inputs) {
  ...
  return inputs.interestBasedBidData.cpm
      * inputs.customContextualSignals.placementMultiplier;
}

Os campos nomeados no argumento inputs do objeto incluem (sujeito a alterações à medida que o experimento avança):

openrtbContextualBidRequest (Objeto JS) A solicitação de lance contextual no protocolo OpenRTB. Os bidders que usam o protocolo RTB do Authorized Buyers precisam ignorar essa entrada e não podem usá-la nas funções de lances.
googleContextualBidRequest (Objeto JS) A solicitação de lance contextual no protocolo do Google Authorized Buyers. Os bidders que usam o protocolo OpenRTB devem ignorar essa entrada e não a usar nas funções de lance.
customContextualSignal (Objeto JS) Dados personalizados fornecidos pelo bidder na resposta do lance contextual. O bidder determina o formato.
interestBasedBidData (Objeto JS) Dados personalizados fornecidos pelo bidder na resposta do lance do grupo de interesse. O bidder determina o formato.

Como gerenciar funções de lances usando uma API

Esse recurso experimental da API permite que os bidders façam upload das funções de lances para o Google e gerenciem essas funções.

Endpoint de serviço base: https://realtimebidding.googleapis.com

Recurso: função de lance

{
  "name": string,
  "biddingFunction": string
}

O campo, name, representa o nome da função de lances, precisa seguir o formato: bidders/{bidderAccountId}/biddingFunctions/{biddingFunctionName}, em que biddingFunctionName é escolhido por um bidder.

O campo biddingFunction é o código-fonte JavaScript da função de lances, com os seguintes requisitos:

  • Tamanho menor que 5 MiB.
  • Segue os requisitos da interface de funções de lances.
  • Precisa oferecer suporte à execução sem nenhuma entrada durante a criação inicial no sandbox.

Exemplo:

{
  "name": "bidders/1234567678/biddingFunctions/my_bidding_function_name",
  "biddingFunction": "(function(inputs) {return 1.23;})"
}

Como criar uma função de lances

Uma função de lances vai estar disponível para uso nas respostas do grupo de interesse em aproximadamente uma hora após uma chamada de API CreateBiddingFunction.

POST https://realtimebidding.googleapis.com/v1alpha/{parent=bidders/*}/biddingFunctions
Parâmetros de caminho
parent String no formato bidders/{bidderAccountId}
Body: Função de lances a ser criada
{
  "name": "bidders/1234567678/biddingFunctions/my_bidding_function_name",
  "biddingFunction": "(function(inputs) {return 1.23;})"
}
Resposta (função de lances)
{
  "name": "bidders/1234567678/biddingFunctions/my_bidding_function_name",
  "biddingFunction": "(function(inputs) {return 1.23;};)"
}

Como listar as funções atuais de lances

GET https://realtimebidding.googleapis.com/v1alpha/bidders/{bidderAccountId}/biddingFunctions
Parâmetros de caminho
parent String no formato bidders/{bidderAccountId}.
Parâmetros de consulta
pageToken Token de string que identifica uma página de resultados que o servidor precisa retornar. Esse valor será recebido de uma resposta de chamada ListBiddingFunctions anterior, se os resultados não couberem em uma página.
Resposta
{
  "biddingFunctions": [
    {
      object (BiddingFunction)
    }
  ],
  "nextPageToken": string
}
Exemplo de chamada
GET https://realtimebidding.googleapis.com/v1alpha/bidders/123456789/biddingFunctions

Alterações no protocolo RTB da simulação TURTLEDOVE

Protocolo RTB do Authorized Buyers

Solicitações de lance

Uma solicitação de lance contextual no experimento será igual às solicitações de lance convencionais, mas com identificadores de usuário pseudônimos editados.

// All fields will be filled unless otherwise specified.
message BidRequest {
  // Fields below would not be populated in the experiment
  optional string google_user_id = ...;
  optional uint32 cookie_version = ...;
  optional int32 cookie_age_seconds = ...;
  optional bytes hosted_match_data = ...;
  optional string session_id = ...;

  // Contextual fields below will be populated
  optional string publisher_id = ...;
  optional string url = ...;
  ...
  message Mobile {
    // Device advertising identifiers below would not be populated
    // in the contextual requests in the experiment
    optional bytes encrypted_advertising_id = ...;
    optional bytes advertising_id = ...;
    ...
    optional bytes encrypted_hashed_idfa = ...;
    optional bytes hashed_idfa = ...;
    ...
  }
  ...
  message AdSlot {
    message MatchingAdData {
      repeated int64 billing_id = ...;
      ...
    }
    ...
  }
  repeated AdSlot adslot = ...;
  ...
}

Exemplo:

{
  id: "_\321\326\000\n\301\207\n\323\n\227",
  ip: "S\030\347",
  user_agent: "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
  publisher_country: "RU",
  geo_criteria_id: 9061060,
   adslot: [{
    id: 1,
    ad_block_key: 3613182520,
    width:   [240,200,120],
    height:   [400,200,240],
    matching_ad_data:   [{
      billing_id:     [923487589],
      minimum_cpm_micros: 850000
    }]
  }]
}

Uma solicitação com base em interesses no experimento conterá identificadores de usuário pseudônimos convencionais, sujeitos a todas as proteções e controles de privacidade existentes, mas não terá informações contextuais (URL da página, ID do editor etc.).

// Most fields would not be populated in the experiment unless otherwise specified.
message BidRequest {
   // Will be provided, subject to the existing privacy controls.
  optional string google_user_id = ...;
  optional uint32 cookie_version = ...;
  optional int32 cookie_age_seconds = ...;
  optional bytes hosted_match_data = ...;

  message AdSlot {
    // Will be filled.
    repeated int32 width = ...;
    repeated int32 height = ...;
    optional ConsentedProvidersSettings consented_providers_settings = ...;
    optional bool regs_gdpr = ...;
    optional bool regs_lgpd = ...;

    message MatchingAdData {
      // Will be filled.
      repeated int64 billing_id = ...;
      ...
    }
    ...
  }
  repeated AdSlot adslot = ...;
  ...
}

Exemplo:

id: "_\322\207\000\003\320\n\031\177C\307\215\035"
adslot {
  id: 1
  width: 1200
  height: 60
  consented_providers_settings {
    consented_providers: 292
    tcf_consent_string: "CO-eDrRO-eDrREkAAAAAAAAeYwf95y3p-wzhheMCY70-vv__7v3ff_3g"
  }
  regs_gdpr: true
  matching_ad_data {
    billing_id: 9833784997
  }
}
google_user_id: "ABCDEF1"
hosted_match_data: "ABCABCABC2"

Respostas de lance

Uma resposta de lance contextual pode conter dados contextuais personalizados específicos do bidder em formato arbitrário que serão transmitidos à função de lances posteriormente.

message BidResponse {
  message Ad {
    message AdSlot {
      required int64 max_cpm_micros = ...;
      ...
    }
    repeated AdSlot adslot = ...;
    ...
  }
  repeated Ad ad = ...;
  // Contains contextual signals that will be passed to the bidding function.
  // This can be any JSON value. For example:
  // {"foo": "bar", "base": [1, 2, 3]}
  optional google.protobuf.Value custom_contextual_signal = ...;

  ...
}

Por exemplo:

ad {
  html_snippet: "<iframe src=\"http://example.com/something" width=\"300\" height=\"250\" scrolling=\"no\" frameBorder=\"0\" ></iframe>"
  adslot {
    id: 1
    max_cpm_micros: 100000
    billing_id: 1234567890
  }
  click_through_url: "https://www.example.com.pl"
  attribute: 47
  buyer_creative_id: "FFI399F3HI9HFH"
  width: 300
  height: 250
  impression_tracking_url: "http://example.com/impression"
}
custom_contextual_signal {
 struct_value {
   fields {
     name: "string_data_name"
     value {
       string_value: "string_value_1"
     }
   }
   fields {
     name: "bool_data_name"
     value {
       bool_value: true
     }
   }
 }
}
processing_time_ms: 1

Um lance com base em grupo de interesse

Cada lance na resposta de lance do grupo de interesse conterá uma referência à função de lance pelo nome. As funções de lances serão fornecidas por um bidder com antecedência.

// All fields should be filled by a bidder as discussed in
// https://developers.google.com/authorized-buyers/rtb/response-guide
// unless otherwise specified.
message BidResponse {
  // Ad HTML code that will be rendered normally upon winning.
  optional string html_snippet = ...;

  message Ad {
    message AdSlot {
      // Should not be populated for interest group-based bids.
      required int64 max_cpm_micros = ...;
      ...
    }
    repeated AdSlot adslot = ...;

    // Will be filled.
    // This is the bidding function name that references a bidding function
    // that is provided ahead of time through Bidding functions API resource.
    optional string bidding_function_name = ...;

    // Contains interest group-related data that will be passed
    // to the bidding function. This can be any JSON value.
    optional google.protobuf.Value interest_group_data = ...;
    ...
  }
  repeated Ad ad = ...;
  ...
}

Exemplo:

ad {
  html_snippet: "<iframe src=\"http://example.com/something" width=\"300\" height=\"250\" scrolling=\"no\" frameBorder=\"0\" ></iframe>"
  adslot {
    id: 1
    max_cpm_micros: 0
    billing_id: 1234567890
    bidding_function_name: "bidders/123/biddingFunctions/my_bidding_function_1"
    interest_group_data {
      struct_value {
        fields {
          name: "string_data_name"
          value {
            string_value: "string_value_1"
          }
        }
        fields {
          name: "bool_data_name"
          value {
            bool_value: true
          }
        }
      }
    }
  }
  click_through_url: "https://www.example.com.pl"
  attribute: 47
  buyer_creative_id: "FFI399F3HI9HFH"
  width: 300
  height: 250
  impression_tracking_url: "http://example.com/impression"
}
processing_time_ms: 1

OpenRTB

Solicitações de lance

Solicitação contextual (em JSON)
// All fields will be filled unless otherwise specified.
{
  // Fields below would not be populated in the experiment
  "user": {...}

  "device": {
    // Fields below would not be populated in the experiment
    "ifa": ...
    "dpidsha1": ...
    "dpidmd5": ...


    // Other fields will not be affected by the experiment
    ...
  }

  // Other fields will not be affected by the experiment
  ...
}
Solicitação com base em interesses (em JSON)
// Most fields would not be populated in the experiment unless otherwise specified.
{
  // Will be provided, subject to the existing privacy controls.
  "user": {
    "id": "BFEUKH3"
    "buyeruid": "FEI3F3I29"
    "ext": {
      "consented_providers": [ 292 ]
      "tcf_consent_string": "CO-eDrRO-eDrREkAAilsbO2dYGD9Pn8HT3ZCY70-vv__7v3ff_3g"
    }
  }

  "imp": {
    // Will be provided, subject to the existing privacy controls.
    "banner": {
      "w": ...
      "h": ...
    }

    "ext": {
      // Will be provided, subject to the existing privacy controls.
      "billing_id": [...]

      // Other fields will not be provided by the experiment
      ...
    }
  }
}

Respostas de lance

Uma resposta de lance contextual pode conter dados contextuais personalizados específicos do bidder que seriam transmitidos à função de lances posteriormente.

// All fields should be filled by a bidder as discussed in
// https://developers.google.com/authorized-buyers/rtb/response-guide
// unless otherwise specified.
{
  ...
  "seatbid": [{
     "bid": [...],
     ...
  }],
  ...
  "ext": {
    // Contains contextual signals that will be passed to the bidding function.
    // This signal can be any JSON blob. For example:
    // {"foo", "bar", "base": [1, 2, 3]}
    "custom_contextual_signal": ...
  }
}

Uma resposta de lance com base em grupo de interesse

Cada lance na resposta de lance do grupo de interesse conterá uma referência à função de lance pelo nome. As funções de lances serão fornecidas por um bidder com antecedência.

// All fields should be filled by a bidder as discussed in
// https://developers.google.com/authorized-buyers/rtb/response-guide
// unless otherwise specified.
{
  "bid": [{
       "id": ...
       ...
       "ext": {
         // This is the bidding function name that references a bidding function
         // that is provided ahead of time through Bidding functions API resource.
         "bidding_function_name": ...

         // Contains interest group related data that will be passed to the
         // bidding function.
         // This signal can be any JSON blob. For example:
         // {"foo", "bar", "base": [1, 2, 3]}
         "interest_group_data": ...
       }
    }
    ...
  ]
}