Руководство разработчика сигналов защищенных приложений

ad techproject_path: /_project.yaml book_path: /_book.yaml ключевые слова: api:ProtectedAppSignals, docType:Guide, skill:Beginner, auditorAdBuyer, auditorAdSeller, topicAdAuction, contentTypeFundamental, category:Mobile, apiGroupAds

Чтобы помочь разработчикам начать экспериментировать с API защищенных сигналов приложений, в этом документе описываются все API в пределах поверхности API, подробно описывается, как настроить тестовую среду, а также приводятся примеры конфигурации и скриптов.

История версий

Янв 2024

Первый выпуск руководства разработчика, поддерживающего выпуск PAS MVP

Март 2024 г.

Изменения в API для поддержки выпуска M-2024-05 API Android и выпуска серверных компонентов в апреле 2024 года. Наиболее заметные изменения:

  • Добавлены сведения о разрешениях, необходимых для API на устройстве.
  • Добавлены сведения об управлении квотами сигналов на устройстве.
  • Обновленная подпись generateBid с изменениями, связанными с поиском контекстной рекламы и поддержкой выхода
  • Обновленная документация reportWin , включая поддержку выхода
  • Обновление документации API поиска рекламы путем удаления поддержки поиска рекламы BYOS и документирования UDF поиска рекламы

Обзор API

Поверхность API защищенных сигналов включает в себя различные подмножества API в разных системах:

  • API Android:
    • API обработки сигналов, состоящий из:
    • API сигналов обновления
    • API кодирования сигналов
    • API поддержки защищенного аукциона: используется SDK для запуска защищенного аукциона на серверах торгов и аукционов (B&A) с использованием защищенных сигналов приложений.
  • API на стороне сервера:
    • Защищенный API аукциона: Серия скриптов JS, работающих на серверах торгов и аукционов. Этот API позволяет продавцам и покупателям писать логику для реализации защищенного аукциона.
    • API поиска рекламы: отвечает за предоставление списка подходящих объявлений с учетом контекстной и пользовательской информации, предоставленной серверу торгов покупателя.

Android-клиент

На стороне клиента поверхность защищенных сигналов приложений состоит из трех различных API:

  • Обновление сигналов: API-интерфейс системы Android, позволяющий отслеживать сигналы на устройстве.
  • Кодирование сигналов: API JavaScript для подготовки сигналов для отправки на сервер во время аукциона.
  • Поддержка защищенного аукциона: API для поддержки выполнения защищенного аукциона на серверах торгов и аукционов. Этот API не является специфичным для защищенных сигналов приложений и также используется для поддержки аукционов для API защищенной аудитории.

API сигналов обновления

API сигналов обновления предоставляет рекламным техникам возможность регистрировать сигналы, связанные с пользователем и приложением, от имени покупателя. API работает по модели делегирования. Вызывающая сторона предоставляет URI, из которого фреймворк извлекает соответствующие сигналы и логику для кодирования этих сигналов для использования в аукционе.

Для API требуется разрешение android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS .

API updateSignals() извлекает объект JSON из URI, который описывает, какие сигналы следует добавить или удалить, а также как подготовить эти сигналы к аукциону.

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);

Платформа делает https-запрос на URI, указанный в запросе, чтобы получить обновления сигнала. Вместе с обновлениями сигнала ответ может включать конечную точку, которая размещает логику кодирования для преобразования необработанных сигналов в закодированную полезную нагрузку. Ожидается, что обновления сигнала будут в формате JSON и могут иметь следующие ключи:

Ключи верхнего уровня для объекта JSON должны соответствовать одной из пяти команд:

ключ

Описание

put

Добавляет новый сигнал, перезаписывая любые существующие сигналы с тем же ключом. Значение

поскольку это объект JSON, где ключи представляют собой строки в кодировке base 64, соответствующие ключу, который необходимо ввести, а значения представляют собой строки в кодировке base 64, соответствующие значению, которое необходимо ввести.

append

Добавляет новый сигнал/сигналы к временной серии сигналов, удаляя самые старые

сигналы, чтобы освободить место для новых, если размер серии превышает заданный максимум. Значение для этого - это объект JSON, в котором ключи являются базовыми 64 строками, соответствующими клавишу для добавления, и значения являются объектами с двумя полями: «значения» и «maxSignals».

«values»: список строк в кодировке base 64, соответствующих значениям сигнала для добавления к временному ряду.

"maxSignals": Максимальное количество значений, разрешенных в этом временном ряду. Если

текущее количество сигналов, связанных с ключом, превышает maxSignals самые старые сигналы будут удалены. Обратите внимание, что вы можете добавить к ключу, добавленному с помощью put. Обратите внимание, что добавление большего количества значений, чем максимальное, приведет к сбою.

put_if_not_present

Добавляет новый сигнал только в том случае, если нет существующих сигналов с тем же ключом. Значение для этого — объект JSON, где ключи — это строки в кодировке base 64, соответствующие ключу для размещения, а значения — это строки в кодировке base 64, соответствующие значению для размещения.

remove

Удаляет сигнал для ключа. Значение этого — список строк base 64, соответствующих ключам сигналов, которые следует удалить.

update_encoder

