Guía para desarrolladores de Indicadores de apps protegidas

Para ayudar a los desarrolladores a comenzar a experimentar con la API de Protected App Signals, en este documento, se describen todas las APIs dentro de la plataforma de la API, se detalla cómo configurar un entorno de pruebas y se brindan ejemplos de la configuración y las secuencias de comandos.

Historial de versiones

enero de 2024

Primera versión de la guía para desarrolladores que admite el lanzamiento del MVP de PAS

March 2024

Cambios en la API para admitir la versión M-2024-05 de la API de Android y la versión de abril de 2024 de los componentes del servidor. Cambios más destacados:

  • Se agregaron detalles sobre los permisos requeridos para la API en el dispositivo.
  • Se agregaron detalles sobre la administración de la cuota de indicadores integrados en el dispositivo.
  • Se actualizó la firma generateBid con cambios relacionados con la recuperación de anuncios contextuales y la compatibilidad con la salida.
  • Se actualizó la documentación de reportWin, incluida la compatibilidad de salida
  • Se actualizó la documentación de la API de recuperación de anuncios para quitar la compatibilidad con la recuperación de anuncios BYOS y documentar la UDF de recuperación de anuncios

Descripción general de la API

La plataforma de la API de Protected Signals incluye diferentes subconjuntos de la API en diferentes sistemas:

  • APIs de Android:
    • API de Signal Curation, que incluye lo siguiente:
    • API de Update Signals
    • API de Signals Encoding
    • API de Protected Auction Support (se usará en los SDKs para ejecutar la subasta protegida en los servidores de ofertas y subastas (B&A) con indicadores de app protegidos)
  • APIs del servidor:
    • API de Protected Auction: Una serie de secuencias de comandos de JS que se ejecutan en los servidores de ofertas y subastas. Esta API permite a los vendedores y compradores escribir la lógica para implementar la subasta protegida.
    • API de Ad Retrieval: Se ocupa de proporcionar una lista de anuncios candidatos, según la información contextual y la del usuario que se pone a disposición del servidor de ofertas del comprador.

Cliente de Android

En el cliente, la plataforma de Protected App Signals consta de tres APIs diferentes:

  • Update Signals: Una API del sistema Android que permite la selección de los indicadores en el dispositivo.
  • Signals Encoding: Una API de JavaScript para preparar los indicadores que se enviarán al servidor durante la subasta.
  • Protected Auction Support: Una API para admitir la ejecución de una subasta protegida en los servidores de ofertas y subastas. Esta API no es específica para Protected App Signals y también se usa para admitir subastas de la API de Protected Audience.

API de Update Signals

La API de Update Signals les proporciona a las tecnologías publicitarias la capacidad de registrar indicadores relacionados con el usuario y la app en nombre de un comprador. La API funciona en un modelo de delegación. El llamador proporciona un URI a partir del cual el framework recupera los indicadores correspondientes y la lógica para codificar esos indicadores que se usarán en la subasta.

La API requiere el permiso android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS.

La API de updateSignals() recuperará un objeto JSON del URI que describe qué indicadores agregar o quitar, y cómo prepararlos para la subasta.

Executor executor = Executors.newCachedThreadPool();
ProtectedSignalsManager protectedSignalsManager
     =  ProtectedSignalsManager.get(context);

// Initialize a UpdateSignalsRequest
UpdateSignalsRequest updateSignalsRequest = new
  UpdateSignalsRequest.Builder(Uri.parse("https://example-adtech1.com/signals"))
      .build();

