API de simulación de RTT de TURTLEDOVE

Como parte de Privacy Sandbox, Chrome propuso TURTLEDOVE, una API en el navegador destinada a permitir que los anunciantes y las empresas de tecnología publicitaria muestren anuncios orientados a grupos de intereses sin depender de cookies de terceros, lo que protege a los usuarios del seguimiento entre sitios. Antes de que Chrome implemente TURTLEDOVE, el equipo de RTB de Google ofrece una simulación de la API de TURTLEDOVE del servidor que permite a sus socios de RTB (socios de Authorized Buyers y de Open Bidding) experimentar con la API. La simulación permite a los socios y Google obtener información sobre la eficacia del flujo de estilo TURTLEDOVE, generar comentarios relevantes sobre posibles mejoras de la API en foros públicos y facilitar la transición para admitir publicidad personalizada sin depender de cookies de terceros.

En la primera fase de la simulación, los ofertantes alojan la membresía del grupo de interés. Los ofertantes también proporcionan funciones de ofertas a Google con anticipación mediante una API. En el momento de la entrega, Google divide cada solicitud de oferta en el alcance de la simulación en dos solicitudes: una solicitud contextual y una solicitud basada en intereses. La solicitud contextual será similar a la solicitud de oferta actual, pero sin identificadores de usuario disponibles (como los campos google_user_id, hosted_match_data). Las solicitudes de grupos de interés no contienen información contextual y solo contienen campos de identificación de usuarios (sujetos a los controles de privacidad existentes). Las ofertas del grupo de interés no contienen un valor de CPM; en su lugar, hacen referencia a una función de ofertas que Google ejecuta en el entorno de zona de pruebas. La subasta se ejecuta normalmente con ofertas contextuales y ofertas calculadas por las funciones de ofertas.

Durante la primera fase de la simulación, Google enviará ID de usuario seudónimos en las solicitudes basadas en intereses. El objetivo es minimizar el trabajo de implementación en ambos lados para poder comenzar los experimentos antes. La presencia de identificadores de usuario en las solicitudes basadas en intereses estará sujeta a las protecciones y los controles de privacidad existentes (como cuando un usuario inhabilita la publicidad personalizada).

Flujo

diagrama de flujo

  1. El ofertante de RTB trabaja con anunciantes para crear, mantener y alojar grupos de interés para cada anunciante y membresía del usuario en esos grupos de intereses.
  2. Cuando el usuario visite una página web del publicador, el navegador del usuario descargará la etiqueta de anuncio de Google. El navegador del usuario solicita un anuncio de la plataforma de Google Publisher.
  3. El ofertante de RTB proporciona a Google una o más funciones de oferta (como funciones de JavaScript) con anticipación. (Consulta la sección Funciones de ofertas).
  4. Para la pequeña fracción de solicitudes dentro del alcance del experimento, Google envía solicitudes de ofertas contextuales independientes y solicitudes de ofertas basadas en intereses a cada ofertante que participa en el experimento (consulta la sección Solicitudes de ofertas).
  5. El ofertante utiliza el ID de usuario seudónimo disponible en la solicitud de oferta del grupo de intereses y lo asigna a los grupos de interés correspondientes. El ofertante de RTB mostrará respuestas de ofertas contextuales y respuestas de ofertas basadas en intereses (consulta la sección Respuestas a ofertas).
    1. Las respuestas de ofertas contextuales serán similares a las respuestas de oferta actuales con cero o más ofertas contextuales. Además, la respuesta de oferta contextual puede contener indicadores contextuales personalizados de ofertantes que se proporcionarán a la función de oferta como una entrada.
    2. Las respuestas a ofertas basadas en intereses no especificarán una oferta, sino que especificarán el nombre de la función de ofertas. Google ejecutará la función de ofertas para obtener una oferta.
  6. Google realiza una subasta del servidor con los siguientes candidatos:

    1. Ofertas de la respuesta contextual.
    2. Ofertas de la respuesta del grupo de interés con precios de oferta calculados mediante la ejecución de las funciones de oferta
    3. Ofertas regulares de otros ofertantes

    Tenga en cuenta que esta es la misma subasta que hoy.

  7. Google muestra un anuncio ganador en el navegador del usuario, que se renderiza normalmente.

Funciones de ofertas

Las funciones de ofertas son funciones que proporcionan los ofertantes que mostrarán un valor de oferta para un anuncio determinado basado en grupos de intereses y un espacio publicitario . En la propuesta TURTLEDOVE original, esta función se almacenará en el navegador del usuario. En esta simulación, los ofertantes subirán las funciones de oferta a Google mediante una API antes de la publicación de anuncios. Durante la publicación de anuncios, la respuesta del grupo de interés especificará un nombre para la función de ofertas. Google ejecutará esa función de ofertas en un entorno de zona de pruebas para obtener el valor de la oferta. Este valor de oferta basada en intereses ingresará a la misma subasta que la oferta contextual.

Interfaz de la función de ofertas

La función de ofertas debe ser una función sin efectos secundarios pura implementada en JavaScript que se ejecutará en una zona de pruebas proporcionada por Exchange. Una función de oferta no tiene acceso a la red, el almacenamiento ni otras formas de E/S y no puede conservar ningún estado entre invocaciones para diferentes solicitudes de oferta. La función de ofertas calcula y muestra un CPM de precio de oferta para un candidato de anuncio determinado de manera algorítmica según la combinación de datos contextuales y datos del grupo de intereses.