Предоставляет действие для обновления конечной точки и URI, который можно использовать

для извлечения логики кодирования. Подключ для предоставления действия обновления — «действие», а

Поддерживаемые значения — только «REGISTER», который зарегистрирует конечную точку кодировщика, если она предоставлена ​​впервые, или перезапишет существующую с помощью новой предоставленной конечной точки. Предоставление конечной точки требуется для действия «REGISTER». Подключ для предоставления конечной точки кодировщика — «endpoint», а значение — URI

строка для конечной точки.

Пример запроса JSON будет выглядеть следующим образом:

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

Сигналы будут иметь квоту на устройстве порядка 10-15 Кб. После превышения квоты PPAPI вытеснит сигналы, используя стратегию FIFO. Процесс вытеснения позволит немного превышать квоту на короткие промежутки времени, чтобы снизить частоту вытеснений.

API кодирования сигналов

Покупатели должны предоставить функцию Java Script, которая будет использоваться для кодирования сигналов, хранящихся на устройстве, для отправки на сервер во время защищенного аукциона. Покупатели могут предоставить этот скрипт, добавив URL, по которому его можно получить, используя ключ "update_encoder" в любом из ответов на запрос API UpdateSignal. Скрипт будет иметь следующую сигнатуру:

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)};
}

Параметр signals — это карта ключей в виде массивов UInt8Arrays размером 4 в списки объектов Protected App Signals. Каждый объект Protected App Signals имеет три поля:

  • signal_value : массив UInt8Array, представляющий значение сигнала.
  • creation_time : число, представляющее время создания сигналов в секундах эпохи.
  • package_name : строка, представляющая имя пакета, создавшего сигнал.

Параметр maxSize — это число, описывающее максимально допустимый размер массива для вывода.

Функция должна выводить объект с двумя полями:

  • status : Должен быть 0, если скрипт выполнен успешно.
  • results : Должен быть UInt8Array длиной меньше или равной maxSize. Этот массив будет отправлен на сервер во время аукционов и подготовлен скриптом prepareDataForAdRetrieval .

Кодирование предоставляет рекламным технологиям начальный этап проектирования функций, где они могут выполнять преобразования, такие как сжатие необработанных сигналов в конкатенированные версии на основе собственной пользовательской логики. Обратите внимание, что во время защищенного аукциона, запущенного в доверенных средах выполнения (TEE), пользовательская логика рекламных технологий будет иметь доступ на чтение к полезным нагрузкам сигналов, сгенерированным кодированием. Пользовательская логика, известная как определяемая пользователем функция (UDF) , запущенная в B&A TEE покупателя, будет иметь доступ на чтение к закодированным сигналам и другим контекстным сигналам, предоставленным приложением издателя для выполнения выбора рекламы (извлечение рекламы и торги).

Кодирование сигналов

Каждый час покупатели, которые предоставили логику кодирования с зарегистрированными сигналами, будут кодировать свои сигналы в полезную нагрузку аукциона. Массив байтов для полезной нагрузки аукциона сохраняется на устройстве, зашифрован и будет собираться продавцами как часть данных выбора рекламы для включения в защищенный аукцион. Для тестирования вы можете запустить это кодирование вне его почасового ритма, выполнив следующую команду:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
Версионность логики кодировщика

Когда делается запрос на загрузку пользовательской логики кодировщика рекламных технологий, конечная точка рекламных технологий может ответить номером версии в заголовках ответа. Эта версия сохраняется вместе с логикой кодировщика на устройстве. Когда необработанные сигналы кодируются, закодированная полезная нагрузка сохраняется вместе с версией, используемой для кодирования. Эта версия также отправляется на сервер B&A во время защищенного аукциона, чтобы рекламные технологии могли согласовать свою логику торгов и кодирования на основе версии.

Response header for providing encoder version : X_ENCODER_VERSION

API поддержки защищенного аукциона

На стороне устройства проведение аукциона для защищенных сигналов приложений аналогично проведению аукциона для защищенных аудиторий .

Услуги по проведению торгов и аукционов

API-интерфейсы на стороне сервера включают в себя:

  • Защищенный API аукциона: ряд функций JS или UDF, которые покупатели и продавцы могут развертывать на принадлежащих им компонентах B&A для определения логики торгов и аукциона.
  • API поиска рекламы: покупатели могут реализовать этот API, внедрив конечную точку REST, которая будет отвечать за предоставление набора потенциальных объявлений для аукциона Protected App Signal.

Защищенный API аукциона

API защищенного аукциона состоит из JS API или UDF-функций, которые покупатели и продавцы могут использовать для реализации своей логики аукционов и торгов.

Пользовательские функции рекламных технологий покупателя
подготовитьDataForAdRetrieval UDF

Прежде чем использовать защищенные сигналы приложений для извлечения кандидатов на рекламу из службы поиска рекламы TEE, покупатели должны декодировать и подготовить защищенные сигналы приложений и другие данные, предоставленные продавцом. Покупатели prepareDataForAdRetrieval данные для AdRetrieval. Выходные данные UDF передаются в службу поиска рекламы для извлечения k лучших кандидатов на торги .

// 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 ad tech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
   return {};
}
ГенерироватьБид UDF