OutcomeReceiver<Object, Exception> outcomeReceiver = new OutcomeReceiver<Object, Exception>() {
  @Override
  public void onResult(Object o) {
    //Post-success actions
  }

  @Override
  public void onError(Exception error) {
    //Post-failure actions
  };

// Call updateSignals
protectedSignalsManager.updateSignals(updateSignalsRequest,
    executor,
    outcomeReceiver);

La plataforma realiza una solicitud HTTPS para el URI proporcionado en la solicitud para recuperar las actualizaciones de los indicadores. Junto con las actualizaciones de los indicadores, la respuesta puede incluir un extremo que aloje la lógica de codificación para convertir los indicadores sin procesar en una carga útil codificada. Se espera que las actualizaciones de los indicadores tengan el formato JSON y puedan tener las siguientes claves:

Las claves de nivel superior del objeto JSON deben corresponder a uno de estos cinco comandos:

Clave

Descripción

put

Agrega un indicador nuevo y reemplaza los existentes con la misma clave. El valor

de esta clave es un objeto JSON en el que las claves son cadenas de base 64 correspondientes a la clave que se va a colocar y los valores son cadenas de base 64 correspondientes al valor que se va a colocar.

append

Agrega uno o varios indicadores nuevos a una serie temporal de indicadores, y quita los más antiguos

para incluir los nuevos si el tamaño de la serie supera el máximo determinado. El valor de esta clave es un objeto JSON en el que las claves son cadenas de base 64 correspondientes a la clave que se agrega y los valores son objetos con dos campos: "values" y "maxSignals".

"values": Una lista de cadenas de base 64 correspondientes a los valores del indicador que se agregarán a las series temporales.

"maxSignals": La cantidad máxima de valores permitidos en esta serie temporal. Si

la cantidad actual de indicadores asociados con la clave supera el objeto maxSignals, se quitarán los indicadores más antiguos. Ten en cuenta que puedes agregarlo a una clave introducida por put. Ten en cuenta que, si agregas más valores que la cantidad máxima, se producirá un error.

put_if_not_present

Agrega un indicador nuevo solo si no hay indicadores existentes con la misma clave. El valor de esta clave es un objeto JSON en el que las claves son cadenas de base 64 correspondientes a la clave que se va a colocar y los valores son cadenas de base 64 correspondientes al valor que se va a colocar.

remove

Quita el indicador de una llave. El valor es una lista de cadenas base 64 correspondientes a las claves de los indicadores que se deben borrar.

update_encoder

Proporciona una acción para actualizar el extremo y un URI que se puede usar

para recuperar una lógica de codificación. La subclave para proporcionar una acción de actualización es "action", y el

valor admitido actualmente solo es "REGISTER", que registrará el extremo del codificador si se proporciona por primera vez o reemplazará el existente con el extremo proporcionado recientemente. Es obligatorio proporcionar el extremo para la acción "REGISTER". La clave secundaria para proporcionar un extremo del codificador es "endpoint" y el valor es la cadena del URI

para el extremo.

Por ejemplo, Una solicitud JSON se vería de la siguiente manera:

{
    "put": {
        "AAAAAQ==": "AAAAZQ==",
        "AAAAAg==": "AAAAZg=="
    },
    "append": {
        "AAAAAw==": {
            "values": [
                "AAAAZw=="
            ],
            "max_signals": 3
        }
    },
    "put_if_not_present": {
        "AAAABA==": "AAAAaQ==",
        "AAAABQ==": "AAAAag=="
    },
    "update_encoder": {
        "action": "REGISTER",
        "endpoint": "https://adtech1.com/Protected App Signals_encode_script.js"
    }
}

Los indicadores tendrán una cuota integrada en el dispositivo de entre 10 y 15 KB. Una vez que se supere la cuota, la PPAPI expulsará los indicadores mediante una estrategia FIFO. El proceso de expulsión permitirá que se supere un poco la cuota durante intervalos cortos de tiempo para reducir la frecuencia de las expulsiones.

API de Signals Encoding

Los compradores deben proporcionar una función de Java Script que se utilice para codificar los indicadores almacenados en el dispositivo que se enviarán al servidor durante la subasta protegida. Los compradores pueden proporcionar esta secuencia de comandos agregando la URL que se puede recuperar con la clave "update_encoder" en cualquiera de las respuestas a una solicitud a la API de UpdateSignal. La secuencia de comandos tendrá la siguiente firma:

function encodeSignals(signals, maxSize) {
  let result = new Uint8Array(maxSize);
  // first entry will contain the total size
  let size = 1;
  let keys = 0;
  
  for (const [key, values] of signals.entries()) {
    keys++;
    // In this encoding we only care about the first byte
    console.log("key " + keys + " is " + key)
    result[size++] = key[0];
    result[size++] = values.length;
    for(const value of values) {
      result[size++] = value.signal_value[0];
    }
  }
  result[0] = keys;
  
  return { 'status': 0, 'results': result.subarray(0, size)};
}

El parámetro signals es un mapa de claves en forma de UInt8Arrays de tamaño 4 para las listas de objetos de Protected App Signals. Cada objeto de Protected App Signals tiene los siguientes tres campos:

  • signal_value: Un UInt8Array que representa el valor del indicador.
  • creation_time: Un número que representa la hora de creación de los indicadores en segundos de época.
  • package_name: Una cadena que representa el nombre del paquete que creó el indicador.

El parámetro maxSize es un número que describe el tamaño del array más grande permitido para el resultado.

La función debería generar un objeto con dos campos:

  • status: Debe ser 0 si la secuencia de comandos se ejecutó de forma correcta.
  • results: Debe ser un UInt8Array con una longitud menor o igual que maxSize. Este array se enviará al servidor durante las subastas y será preparado por la secuencia de comandos prepareDataForAdRetrieval.

La codificación les proporciona a las tecnologías publicitarias una etapa inicial de ingeniería de atributos, en la que pueden realizar transformaciones, por ejemplo, comprimir indicadores sin procesar en versiones concatenadas, según su propia lógica personalizada. Ten en cuenta que, durante una subasta protegida que se ejecuta en los entornos de ejecución confiables (TEE), la lógica personalizada de la tecnología publicitaria tendrá acceso de lectura a las cargas útiles de los indicadores que generó la codificación. La lógica personalizada, conocida como función definida por el usuario (UDF), que se ejecuta en el TEE de B&A del comprador, tendrá acceso de lectura a los indicadores codificados y a otros indicadores contextuales que proporciona la app del publicador para realizar la selección de anuncios (recuperación de anuncios y ofertas).

Codificación de indicadores

Cada hora, los compradores que proporcionaron la lógica de codificación con sus indicadores registrados tendrán los indicadores codificadas en una carga útil de subasta. El array de bytes para la carga útil de la subasta se conservará en el dispositivo, estará encriptado y será recopilado por los vendedores como parte de los datos de la selección de anuncios para que se incluyan en una subasta protegida. Para realizar pruebas, puedes activar esta codificación fuera de su frecuencia por hora ejecutando el siguiente comando:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
Control de las versiones de la lógica del codificador

Cuando se realiza una solicitud para descargar la lógica personalizada del codificador de la tecnología publicitaria, el extremo de esta puede responder con un número de versión en los encabezados de respuesta. Esta versión se conserva junto con la lógica del codificador en el dispositivo. Cuando se codifican los indicadores sin procesar, la carga útil codificada se conserva junto con la versión que se usó para la codificación. Esta versión también se envía al servidor de B&A durante una subasta protegida, de modo que las tecnologías publicitarias puedan alinear su lógica de oferta y codificación en función de la versión.

Response header for providing encoder version : X_ENCODER_VERSION

API de Protected Auction Support

En el dispositivo, ejecutar una subasta para los indicadores de apps protegidos es lo mismo que ejecutar una subasta para públicos protegidos.

Servicios de ofertas y subastas

Las APIs del servidor incluyen lo siguiente:

  • API de Protected Auction: Una serie de funciones de JS o UDF que los compradores y vendedores pueden implementar en los componentes de B&A que poseen para determinar las ofertas y la lógica de la subasta.
  • API de Ad Retrieval: Los compradores pueden implementar esta API si implementan un extremo de REST que se ocupará de proporcionar un conjunto de anuncios candidatos para la subasta de los indicadores de apps protegidos.

API de Protected Auction

La API de Protected Auction consta de la API de JS o UDF que los compradores y vendedores pueden usar para implementar su lógica de subasta y oferta.

UDF de la tecnología publicitaria del comprador
UDF prepareDataForAdRetrieval

Antes de que se puedan usar los indicadores de apps protegidas para recuperar anuncios candidatos del servicio de recuperación de anuncios de TEE, los compradores deben decodificar y preparar los indicadores de apps protegidas y otros datos que proporcione el vendedor. El resultado de la UDF prepareDataForAdRetrieval de los compradores se pasa al servicio de recuperación de anuncios para obtener los anuncios candidatos Top-K para ofertar.

// Inputs
// ------
// encodedOnDeviceSignals: A Uint8Array of bytes from the device.
// encodedOnDeviceSignalsVersion: An integer representing the encoded
//   version of the signals.
// sellerAuctionSignals: Information about auction (ad format, size) derived
//                       contextually.
// contextualSignals: Additional contextual signals that could help in
//                    generating bids.
//
// Outputs
// -------
// Returns a JSON structure to be used for retrieval.
// The structure of this object is left to the adtech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
   return {};
}
UDF generateBid