Una función de oferta debe aceptar y ejecutar con un objeto vacío como su parámetro de entrada; se proporciona una entrada vacía a las funciones de oferta durante su inicialización única. En el momento de la inicialización, se crea e invoca una instantánea de la función de ofertas varias veces para permitir que el compilador JIT (justo a tiempo) optimice los hotspots en el 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;
}

Los campos con nombre en el argumento del objeto inputs incluyen (sujetos a cambios a medida que el experimento avanza):

openrtbContextualBidRequest (JS Object) La solicitud de oferta contextual en el protocolo OpenRTB. Los ofertantes que usan el protocolo de RTB de Authorized Buyers deben ignorar esta entrada y no deben usarla en sus funciones de oferta.
googleContextualBidRequest (Objeto de JS) La solicitud de oferta contextual en el protocolo de Authorized Buyers de Google. Los ofertantes que usen el protocolo OpenRTB deberían ignorar esta entrada y no deberían usarla en sus funciones de oferta.
customContextualSignal (Objeto de JS) Datos personalizados proporcionados por el ofertante en la respuesta a la oferta contextual. El ofertante determina el formato.
interestBasedBidData (Objeto de JS) Datos personalizados proporcionados por el ofertante en la respuesta a la oferta del grupo de intereses. El ofertante determina el formato.

Cómo administrar las funciones de ofertas a través de una API

Este recurso de API experimental permite a los ofertantes subir funciones de ofertas a Google y administrarlas.

Extremo del servicio base: https://realtimebidding.googleapis.com

Recurso: Función de ofertas

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

El campo, name, representa el nombre de la función de licitación, debe seguir el formato: bidders/{bidderAccountId}/biddingFunctions/{biddingFunctionName}, en el que un ofertante elige biddingFunctionName.

El campo biddingFunction es el código fuente de JavaScript de la función de ofertas, con los siguientes requisitos:

  • <5 MiB.
  • Cumpla con los requisitos de la interfaz de función de ofertas.
  • Debe admitir la ejecución sin ninguna entrada durante la creación inicial en la zona de pruebas.

Ejemplo:

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

Cómo crear una función de ofertas

Una función de oferta estará disponible para su uso en las respuestas del grupo de intereses durante una hora después de que la llamada a la API de CreateBiddingFunction se realice correctamente.

POST https://realtimebidding.googleapis.com/v1alpha/{parent=bidders/*}/biddingFunctions
Parámetros de ruta de acceso
parent String en el formato bidders/{bidderAccountId}
Body: Función de ofertas para crear
{
  "name": "bidders/1234567678/biddingFunctions/my_bidding_function_name",
  "biddingFunction": "(function(inputs) {return 1.23;})"
}
Respuesta (función de oferta)
{
  "name": "bidders/1234567678/biddingFunctions/my_bidding_function_name",
  "biddingFunction": "(function(inputs) {return 1.23;};)"
}

Cómo enumerar las funciones de ofertas existentes

GET https://realtimebidding.googleapis.com/v1alpha/bidders/{bidderAccountId}/biddingFunctions
Parámetros de ruta de acceso
parent String en el formato bidders/{bidderAccountId}.
Parámetros de consulta
pageToken Es el token de string que identifica una página de resultados que el servidor debe mostrar. Este valor se recibe de una respuesta de llamada ListBiddingFunctions anterior, si los resultados no caben en una página.
Respuesta
{
  "biddingFunctions": [
    {
      object (BiddingFunction)
    }
  ],
  "nextPageToken": string
}
Llamada de ejemplo
GET https://realtimebidding.googleapis.com/v1alpha/bidders/123456789/biddingFunctions

Cambios en el protocolo de RTB de simulación de TURTLEDOVE

Protocolo de RTB para Authorized Buyers

Solicitudes de oferta

Una solicitud de oferta contextual en el experimento tendrá el mismo aspecto que las solicitudes de oferta convencionales, pero con los identificadores de usuario seudónimos ocultos.

// 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 = ...;
  ...
}

Por ejemplo:

{
  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
    }]
  }]
}

Una solicitud basada en intereses en el experimento contendrá identificadores de usuario seudónimos convencionales, sujetos a todas las protecciones y los controles de privacidad existentes, pero no incluiría la información contextual (URL de la página, ID de publicador, 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 = ...;
  ...
}

Por ejemplo:

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"

Respuestas a ofertas

Una respuesta contextual de oferta puede contener datos contextuales personalizados y específicos del ofertante en formato arbitrario que se pasarán más adelante a la función de oferta.

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 ejemplo:

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

Una oferta basada en grupos de intereses

Cada oferta en la respuesta del grupo de intereses contendrá una referencia a la función de ofertas por su nombre. Los ofertantes proporcionarán con anticipación las funciones de ofertas.

// 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 = ...;
  ...
}

Por ejemplo:

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

Solicitudes de oferta

Solicitud contextual (en 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
  ...
}
Solicitud basada en intereses (en 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
      ...
    }
  }
}

Respuestas a ofertas

Una respuesta contextual de oferta puede contener datos contextuales personalizados y específicos del ofertante que se pasarán a la función de oferta más adelante.

// 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": ...
  }
}

Una respuesta a la oferta basada en grupos de intereses

Cada oferta en la respuesta del grupo de intereses contendrá una referencia a la función de ofertas por su nombre. Los ofertantes proporcionarán con anticipación las funciones de ofertas.

// 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": ...
       }
    }
    ...
  ]
}