После возврата первых k объявлений-кандидатов они передаются в пользовательскую логику торгов покупателя, generateBid UDF :

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

Выход этой функции — это одна ставка для кандидата на объявление, представленная в виде эквивалента JSON ProtectedAppSignalsAdWithBidMetadata . Функция также может возвращать два массива, которые затем будут переданы в reportWin для включения обучения модели (более подробную информацию о выходе и обучении модели см. в разделе отчетов в объяснении PAS )

reportWin UDF

Когда аукцион завершается, служба аукциона генерирует URL-адреса отчетов для покупателей и регистрирует маяки с помощью reportWin UDF (это та же функция reportWin , которая используется для защищенных аудиторий) . Это будет проверено устройством после того, как объявление будет отображено клиентом. Сигнатура этого метода почти такая же, как и в версии защищенной аудитории, за исключением двух дополнительных параметров egressPayload и temporaryUnlimitedEgressPayload , которые используются для включения обучения модели и заполняются результатами из generateBid .

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals,
                   egressPayload, temporaryUnlimitedEgressPayload) {
  // ...
}
UDF-файлы рекламных технологий продавца
оценкаAd UDF

Этот UDF используется продавцами для выбора того, какое из объявлений, полученных от покупателей, победит на аукционе.

function scoreAd(adMetadata, bid, auctionConfig,
                 trustedScoringSignals, bid_metadata) {
  // ...
  return {desirability: desirabilityScoreForThisAd,
              allowComponentAuction: true_or_false};
}
отчетРезультат UDF

Эта UDF позволяет продавцу (в конечном итоге) создавать отчеты на уровне событий с информацией о победившем объявлении.

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

API поиска рекламы

В выпуске MVP служба поиска рекламы будет управляться покупателем и размещаться, а служба торгов будет извлекать кандидатов на рекламу из этой службы. Начиная с апреля 2024 года сервер поиска рекламы должен работать в среде доверенного выполнения (TEE) и будет предоставлять интерфейс GRPC/proto. Компании, занимающиеся рекламными технологиями, должны настроить этот сервер и предоставить его URL как часть развертывания стека B&A. Реализация этой службы, работающей в TEE, доступна в Privacy Sandbox GitHub , и в остальной части документации мы предполагаем, что это код, используемый при развертывании.

Начиная с апреля 2024 года версии B&A поддерживают контекстный путь поиска рекламы. В этом случае сервер торгов получит список идентификаторов рекламы, отправленных сервером RTB во время контекстной части аукциона. Идентификаторы будут отправлены на сервер TEE KV для извлечения всей информации, связанной с рекламой, которая будет использоваться на этапе торгов (например, ad-render-url, метаданные и встраивания рекламы для использования при выборе top-k). Этот второй путь не требует развертывания какой-либо конкретной логики, поэтому мы документируем здесь только то, как настроить вариант использования поиска рекламы на основе TEE.

getCandidateAds UDF
function getCandidateAds(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals, contextualAdIds,) {
    return adsMetadataString;
}

Где:

  • requestMetadata : JSON. Метаданные сервера по запросу в UDF. Пока пусто.
  • preparedDataForAdRetrieval : содержимое этого поля зависит от стратегии поиска рекламы. В случае поиска контекстной рекламы этот параметр будет содержать необработанные сигналы, исходящие от устройства и переданные из службы торгов. В случае поиска рекламы TEE с использованием сервера поиска рекламы этот параметр будет содержать результат функции prepareDataForAdRetrieval UDF. Примечание: на этом этапе защищенные сигналы приложения будут декодированы и не будут зашифрованы.
  • deviceMetadata : JSON-объект, содержащий метаданные устройства, переданные службой объявлений продавца. Подробности см. в документации B&A.
    • X-Accept-Language : язык, используемый на устройстве.
    • X-User-Agent : пользовательский агент, используемый на устройстве.
    • X-BnA-Client-IP : IP-адрес устройства.
  • contextualSignals : произвольная строка, полученная с сервера контекстных торгов, управляемого тем же DSP. Ожидается, что UDF сможет декодировать строку и использовать ее. Контекстные сигналы могут содержать любую информацию, например информацию о версии модели ML для защищенного внедрения, переданную с помощью защищенных сигналов приложения.
  • contextualAdIds : объект JSON, содержащий необязательный список идентификаторов объявлений.

UDF должна возвращать строку в случае успеха. Строка возвращается на сервер торгов, который затем передает ее в generateBid UDF. Хотя строка может быть просто базовой строкой, скорее всего, это должен быть сериализованный объект, схема которого определяется каждой рекламной технологией самостоятельно. На схему нет ограничений, пока логика generateBid рекламной технологии может распознавать и использовать строку.

Настройте свою систему для разработки

андроид

Чтобы настроить среду разработки Android, вам необходимо сделать следующее:

  1. Создайте эмулятор (предпочтительно) или физическое устройство, на котором запущен образ Developer Preview 10.
  2. Выполните следующее:
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity

Затем выберите показанный вариант, чтобы дать согласие на предлагаемую приложением рекламу.

  1. Запустите следующую команду, чтобы включить соответствующие API. Возможно, вам придется время от времени запускать ее повторно, так как конфигурация по умолчанию для отключенных функций будет периодически синхронизироваться.
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. Перезагрузите устройство.
  2. Переопределите аукционные ключи устройства, чтобы они указывали на ваш сервер аукционных ключей. Важно выполнить этот шаг перед попыткой запустить аукцион, чтобы предотвратить кэширование неправильных ключей.

Услуги по проведению торгов и аукционов

Чтобы настроить серверы B&A, обратитесь к документации по самостоятельной настройке .

В этом документе основное внимание будет уделено настройке серверов, предназначенных для покупателей, поскольку для продавцов никаких изменений не требуется.

Предпосылки

Перед развертыванием комплекса услуг B&A специалисту по работе с рекламодателями необходимо:

  • Убедитесь, что они развернули собственную службу поиска рекламы TEE (см. соответствующий раздел ).
  • Убедитесь, что в рекламной технологии определены и размещены все необходимые пользовательские функции ( prepareDataForAdRetrieval , generateBid , reportWin , getCandidateAds ).

Понимание того, как работает защищенный аукцион с защищенной аудиторией в B&A, также будет полезным, но не обязательным.

Конфигурация терраформа

Чтобы использовать защищенные сигналы приложений, специалисты по рекламе должны:

  • Включите поддержку защищенных сигналов приложений в B&A.
  • Укажите конечные точки URL, из которых можно извлечь новые пользовательские функции для prepareDataForAdRetrieval, generateBid и reportWin .

Кроме того, в этом руководстве предполагается, что специалисты по рекламе, желающие использовать B&A для ремаркетинга, продолжат устанавливать все существующие флаги конфигурации для аукциона ремаркетинга, как обычно.

Конфигурация технологии рекламы покупателя

Используя этот демонстрационный файл в качестве примера, покупателям необходимо установить следующие флаги:

  • Включить сигналы защищенных приложений : включено для сбора данных сигналов защищенных приложений.
  • URL-адреса защищенных сигналов приложений : укажите URL-адреса серверов защищенных сигналов приложений.

Специалисты по рекламе должны заменить правильные URL-адреса в заполнителях для следующих полей:

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"

Конфигурация технологии рекламы продавца

Используя этот демонстрационный файл в качестве примера, продавцы должны установить следующие флаги. (Примечание: здесь выделена только конфигурация, связанная с защищенными сигналами приложений). Специалистам по рекламе необходимо убедиться, что они подставляют правильные URL-адреса в заполнители:

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 и рекламы

В зависимости от выбранных стратегий поддержки поиска рекламы, система потребует развертывания одного или двух экземпляров службы KV. Мы будем называть экземпляр KV, используемый для поиска рекламы на основе TEE, Ad Retrieval Server , а экземпляр для поддержки поиска на основе контекстного пути — KV Lookup Server .

В обоих случаях развертывание серверов следует документации, доступной на сервере KV GitHub , разница между двумя случаями заключается в том, что случай поиска работает из коробки без какой-либо дополнительной настройки, в то время как случай извлечения требует развертывания getCandidateAds UDF для реализации логики извлечения. Для получения более подробной информации см. руководство по подключению сервера KV . Обратите внимание, что B&A ожидает, что обе службы будут развернуты в той же сервисной сетке, что и служба торгов.

Пример настройки

Рассмотрим следующий сценарий: используя API защищенных сигналов приложений, рекламная технология сохраняет соответствующие сигналы на основе использования приложения пользователем. В нашем примере хранятся сигналы, представляющие покупки в приложении из нескольких приложений. Во время аукциона зашифрованные сигналы собираются и передаются в защищенный аукцион, работающий в B&A. UDF покупателя, работающие в B&A, используют сигналы для получения кандидатов на рекламу и вычисления ставки.

[Покупатель] Примеры сигналов

Добавляет сигнал с ключом 0 и значением 1.

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

Добавляет сигнал с ключом 1 и значением 2.

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

[Покупатель] пример encodeSignals

Кодирует каждый сигнал в два байта, причем первый байт является первым байтом ключа сигнала, а второй байт является первым байтом значения сигнала.

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};
}

[Покупатель] пример prepareDataForAdRetrieval