Una vez que se muestran los anuncios candidatos Top-K, los candidatos se pasan a la lógica de oferta personalizada del comprador, la UDF generateBid:

// Inputs
// ------
// ads: Data string returned by the ads retrieval service. This can include Protected App Signals
//   ads and related ads metadata.
// sellerAuctionSignals: Information about the auction (ad format, size),
//                       derived contextually
// buyerSignals: Any additional contextual information provided by the buyer
// preprocessedDataForRetrieval: This is the output of this UDF.
function generateBid(ads, sellerAuctionSignals, buyerSignals,
                    preprocessedDataForRetrieval,
                    rawSignals, rawSignalsVersion) {
    return { "ad": <ad Value Object>,
             "bid": <float>,
             "render": <render URL string>,
             'adCost': <optional float ad cost>,
             "egressPayload": <limitedEgressPayload>,
             "temporaryUnlimitedEgressPayload": <temporaryUnlimitedEgressPayload>
    };
}

El resultado de esta función es una oferta única para un candidato de anuncio, representada como un equivalente JSON de ProtectedAppSignalsAdWithBidMetadata. La función también puede mostrar dos arrays que luego se pasarán a reportWin para habilitar el entrenamiento de modelos (para obtener más detalles sobre la salida y el entrenamiento de modelos, consulta la sección de informes en la explicación de PAS).

