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

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

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

январь 2024 г.

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

март 2024 г.

Изменения в API для поддержки версии Android API M-2024-05 и версии серверных компонентов от апреля 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, где ключи представляют собой строки в базе 64, соответствующие ключу, который нужно вставить, а значения представляют собой строку в базе 64, соответствующую вставляемому значению.

append

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

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

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

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

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

put_if_not_present

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

remove

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

update_encoder

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

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

В настоящее время поддерживаются только значения «РЕГИСТРАЦИЯ», при которых конечная точка кодировщика будет зарегистрирована, если она указана впервые, или перезапишет существующую с новой предоставленной конечной точкой. Для действия «РЕГИСТРАЦИЯ» требуется предоставление конечной точки. Подключом для предоставления конечной точки кодировщика является «конечная точка», а значением является 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 со списками объектов сигналов защищенного приложения. Каждый объект сигналов защищенного приложения имеет три поля:

  • 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-функций или пользовательских функций, которые покупатели и продавцы могут развертывать на принадлежащих им компонентах B&A, чтобы определять ставки и логику аукциона.
  • API поиска рекламы. Покупатели могут реализовать этот API, внедрив конечную точку REST, которая будет отвечать за предоставление набора объявлений-кандидатов для аукциона сигналов защищенных приложений.

API защищенного аукциона

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

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

Прежде чем сигналы защищенного приложения можно будет использовать для получения кандидатов на рекламу из службы поиска рекламы TEE, покупатели должны декодировать и подготовить сигналы защищенного приложения и другие данные, предоставленные продавцом. Выходные данные UDF Buyers prepareDataForAdRetrieval передаются в службу поиска объявлений для получения 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 adtech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
   return {};
}
генерируемая ставка Bid 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 ).

отчетWin UDF

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

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals,
                   egressPayload, temporaryUnlimitedEgressPayload) {
  // ...
}
Пользовательские функции для рекламных технологий продавца
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/прототип. Компании, занимающиеся рекламными технологиями, должны настроить этот сервер и предоставить его URL-адрес в рамках развертывания стека B&A. Реализация этой службы, работающей в TEE, доступна в Privacy Sandbox GitHub , а в остальной документации мы предполагаем, что это код, используемый при развертывании.

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

Пользовательская функция HandleRequest
function HandleRequest(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals) {
    return adsMetadataString;
}

Где:

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

UDF должен возвращать строку в случае успеха. Строка возвращается на сервер назначения ставок, который затем передает ее в пользовательскую функцию generateBid . Хотя строка может быть простой строкой, скорее всего, она должна представлять собой сериализованный объект, схема которого определяется каждой рекламной технологией самостоятельно. На схему нет никаких ограничений, если логика 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 , HandleRequest ).

Понимание того, как Защищенный аукцион с Защищенной аудиторией работает с 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 .

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

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

Рассмотрим следующий сценарий: используя API сигналов защищенных приложений, рекламная технология сохраняет релевантные сигналы на основе использования приложения пользователем. В нашем примере сохраняются сигналы, которые представляют собой покупки в нескольких приложениях. Во время аукциона зашифрованные сигналы собираются и передаются на защищенный аукцион, проводимый в B&A. Пользовательские функции покупателя, работающие в 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};
}

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

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

[Покупатели] Пример UDF для поиска объявлений

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

function HandleRequest(requestMetadata, protectedSignals, deviceMetadata,
                      contextualSignals) {
 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};
}

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

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-сервер сигналов оценки, чтобы было доступно сопоставление 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
  };
}

[Продавец] Пример отчетаРезультат

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, который можно найти в этом примере репозитория .