/**
 * `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, an 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 ad tech 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;
}

[Покупатели] Пример поиска рекламы UDF

В нашем примере сервер поиска объявлений отправляет метаданные (т. е. идентификатор каждого объявления в этом примере, но может содержать и другие данные для каждого объявления, которые могут быть полезны при формировании ставок в дальнейшем) для каждого из k лучших кандидатов на размещение объявлений.

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

[Покупатели] пример generateBid

/**
 * 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};
}

[Покупатели] reportWin пример

reportWin UDF сообщает покупателю, что он выиграл аукцион.

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

[Продавец] Настройка сервера KV

Продавцы должны настроить сервер KV сигналов оценки, чтобы было доступно сопоставление URL-адресов отображения рекламы с соответствующими сигналами оценки, например: если https:/buyer-domain.com/get-fitness-app и https:/buyer-domain.com/get-fastfood-app должны быть возвращены покупателем, продавец может получить следующий пример ответа сигналов оценки при запросе SFE с использованием GET на 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"
      ]
   }
}

[Продавец] оценкаПример рекламы

/**
 * 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
  };
}

[Продавец] reportResult пример

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

Пример приложения

В качестве примера того, как API может использоваться для создания приложения, использующего этот поток, мы создали пример приложения Protected App Signals, который можно найти в этом репозитории примеров .

,

ad techproject_path: /_project.yaml book_path: /_book.yaml ключевые слова: api:ProtectedAppSignals, docType:Guide, skill:Beginner, auditorAdBuyer, auditorAdSeller, topicAdAuction, contentTypeFundamental, category:Mobile, apiGroupAds

Чтобы помочь разработчикам начать экспериментировать с API защищенных сигналов приложений, в этом документе описываются все API в пределах поверхности API, подробно описывается, как настроить тестовую среду, а также приводятся примеры конфигурации и скриптов.

История версий

Янв 2024

Первый выпуск руководства разработчика, поддерживающего выпуск PAS MVP

Март 2024 г.

Изменения в API для поддержки выпуска M-2024-05 API Android и выпуска серверных компонентов в апреле 2024 года. Наиболее заметные изменения:

  • Добавлены сведения о разрешениях, необходимых для API на устройстве.
  • Добавлены сведения об управлении квотами сигналов на устройстве.
  • Обновленная подпись generateBid с изменениями, связанными с поиском контекстной рекламы и поддержкой выхода
  • Обновленная документация reportWin , включая поддержку выхода
  • Обновление документации API поиска рекламы путем удаления поддержки поиска рекламы BYOS и документирования UDF поиска рекламы

Обзор API

Поверхность API защищенных сигналов включает в себя различные подмножества API в разных системах:

  • API Android:
    • API обработки сигналов, состоящий из:
    • API сигналов обновления
    • API кодирования сигналов
    • API поддержки защищенного аукциона: используется SDK для запуска защищенного аукциона на серверах торгов и аукционов (B&A) с использованием защищенных сигналов приложений.
  • API на стороне сервера:
    • Защищенный API аукциона: Серия скриптов JS, работающих на серверах торгов и аукционов. Этот API позволяет продавцам и покупателям писать логику для реализации защищенного аукциона.
    • API поиска рекламы: отвечает за предоставление списка подходящих объявлений с учетом контекстной и пользовательской информации, предоставленной серверу торгов покупателя.

Android-клиент

На стороне клиента поверхность защищенных сигналов приложений состоит из трех различных API:

  • Обновление сигналов: API-интерфейс системы Android, позволяющий отслеживать сигналы на устройстве.
  • Кодирование сигналов: API JavaScript для подготовки сигналов для отправки на сервер во время аукциона.
  • Поддержка защищенного аукциона: API для поддержки выполнения защищенного аукциона на серверах торгов и аукционов. Этот API не является специфичным для защищенных сигналов приложений и также используется для поддержки аукционов для API защищенной аудитории.

API сигналов обновления

API сигналов обновления предоставляет рекламным техникам возможность регистрировать сигналы, связанные с пользователем и приложением, от имени покупателя. API работает по модели делегирования. Вызывающая сторона предоставляет URI, из которого фреймворк извлекает соответствующие сигналы и логику для кодирования этих сигналов для использования в аукционе.

Для API требуется разрешение android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS .

API updateSignals() извлекает объект JSON из URI, который описывает, какие сигналы следует добавить или удалить, а также как подготовить эти сигналы к аукциону.

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);

Платформа делает https-запрос на URI, указанный в запросе, чтобы получить обновления сигнала. Вместе с обновлениями сигнала ответ может включать конечную точку, которая размещает логику кодирования для преобразования необработанных сигналов в закодированную полезную нагрузку. Ожидается, что обновления сигнала будут в формате JSON и могут иметь следующие ключи:

Ключи верхнего уровня для объекта JSON должны соответствовать одной из пяти команд:

ключ

Описание

put

Добавляет новый сигнал, перезаписывая любые существующие сигналы с тем же ключом. Значение

поскольку это объект JSON, где ключи представляют собой строки в кодировке base 64, соответствующие ключу, который необходимо ввести, а значения представляют собой строки в кодировке base 64, соответствующие значению, которое необходимо ввести.

append

Добавляет новый сигнал/сигналы во временные ряды сигналов, удаляя самые старые

сигналы, освобождающие место для новых, если размер серии превышает заданный максимум. Значение для этого — объект JSON, где ключи — это строки base 64, соответствующие ключу для добавления, а значения — это объекты с двумя полями: «values» и «maxSignals».

«values»: список строк в кодировке base 64, соответствующих значениям сигнала для добавления к временному ряду.

"maxSignals": Максимальное количество значений, разрешенных в этом временном ряду. Если

текущее количество сигналов, связанных с ключом, превышает maxSignals самые старые сигналы будут удалены. Обратите внимание, что вы можете добавить к ключу, добавленному с помощью put. Обратите внимание, что добавление большего количества значений, чем максимальное, приведет к сбою.

put_if_not_present

Добавляет новый сигнал только в том случае, если нет существующих сигналов с тем же ключом. Значение для этого — объект JSON, где ключи — это строки в кодировке base 64, соответствующие ключу для размещения, а значения — это строки в кодировке base 64, соответствующие значению для размещения.

remove

Удаляет сигнал для ключа. Значение этого — список строк base 64, соответствующих ключам сигналов, которые следует удалить.

update_encoder

Предоставляет действие для обновления конечной точки и URI, который можно использовать

для извлечения логики кодирования. Подключ для предоставления действия обновления — «действие», а

Поддерживаемые значения — только «REGISTER», который зарегистрирует конечную точку кодировщика, если она предоставлена ​​впервые, или перезапишет существующую с помощью новой предоставленной конечной точки. Предоставление конечной точки требуется для действия «REGISTER». Подключ для предоставления конечной точки кодировщика — «endpoint», а значение — URI

строка для конечной точки.

Пример запроса JSON будет выглядеть следующим образом:

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

Сигналы будут иметь квоту на устройстве порядка 10-15 Кб. После превышения квоты PPAPI вытеснит сигналы, используя стратегию FIFO. Процесс вытеснения позволит немного превышать квоту на короткие промежутки времени, чтобы снизить частоту вытеснений.

API кодирования сигналов

Покупатели должны предоставить функцию Java Script, которая будет использоваться для кодирования сигналов, хранящихся на устройстве, для отправки на сервер во время защищенного аукциона. Покупатели могут предоставить этот скрипт, добавив URL, по которому его можно получить, используя ключ "update_encoder" в любом из ответов на запрос API UpdateSignal. Скрипт будет иметь следующую сигнатуру:

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)};
}

Параметр signals — это карта ключей в виде массивов UInt8Arrays размером 4 в списки объектов Protected App Signals. Каждый объект Protected App Signals имеет три поля:

  • signal_value : массив UInt8Array, представляющий значение сигнала.
  • creation_time : число, представляющее время создания сигналов в секундах эпохи.
  • package_name : строка, представляющая имя пакета, создавшего сигнал.

Параметр maxSize — это число, описывающее максимально допустимый размер массива для вывода.

Функция должна выводить объект с двумя полями:

  • status : Должен быть 0, если скрипт выполнен успешно.
  • results : Должен быть UInt8Array длиной меньше или равной maxSize. Этот массив будет отправлен на сервер во время аукционов и подготовлен скриптом prepareDataForAdRetrieval .

Кодирование предоставляет рекламным технологиям начальный этап проектирования функций, где они могут выполнять преобразования, такие как сжатие необработанных сигналов в конкатенированные версии на основе собственной пользовательской логики. Обратите внимание, что во время защищенного аукциона, запущенного в доверенных средах выполнения (TEE), пользовательская логика рекламных технологий будет иметь доступ на чтение к полезным нагрузкам сигналов, сгенерированным кодированием. Пользовательская логика, известная как определяемая пользователем функция (UDF) , запущенная в B&A TEE покупателя, будет иметь доступ на чтение к закодированным сигналам и другим контекстным сигналам, предоставленным приложением издателя для выполнения выбора рекламы (извлечение рекламы и торги).

Кодирование сигналов

Каждый час покупатели, которые предоставили логику кодирования с зарегистрированными сигналами, будут кодировать свои сигналы в полезную нагрузку аукциона. Массив байтов для полезной нагрузки аукциона сохраняется на устройстве, зашифрован и будет собираться продавцами как часть данных выбора рекламы для включения в защищенный аукцион. Для тестирования вы можете запустить это кодирование вне его почасового ритма, выполнив следующую команду:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
Версионность логики кодировщика

Когда делается запрос на загрузку пользовательской логики кодировщика рекламных технологий, конечная точка рекламных технологий может ответить номером версии в заголовках ответа. Эта версия сохраняется вместе с логикой кодировщика на устройстве. Когда необработанные сигналы кодируются, закодированная полезная нагрузка сохраняется вместе с версией, используемой для кодирования. Эта версия также отправляется на сервер B&A во время защищенного аукциона, чтобы рекламные технологии могли согласовать свою логику торгов и кодирования на основе версии.

Response header for providing encoder version : X_ENCODER_VERSION

API поддержки защищенного аукциона

На стороне устройства проведение аукциона для защищенных сигналов приложений аналогично проведению аукциона для защищенных аудиторий .

Услуги по проведению торгов и аукционов

API-интерфейсы на стороне сервера включают в себя:

  • Защищенный API аукциона: ряд функций JS или UDF, которые покупатели и продавцы могут развертывать на принадлежащих им компонентах B&A для определения логики торгов и аукциона.
  • API поиска рекламы: покупатели могут реализовать этот API, внедрив конечную точку REST, которая будет отвечать за предоставление набора потенциальных объявлений для аукциона Protected App Signal.

Защищенный API аукциона

API защищенного аукциона состоит из JS API или UDF-функций, которые покупатели и продавцы могут использовать для реализации своей логики аукционов и торгов.

Пользовательские функции рекламных технологий покупателя
подготовитьDataForAdRetrieval UDF

Прежде чем использовать защищенные сигналы приложений для извлечения кандидатов на рекламу из службы поиска рекламы TEE, покупатели должны декодировать и подготовить защищенные сигналы приложений и другие данные, предоставленные продавцом. Покупатели prepareDataForAdRetrieval данные для AdRetrieval. Выходные данные UDF передаются в службу поиска рекламы для извлечения k лучших кандидатов на торги .

// 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 ad tech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
   return {};
}
ГенерироватьБид UDF

После возврата первых k объявлений-кандидатов они передаются в пользовательскую логику торгов покупателя, generateBid UDF :

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

Выход этой функции — это одна ставка для кандидата на объявление, представленная в виде эквивалента JSON ProtectedAppSignalsAdWithBidMetadata . Функция также может возвращать два массива, которые затем будут переданы в reportWin для включения обучения модели (более подробную информацию о выходе и обучении модели см. в разделе отчетов в объяснении PAS )

reportWin UDF

Когда аукцион завершается, служба аукциона генерирует URL-адреса отчетов для покупателей и регистрирует маяки с помощью reportWin UDF (это та же функция reportWin , которая используется для защищенных аудиторий) . Это будет проверено устройством после того, как объявление будет отображено клиентом. Сигнатура этого метода почти такая же, как и в версии защищенной аудитории, за исключением двух дополнительных параметров egressPayload и temporaryUnlimitedEgressPayload , которые используются для включения обучения модели и заполняются результатами из generateBid .

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals,
                   egressPayload, temporaryUnlimitedEgressPayload) {
  // ...
}
UDF-файлы рекламных технологий продавца
оценкаAd UDF

Этот UDF используется продавцами для выбора того, какое из объявлений, полученных от покупателей, победит на аукционе.

function scoreAd(adMetadata, bid, auctionConfig,
                 trustedScoringSignals, bid_metadata) {
  // ...
  return {desirability: desirabilityScoreForThisAd,
              allowComponentAuction: true_or_false};
}
отчетРезультат UDF

Эта UDF позволяет продавцу (в конечном итоге) создавать отчеты на уровне событий с информацией о победившем объявлении.

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

API поиска рекламы

В выпуске MVP служба поиска рекламы будет управляться покупателем и размещаться, а служба торгов будет извлекать кандидатов на рекламу из этой службы. Начиная с апреля 2024 года сервер поиска рекламы должен работать в среде доверенного выполнения (TEE) и будет предоставлять интерфейс GRPC/proto. Компании, занимающиеся рекламными технологиями, должны настроить этот сервер и предоставить его URL как часть развертывания стека B&A. Реализация этой службы, работающей в TEE, доступна в Privacy Sandbox GitHub , и в остальной части документации мы предполагаем, что это код, используемый при развертывании.

Начиная с апреля 2024 года, версии B & A поддерживают контекстуальный путь AD -поиска. In this case the Bidding server will receive a list of ad-identifiers sent by the RTB server during the contextual part of the auction. Идентификаторы будут отправлены на TEE KV-сервер, чтобы получить всю информацию, связанную с рекламой, которая будет использоваться на этапе ставок (например, AD-render-URL, метаданные и AD Enterdings, которые будут использоваться в выборе Top-K). Этот второй путь не нуждается в какой -либо конкретной логике, которая будет развернута, поэтому мы документируем здесь только то, как настроить вариант использования AD на основе TEE.

GetCandidateads UDF
function getCandidateAds(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals, contextualAdIds,) {
    return adsMetadataString;
}

Где:

  • requestMetadata : JSON. Метаданные сервера для Per-запроса в UDF. На данный момент пусто.
  • preparedDataForAdRetrieval : содержание этой области зависит от стратегии поиска AD. В случае контекстуального поиска AD этот параметр будет содержать необработанные сигналы, происходящие с устройства, и передается из службы торгов. В случае поиска AD с использованием сервера поиска AD, этот параметр будет содержать результат prepareDataForAdRetrieval UDF. Примечание. На этом этапе сигналы защищенного приложения будут декодированы и не затратны.
  • deviceMetadata : объект JSON, содержащий метаданные устройства, направленные рекламной службой продавца. Смотрите документацию B & A для получения более подробной информации.
    • X-Accept-Language : язык, используемый на устройстве.
    • X-User-Agent : пользовательский агент, используемый на устройстве.
    • X-BnA-Client-IP : IP-адрес устройства.
  • contextualSignals : произвольная строка, возникшая из контекстуального сервера торгов, работающих на одном DSP. Ожидается, что UDF сможет декодировать строку и использовать ее. Контекстуальные сигналы могут содержать любую информацию, такую как информация о модельной версии ML для защищенного встраивания, передаваемого при использовании защищенных сигналов приложения.
  • contextualAdIds : объект JSON, содержащий необязательный список идентификаторов AD.

UDF должен вернуть строку на успех. Строка возвращается на сервер торгов, который затем передает его generateBid UDF. Хотя строка может быть просто основной строкой, скорее всего, это должен быть сериализованный объект, схема которой самостоятельно определяется каждой технологией AD. На схеме нет ограничений, если бы generateBid логика AD Tech может распознавать и использовать строку.

Настройте вашу систему для разработки

андроид

Чтобы настроить среду разработки Android, вам нужно сделать следующее:

  1. Создайте эмулятор (предпочтительный) или физическое устройство, которое запускает изображение Developer Preview 10
  2. Запустите следующее:
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity

Затем выберите опцию, показанную для согласия на объявления о приложениях.

  1. Запустите следующую команду, чтобы включить соответствующие API. Вам может потребоваться повторное заполнение этого иногда, так как конфигурация отключений по умолчанию будет периодически синхронизироваться.
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. Перезагрузите устройство.
  2. Переопределите клавиши аукциона устройства, чтобы указать на ваш сервер клавиш аукциона. Важно запустить этот шаг, прежде чем попытаться провести аукцион, чтобы предотвратить кэширование неверных ключей.

Служба торгов и аукциона

Чтобы настроить серверы B & A, обратитесь к документации по настройке самообслуживания .

Этот документ будет сосредоточен на том, как настроить специфические серверы покупателя, так как для продавцов нет изменений.

Предпосылки

Прежде чем развернуть стек B & A Service, покупательская реклама должна:

  • Убедитесь, что они развернули свою собственную службу поиска AD TEE (см. Соответствующий раздел ).
  • Убедитесь, что AD Tech имеет все необходимые UDF ( prepareDataForAdRetrieval generateBid reportWin и getCandidateAds .

An understanding of how the Protected Auction with Protected Audience works with B&A will also be helpful but is not mandatory.

Конфигурация терраформ

Чтобы использовать защищенные сигналы приложения, рекламные технологии должны:

  • Включить поддержку защищенных приложений в B & A.
  • Предоставьте конечные точки URL, из которых могут быть извлечены новые UDF для prepareDataForAdRetrieval, generateBid и reportWin .

Кроме того, это руководство предполагает, что AD Techs, желающие использовать B & A для ремаркетинга, будут продолжать устанавливать все существующие флаги конфигурации для аукциона ремаркетинга, как обычно.

Покупатель рекламная технологическая конфигурация

Используя этот демо -файл в качестве примера, покупатели должны установить следующие флаги:

  • Включить защищенные сигналы приложения : включен для сбора данных защищенных приложений.
  • Защищенные приложения сигнализируют URL -адреса : установить на URL -адреса защищенных серверов сигналов.

AD Techs должны заменить правильные URL -адреса в заполнителе для следующих полей:

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"

Продавец AD Tech Configuration

Используя этот демонстрационный файл в качестве примера, продавцы должны установить следующие флаги. (Примечание: здесь выделен только защищенные сигналы приложения. AD Techs необходимо проверить, что они заменяют правильные URL -адреса в заполнители:

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 и рекламные услуги

В зависимости от стратегий, выбранных для поддержки поиска рекламы, система потребует развертывания одного или двух экземпляров службы KV. Мы будем ссылаться на экземпляр экземпляра KV, используемый для поиска AD на основе TEE в качестве Ad Retrieval Server и экземпляра для поддержки поиска на основе контекстуального пути в качестве KV Lookup Server .

В обоих случаях развертывание серверов следует за документацией, доступной на Github Server KV , разница между двумя случаями заключается в том, что случай поиска работает из коробки без какой -либо дополнительной конфигурации, в то время как для поиска требуется развертывание UDF getCandidateAds для реализации поисковой логики. Для получения более подробной информации взгляните на руководство по борьбе с сервером KV . Обратите внимание, что B & A ожидает, что обе услуги будут развернуты в одной и той же сервисной сетке, что и Service Service.

Пример настройки

Рассмотрим следующий сценарий: использование API API Signals Signals защищенных приложений, соответствующих сигналов AD, основанных на использовании пользовательского приложения. В нашем примере хранятся сигналы, которые представляют покупки в приложении из нескольких приложений. Во время аукциона зашифрованные сигналы собираются и передаются на защищенный аукцион, работающий в B & A. UDFS покупателя, работающие в B & A, используют сигналы, чтобы принести кандидатов на рекламу и вычислять ставку.

[Покупатель] сигнализирует примеры

Добавляет сигнал с ключом 0 и значением 1.

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

Добавляет сигнал с ключом 1 и значением 2.

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

[Покупатель] Пример кодировки

Кодирует каждый сигнал в два байта, причем первый байт является первым байтом ключа сигнала, а второй байт - первый байт значения сигнала.

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};
}

[Покупатель] Подготовленный пример

/**
 * `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, an 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 ad tech 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;
}

[Покупатели] Образец поиска рекламы UDF

В нашем примере сервер поиска рекламы отправляет метаданные (т.е. идентификатор для каждого объявления в этом примере, но может содержать другие данные для каждого, которые могут быть полезны для создания заявок позже) для каждого из лучших кандидатов на k AD.

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

[Покупатели] генерируют пример

/**
 * 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};
}

[Покупатели] Пример отчетов

reportWin UDF сообщает покупателю, что они выиграли аукцион.

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

[Продавец] Настройка сервера KV

Продавцы должны установить сигналы оценки KV-сервера, чтобы было доступно отображение от URL-адресов AD рендеринга с соответствующими сигналами оценки, например: если https:/buyer-domain.com/get-fitness-app и https:/buyer-domain.com/get-fastfood-app GET 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"
      ]
   }
}

[Продавец] Пример оказания большего

/**
 * 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
  };
}

[Продавец] Reportresult пример

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

Пример приложения

В качестве примера того, как API можно использовать для создания приложения, которое использует этот поток, мы создали образец защищенного приложения, который можно найти в этом репозитории этого образца .