UDF informeWin

Cuando finaliza una subasta, el servicio de subastas generará URLs de informes para los compradores y registrará los píxeles contadores con reportWin UDF (esta es la misma función reportWin que se usa para Protected Audiences). El dispositivo hará ping una vez que el cliente renderice el anuncio. La firma de este método es casi la misma que la versión de Protected Audience, excepto por dos parámetros adicionales egressPayload y temporaryUnlimitedEgressPayload que se usan para habilitar el entrenamiento de modelos y se propagan con los resultados de generateBid.

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals,
                   egressPayload, temporaryUnlimitedEgressPayload) {
  // ...
}
UDF de la tecnología publicitaria del vendedor
UDF scoreAd

Los vendedores usan esta UDF para seleccionar cuál de los anuncios recibidos de los compradores ganará la subasta.

function scoreAd(adMetadata, bid, auctionConfig,
                 trustedScoringSignals, bid_metadata) {
  // ...
  return {desirability: desirabilityScoreForThisAd,
              allowComponentAuction: true_or_false};
}
UDF reportResult

Esta UDF le permite al vendedor generar (en algún momento) informes al nivel del evento con la información sobre el anuncio ganador.

function reportResult(auctionConfig, reporting_metadata) {
  // ...
  registerAdBeacon({"click", clickUrl,"view", viewUrl});
  sendReportTo(reportResultUrl);
  return signalsForWinner;
}

API de Ad Retrieval

En la versión de MVP, el servicio de recuperación de anuncios será un servicio alojado y administrado por el comprador, y el servicio de ofertas recuperará los candidatos de anuncios de este servicio. A partir de abril de 2024, el servidor de recuperación de anuncios debe ejecutarse en un entorno de ejecución confiable (TEE) y exponer una interfaz GRPC/proto. Las empresas de tecnología publicitaria deben configurar este servidor y proporcionar su URL como parte de la implementación de la pila de B&A. Hay una implementación de este servicio que se ejecuta en el TEE disponible en GitHub de Privacy Sandbox y en el resto de la documentación, suponemos que este es el código que se usa en la implementación.

A partir de abril de 2024, las versiones de B&A admiten la recuperación de anuncios de ruta contextual. En este caso, el servidor de ofertas recibirá una lista de identificadores de anuncios enviados por el servidor de RTB durante la parte contextual de la subasta. Los identificadores se enviarán a un servidor de KV de TEE para recuperar toda la información relacionada con el anuncio que se usará durante la fase de oferta (por ejemplo, la URL de renderización de anuncios, los metadatos y las incorporaciones de anuncios que se usarán en la selección de k superior). Esta segunda ruta no necesita que se implemente ninguna lógica específica, por lo que solo documentaremos cómo configurar el caso de uso de recuperación de anuncios basado en TEE.

UDF de HandleRequest
function HandleRequest(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals) {
    return adsMetadataString;
}

Aquí:

  • requestMetadata: JSON. Metadatos del servidor por solicitud a la UDF. El valor está vacío por ahora.
  • preparedDataForAdRetrieval: El contenido de este campo depende de la estrategia de recuperación de anuncios. En el caso de la recuperación de anuncios contextuales, este parámetro contendrá los indicadores sin procesar que se originan en el dispositivo y se pasan desde el servicio de ofertas. En el caso de la recuperación de anuncios de TEE con el servidor de recuperación de anuncios, este parámetro contendrá el resultado de la UDF prepareDataForAdRetrieval. Nota: En esta etapa, los indicadores de apps protegidas se decodifican y no se encriptan.
  • deviceMetadata: Es un objeto JSON que contiene los metadatos del dispositivo que reenvía el servicio de anuncios del vendedor. Consulta la documentación de B&A para obtener más detalles.
    • X-Accept-Language: Es el idioma que se usa en el dispositivo.
    • X-User-Agent: Es el usuario-agente que se usa en el dispositivo.
    • X-BnA-Client-IP: Dirección IP del dispositivo.
  • contextualSignals: Es la cadena arbitraria que se origina desde el servidor de ofertas contextuales que opera la misma DSP. Se espera que la UDF pueda decodificar la cadena y usarla. Los indicadores contextuales pueden contener cualquier información, como los datos de la versión del modelo de AA para la incorporación protegida que se pasó con los indicadores de apps protegidas.

La UDF debería mostrar una cadena en caso de éxito. La string se muestra al servidor de ofertas, que luego la pasa a la UDF generateBid. Aunque la string puede ser solo una string simple, lo más probable es que la string sea un objeto serializado cuyo esquema está definido por cada plataforma de tecnología publicitaria por su cuenta. No hay ninguna restricción en el esquema, siempre que la lógica de generateBid de la plataforma de tecnología publicitaria pueda reconocer y usar la cadena.

Configura tu sistema para el desarrollo

Android

Para configurar tu entorno de desarrollo de Android, debes hacer lo siguiente:

  1. Crea un emulador (preferido) o un dispositivo físico que ejecute la imagen de la versión preliminar para desarrolladores 10.
  2. Ejecuta lo siguiente:
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity

Luego, selecciona la opción que se muestra para dar consentimiento a los anuncios sugeridos por apps.

  1. Ejecuta el siguiente comando para habilitar las APIs relevantes. En ocasiones, es posible que debas volver a ejecutarlo, ya que la configuración predeterminada para la opción de inhabilitar se sincronizará de forma periódica.
adb shell device_config put adservices fledge_custom_audience_service_kill_switch false;  adb shell device_config put adservices fledge_select_ads_kill_switch false; adb shell device_config put adservices fledge_on_device_auction_kill_switch false; adb shell device_config put adservices fledge_auction_server_kill_switch false; adb shell "device_config put adservices disable_fledge_enrollment_check true";  adb shell device_config put adservices ppapi_app_allow_list '\*'; adb shell device_config put adservices fledge_auction_server_overall_timeout_ms 60000;
  1. Reinicia el dispositivo.
  2. Anula las claves de subasta del dispositivo para que apunten a tu servidor de claves de subasta. Es importante realizar este paso antes de intentar ejecutar una subasta para evitar que se almacenen en caché claves incorrectas.

Servicios de ofertas y subastas

Para configurar los servidores de B&A, consulta la documentación sobre la configuración del servicio automático.

Este documento se enfocará en cómo configurar los servidores específicos del comprador, ya que no se requieren cambios para los vendedores.

Requisitos previos

Antes de implementar una pila de servicios de B&A, la tecnología publicitaria del comprador debe hacer lo siguiente:

  • Asegúrate de que haya implementado su propio servicio de recuperación de anuncios de TEE (consulta la sección relevante).
  • Asegúrate de que la tecnología publicitaria tenga definidas y alojadas todas las UDF necesarias (prepareDataForAdRetrieval, generateBid, reportWin, HandleRequest).

También será útil comprender cómo funciona la subasta protegida con el público protegido con B&A, pero no es obligatorio.

Configuración de Terraform

Para usar indicadores de apps protegidos, las tecnologías publicitarias deben hacer lo siguiente:

  • Habilitar la compatibilidad con los indicadores de apps protegidos en B&A.
  • Proporcionar extremos de URLs desde los que se puedan recuperar las UDF nuevas para prepareDataForAdRetrieval, generateBid y reportWin.

Además, en esta guía, se supone que las tecnologías publicitarias que desean usar B&A para el remarketing seguirán estableciendo todas las marcas de configuración existentes para la subasta de remarketing como de costumbre.

Configuración de la tecnología publicitaria del comprador

Con este archivo de demostración como ejemplo, los compradores deben establecer las siguientes marcas:

  • Habilitar los indicadores de apps protegidos: Se habilita para recopilar los datos de indicadores de apps protegidos.
  • URLs de los indicadores de apps protegidos: Configúralas en las URLs de los servidores de los indicadores de apps protegidos.

Las tecnologías publicitarias deben sustituir las URLs correctas en los marcadores de posición por los siguientes campos:

module "buyer" {
  # ... More config here.

  runtime_flags = {
    # ... More config here.

    ENABLE_PROTECTED_APP_SIGNALS                  = "true"
    PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS = "60000"
    TEE_AD_RETRIEVAL_KV_SERVER_ADDR               = "<service mesh address of the instance>"
    AD_RETRIEVAL_TIMEOUT_MS                       = "60000"
    BUYER_CODE_FETCH_CONFIG                       = <<EOF
    {
        "protectedAppSignalsBiddingJsUrl": "<URL to Protected App Signals generateBid UDF>",
        "urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
        "urlFetchPeriodMs": 13000000,
        "prepareDataForAdsRetrievalJsUrl": "<URL to the UDF>"
    }
    EOF

  }  # runtime_flags

}  # Module "buyer"

Configuración de la tecnología publicitaria del vendedor

Con este archivo de demostración como ejemplo, los vendedores deben configurar las siguientes marcas. (Nota: Aquí solo se menciona la configuración relacionada con los indicadores de apps protegidos). Las tecnologías publicitarias deben asegurarse de reemplazar las URLs correctas en los marcadores de posición:

module "seller" {
  # ... More config here.

  runtime_flags = {
    # ... More config here.

    ENABLE_PROTECTED_APP_SIGNALS                  = "true"

    SELLER_CODE_FETCH_CONFIG                           = <<EOF
  {
    "urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
    "urlFetchPeriodMs": 13000000,
    "protectedAppSignalsBuyerReportWinJsUrls": {"<Buyer Domain>": "URL to reportWin UDF"}
  }
  EOF

  }  # runtime_flags

}  # Module "seller"

KV y servicios de recuperación de anuncios

Según las estrategias elegidas para admitir la recuperación de anuncios, el sistema requerirá la implementación de una o dos instancias del servicio de KV. Nos referiremos a la instancia de KV que se usa para la recuperación de anuncios basada en TEE como Ad Retrieval Server y a la instancia para admitir la recuperación basada en rutas de acceso contextual como KV Lookup Server.

En ambos casos, la implementación de servidores sigue la documentación disponible en el GitHub del servidor de KV. La diferencia entre los dos casos es que el caso de búsqueda funciona de inmediato y sin ninguna configuración adicional, mientras que el de recuperación requiere la implementación de la UDF HandleRequest para implementar la lógica de recuperación. Si deseas obtener más detalles, consulta la guía de integración del servidor de KV. Ten en cuenta que B&A espera que ambos servicios se implementen en la misma malla de servicios que el servicio de ofertas.

Configuración de ejemplo

Ten en cuenta la siguiente situación: con la API de Protected App Signals, una tecnología publicitaria almacena indicadores relevantes en función del uso de la app por parte del usuario. En nuestro ejemplo, se almacenan indicadores que representan compras directas desde la aplicación de varias apps. Durante una subasta, los indicadores encriptados se recopilan y pasan a una subasta protegida que se ejecuta en B&A. Las UDF del comprador que se ejecutan en B&A usan los indicadores para recuperar anuncios candidatos y calcular una oferta.

Ejemplos de indicadores [comprador]

Agrega un indicador con una clave de 0 y un valor de 1.

{
  "put": {
    "AA==": "AQ=="
  },
  "update_encoder": {
    "action": "REGISTER",
    "endpoint": "https://example.com/example_script"
  }
}

Agrega un indicador con una clave de 1 y un valor de 2.

{
  "put": {
    "AQ==": "Ag=="
  },
  "update_encoder": {
    "action": "REGISTER",
    "endpoint": "https://example.com/example_script"
  }
}

Ejemplo de encodeSignals [comprador]

Codifica cada indicador en dos bytes. El primero es el primero de la clave del indicador, y el segundo es el primer byte del valor del indicador.

function encodeSignals(signals, maxSize) {
  // if there are no signals don't write a payload
  if (signals.size === 0) {
      return {};
  }

  let result = new Uint8Array(signals.size * 2);
  let index = 0;
  
  for (const [key, values] of signals.entries()) {
    result[index++] = key[0];
    result[index++] = values[0].signal_value[0];
  }
  
  return { 'status': 0, 'results': result};
}

Ejemplo de prepareDataForAdRetrieval [comprador]

/**
 * `encodedOnDeviceSignals` is a Uint8Array and would contain
 * the app signals emanating from device. For purpose of the
 * demo, in our sample example, we assume that device is sending
 * the signals with pair of bytes formatted as following:
 * "<id><In app spending>". Where id corresponds to an ad category
 * that user uses on device, and the in app spending is a measure
 * of how much money the user has spent in this app category
 * previously. In our example, id of 0 will correspond to a
 * fitness ad category and a non-zero id will correspond to
 * food app category -- though this info will be useful
 * later in the B&A pipeline.
 *
 * Returns a JSON object indicating what type of ad(s) may be
 * most relevant to the user. In a real setup ad techs might
 * want to decode the signals as part of this script.
 *
 * Note: This example script makes use of only encoded device signals
 * but adtech can take other signals into account as well to prepare
 * the data that will be useful down stream for ad retrieval and
 * bid generation. The max length of the app signals used in this
 * sample example is arbitrarily limited to 4 bytes.
 */
function prepareDataForAdRetrieval(encodedOnDeviceSignals,
                                   encodedOnDeviceSignalsVersion,
                                   sellerAuctionSignals,
                                   contextualSignals) {
  if (encodedOnDeviceSignals.length === 0 || encodedOnDeviceSignals.length > 4 ||
      encodedOnDeviceSignals.length % 2 !== 0) {
     throw "Expected encoded signals length to be an even number in (0, 4]";
  }

  var preparedDataForAdRetrieval = {};
  for (var i = 0; i < encodedOnDeviceSignals.length; i += 2) {
    preparedDataForAdRetrieval[encodedOnDeviceSignals[i]] = encodedOnDeviceSignals[i + 1];
  }
  return preparedDataForAdRetrieval;
}

[Compradores] UDF de recuperación de anuncios de muestra

En nuestro ejemplo, el servidor de recuperación de anuncios envía metadatos (es decir, el ID de cada anuncio en este ejemplo, pero puede contener otros datos de cada uno que pueden ser útiles para generar ofertas más adelante) para cada uno de los anuncios candidatos Top-K.

function HandleRequest(requestMetadata, protectedSignals, deviceMetadata,
                      contextualSignals) {
 return "[{\"adId\":\"0\"},{\"adId\":\"1\"}]"

Ejemplo de generateBid [comprador]

/**
 * This script receives the data returned by the ad retrieval service
 * in the `ads` argument. This argument is supposed to contain all
 * the Protected App Signals related ads and the metadata obtained from the retrieval
 * service.
 *
 * `preparedDataForAdRetrieval` argument contains the data returned
 * from the `prepareDataForAdRetrieval` UDF.
 *
 * This script is responsible for generating bids for the ads
 * collected from the retrieval service and ad techs can decide to
 * run a small inference model as part of this script in order to
 * decide the best bid given all the signals available to them.
 *
 * For the purpose of the demo, this sample script assumes
 * that ad retrieval service has sent us most relevant ads for the
 * user and this scripts decides on the ad render URL as well as
 * what value to bid for each ad based on the previously decoded
 * device signals. For simplicity sake, this script only considers
 * 2 types of app categories i.e. fitness and food.
 *
 * Note: Only one bid is returned among all the
 * input ad candidates.
 */
function generateBid(ads, sellerAuctionSignals, buyerSignals, preparedDataForAdRetrieval) {
  if (ads === null) {
    console.log("No ads obtained from the ad retrieval service")
    return {};
  }     
        
  const kFitnessAd = "0";
  const kFoodAd = "1";
  const kBuyerDomain = "https://buyer-domain.com";
        
  let resultingBid = 0;
  let resultingRender = kBuyerDomain + "/no-ad";
  for (let i = 0 ; i < ads.length; ++i) {
    let render = "";
    let bid = 0;
    switch (ads[i].adId) {
      case kFitnessAd:
        render = kBuyerDomain + "/get-fitness-app";
        bid = preparedDataForAdRetrieval[kFitnessAd];
        break;
      case kFoodAd:
        render = kBuyerDomain + "/get-fastfood-app";
        bid = preparedDataForAdRetrieval[kFoodAd];
        break;
      default:
        console.log("Unknown ad category");
        render = kBuyerDomain + "/no-ad";
        break;
    }
    console.log("Existing bid: " + resultingBid + ", incoming candidate bid: " + bid);
    if (bid > resultingBid) {
      resultingBid = bid;
      resultingRender = render;
    }
  }
  return {"render": resultingRender, "bid": resultingBid};
}

Ejemplo de reportWin [comprador]

La UDF reportWin le informa al comprador que ganó la subasta.

function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                                       buyerReportingSignals, directFromSellerSignals,
                                       egressPayload,
                                       temporaryUnlimitedEgressPayload) {
  sendReportTo("https://buyer-controlled-domain.com/");
  registerAdBeacon({"clickEvent":"https://buyer-controlled-domain.com/clickEvent"});
  return;
}

Configuración del servidor KV [vendedor]

Los vendedores deben configurar un servidor KV de indicadores de puntuación, de modo que haya una asignación disponible desde las URLs de renderización de anuncios para los indicadores de puntuación correspondientes, por ejemplo: si https:/buyer-domain.com/get-fitness-app y https:/buyer-domain.com/get-fastfood-app se devolvieran al comprador, el vendedor podría mostrar el siguiente ejemplo de respuesta de indicadores de puntuación cuando es consultado por SFE con un elemento GET en https://key-value-server-endpoint.com?client_type=1&renderUrls=<render-url-returned-by-the-buyer>:

{
   "renderUrls" : {
      "https:/buyer-domain.com/get-fitness-app" : [
         "1",
         "2"
      ],
      "https:/buyer-domain.com/get-fastfood-app" : [
         "3",
         "4"
      ]
   }
}

Ejemplo de scoreAd [vendedor]

/**
 * This module generates a random desirability score for the Protected App
 * Signals ad in this example. In a production deployment,
 * however, the sellers would want to use all the available signals to generate
 * a score for the ad.
 */
function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

function scoreAd(adMetadata, bid, auctionConfig,
                                   trustedScoringSignals, deviceSignals,
                                   directFromSellerSignals) {
  return {
    "desirability": getRandomInt(10000),
    "allowComponentAuction": false
  };
}

Ejemplo de reportResult [vendedor]

function reportResult(auctionConfig, sellerReportingSignals, directFromSellerSignals){
  let signalsForWinner = {};
    sendReportTo("https://seller-controlled-domain.com");
    registerAdBeacon({"clickEvent":
                    "https://seller-controlled-domain.com/clickEvent"});
    return signalsForWinner;
}

App de ejemplo

Como ejemplo de cómo se puede usar la API para crear una app que utilice un flujo simple como el descrito anteriormente, creamos una app de ejemplo de los indicadores de apps protegidos que se puede encontrar en este repositorio de ejemplo.