Protected App Signals 开发者指南

为帮助开发者开始试用 Protected App Signals API,本文档将介绍 API surface 中的所有 API,详细说明如何设置测试环境,并提供配置和脚本的示例。如需概要了解 Protected App Signals API,请参阅设计方案

API 概览

Protected Signals API Surface 在不同系统上包含不同 API 子集:

  • Android API:
    • Signal Curation API,其中包含:
    • Update Signals API
    • Signals Encoding API
    • Protected Auction Support API:供 SDK 使用,以便在使用 Protected App Signals 的出价和竞价 (B&A) 服务器上运行受保护竞价。
  • 服务器端 API:
    • Protected Auction API:在出价和竞价服务器中运行的一系列 JS 脚本。卖方和买方可以使用此 API 编写逻辑来实现受保护的竞价。
    • Ad Retrieval API:负责根据买方出价服务器可用的情境信息和用户信息提供候选广告列表。

Android 客户端

在客户端,Protected App Signals Surface 由三个不同的 API 组成:

  • Update Signals:一种 Android 系统 API,用于在设备上启用信号分类。
  • Signals Encoding:一种 JavaScript API,用于准备要在竞价期间发送至服务器的信号。
  • Protected Auction Support:支持在出价和竞价服务器上执行受保护的竞价的 API。此 API 并非特定于 Protected App Signals,也用于支持 Protected Audience API 竞价。

Update Signals API

Update Signals API 使广告技术平台能够代表买方注册用户和应用相关信号。该 API 基于委托模型。调用方会提供一个 URI,框架可从该 URI 中提取相应的信号以及对要在竞价中使用的那些信号进行编码的逻辑。

updateSignals() API 将从 URI 中检索一个 JSON 对象,该对象说明了需要添加或移除哪些信号,以及如何为竞价准备这些信号。

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

平台会向请求中提供的 URI 发出 https 请求,以提取信号更新。除了信号更新之外,响应还可以包含一个端点,该端点托管用于将原始信号转换为编码载荷的编码逻辑。信号更新应采用 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。用于提供更新操作的子键是“action”,

目前支持的值只有“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"
    }
}

Signals Encoding API

买方必须提供一个 Java 脚本函数,用于对存储在设备上的信号进行编码,以便在受保护的竞价期间发送到服务器。买方可通过在 UpdateSignal API 请求的任何响应中添加可使用键“update_encoder”提取相应脚本的网址,以提供此脚本。此脚本将具有以下签名:

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 参数是从大小为 4 的 UInt8Arrays 形式的键到 Protected App Signals 对象列表的映射。每个 Protected App Signals 对象都有三个字段:

  • signal_value:一个表示信号值的 UInt8Array。
  • creation_time:一个数字,表示信号的创建时间(以新纪元秒数表示)。
  • package_name:一个字符串,表示创建信号的软件包的名称。

maxSize 参数是一个数字,用于描述输出的最大允许数组大小。

该函数应输出包含以下两个字段的对象:

  • status:如果脚本成功运行,则应为 0。
  • results:应为长度小于或等于 maxSize 的 UInt8Array。 此数组将在竞价期间发送到服务器,并由 prepareDataForAdRetrieval 脚本进行准备。

编码为广告技术平台提供了特征工程的初始阶段,在该阶段,广告技术平台可以执行转换,例如根据自己的自定义逻辑将原始信号压缩为串联版本。请注意,在可信执行环境 (TEE) 中运行 Protected Auction 期间,广告技术平台自定义逻辑将拥有对编码生成的信号载荷的读取权限。在买方的 B&A TEE 中运行的自定义逻辑(称为用户定义的函数 (UDF))将拥有对编码信号和发布商应用提供的其他情境信号的读取权限,以便执行执行广告选择操作(广告检索和出价)。

信号编码

每个小时,已为其注册信号提供编码逻辑的买方都会将其信号编码为竞价载荷。竞价载荷的字节数组持久保存在设备上并经过加密,将作为广告选择数据的一部分由卖方收集,并作为 Protected Auction 的一部分包含在内。对于测试,您可以通过运行以下命令,在每小时的节奏之外触发此编码:

adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
编码器逻辑版本控制

发出下载广告技术自定义编码器逻辑的请求时,广告技术平台端点可以在响应标头中使用版本号进行响应。此版本与设备上的编码器逻辑一起持久保留。对原始信号进行编码时,编码的载荷会与用于编码的版本一起保留。此版本也会在 Protected Auction 期间随同 B&A 服务器一起发送,以便广告技术平台可以根据版本调整其出价和编码逻辑。

Response header for providing encoder version : X_ENCODER_VERSION

Protected Auction Support API

在设备端,为 Protected App Signals 运行竞价的方式与为受保护的受众群体运行竞价相同

出价和竞价服务

服务器端 API 包括:

  • Protected Auction API:一系列 JS 函数或 UDF,买方和卖方可以在他们拥有的 B&A 组件上部署这些函数,以确定出价和竞价逻辑。
  • Ad Retrieval API:买方可通过实现 REST 端点来实现此 API,该端点负责为 Protected App Signal 竞价提供一组候选广告。

Protected Auction API

Protected Auction API 由 JS API 或 UDF 组成,买方和卖方可以使用它们来实现其竞价和出价逻辑。

买方广告技术平台 UDF
prepareDataForAdRetrieval UDF

买方必须先解码并准备 Protected App Signals 及其他卖方提供的数据,然后才能使用 Protected App Signals 从 BYOS 广告检索服务提取候选广告。买方 prepareDataForAdRetrieval 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 adtech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
   return {};
}
generateBid 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) {
    return { "ad": <ad Value Object>,
             "bid": <float>,
             "render": <render URL string>
    };
}

此函数的输出是对候选广告的单次出价,表示为与 ProtectedAppSignalAdWithBidBidMetadata 等效的 JSON

reportWin UDF

竞价结束后,竞价服务将为买方生成报告网址,并使用 reportWin UDF(用于 Protected Audience 的同一 reportWin 函数)注册信标。 客户端呈现广告后,设备将对此执行 ping 操作。 除了 protectedAppSignalsEgress 中一个额外的参数之外,此方法的签名与 Protected Audience 版本几乎相同。目前不支持此参数。

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals, protectedAppSignalsEgress) {
  // ...
}
卖方广告技术平台 UDF
ScoreAd UDF

卖方会使用此 UDF 选择从买方收到的哪些广告将在竞价中胜出。

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

借助此 UDF,卖方可以(最终)使用胜出广告的相关信息进行事件级报告。

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

Ad Retrieval API

对于此 MVP,广告检索服务将是由买方管理的托管服务。出价服务将从此服务中检索候选广告。对于 DP10,此服务器将使用带有 PUT 动词的 HTTP/JSON 接口处理广告检索请求。在 DP10 之后,此服务器必须在可信执行环境 (TEE) 中运行,并且将公开 GRPC/proto 接口。广告技术公司必须设置此服务器,并在 B&A 堆栈部署中提供其网址。

输入格式

提取候选广告所需的输入数据是 partitions > arguments 代码块中的 Protected App Signals,其中参数序列如下所示:

  • prepareDataForAdRetrieval 所返回数据的转换成字符串后的 JSON 版本。
  • 从客户端发送的设备元数据。
  • 情境信号。
{
   "partitions" : [
      {
         "arguments" : [
            {
               "data" : "{\"key1\": \"1\", \"key2\": \"2\"}"
            },
            {
               "data" : {
                  "X-Accept-Language" : "en-US,en;q=0.9",
                  "X-BnA-Client-IP" : "1.2.3.4",
                  "X-User-Agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
               }
            },
            {
               "data" : "{\"key3\": \"3\"}"
            }
         ]
      }
   ]
}

输出格式

服务的输出将包含以下格式的 JSON 对象:

{"singlePartition":{"stringOutput": "arbitrary text string"}}

广告技术平台可以将元数据作为 singlePartition > stringOutput 键的值嵌入到候选广告中,这些元数据可以作为广告技术平台的自定义 generateBid UDF 的输入。

设置系统开发环境

Android

如需设置 Android 开发环境,您需要执行以下操作:

  1. 创建运行开发者预览版 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 服务堆栈之前,买方广告技术平台需要确保以下事项:

  • 他们已部署了自己的 BYOS 广告检索服务(请参阅相关部分)。
  • 广告技术平台已定义并托管所有必要的 UDF(prepareDataForAdRetrievalgenerateBidreportWin)。

了解如何将 B&A 与通过 Protected Audience 开展 Protected Auction 竞价搭配使用也会有所帮助,但不是强制性要求。

Terraform 配置

如需使用 Protected App Signals,广告技术平台必须:

  • 在 B&A 中启用 Protected App Signals 支持。
  • 提供可从中提取 prepareDataForAdRetrieval, generateBidreportWin 的新 UDF 的网址端点。

此外,本指南假定希望使用 B&A 进行再营销的广告技术平台会继续照常为再营销竞价设置所有现有配置标志。

买方广告技术平台配置

以此演示文件为例,买方需要设置以下标志:

  • 启用 Protected App Signals:启用以收集 Protected App Signals 数据。
  • Protected App Signals 网址:设置为 Protected App Signals 服务器的网址。

广告技术平台必须将以下字段的占位符替换为正确的网址:

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

  runtime_flags = {
    # ... More config here.

    ENABLE_PROTECTED_APP_SIGNALS                  = "true"
    PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS = "60000"
    AD_RETRIEVAL_KV_SERVER_ADDR                   = "<Ad Retrieval Service URL>"
    BYOS_AD_RETRIEVAL_SERVER                      = "true"
    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"

卖方广告技术平台配置

以此 demo 文件为例,卖方必须设置以下标志。(注意:此处仅突出显示与 Protected App Signals 相关的配置)。广告技术平台需要确保将占位符替换为正确的网址:

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"

设置示例

请考虑以下情形:广告技术平台借助 Protected App Signals API 根据用户应用使用情况存储相关信号。在我们的示例中,存储的信号表示多个应用中的应用内购买交易。在竞价期间,系统会收集加密信号,并将其传递到在 B&A 中运行的 Protected Auction 竞价。在 B&A 中运行的买方 UDF 会根据这些信号来提取候选广告并计算出价。

[买方] 信号示例

添加一个键为 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, 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;
}

[买方] 广告检索服务器响应示例

在我们的示例中,广告检索服务器为前 k 个候选广告中的每一个发送元数据(即本示例中每个广告的 ID,但可以包含每个广告的其他数据,这些数据有助于稍后生成出价)。

{"singlePartition":{"stringOutput":"[{\"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 会向买方报告他们在竞价中胜出。在 MVP 中,您会看到一个名为 egressFeatures 的额外参数,该参数在此 MVP 中未使用,但为了确保正确性,签名中仍需要该参数。

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

[卖方] KV 服务器设置

卖方必须设置得分信号 KV 服务器,以便提供从广告呈现网址到相应得分信号的映射。例如:如果 https:/buyer-domain.com/get-fitness-apphttps:/buyer-domain.com/get-fastfood-app 由买方返回,那么当 SFE 使用 GEThttps://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"
      ]
   }
}

[Seller] scoreAd 示例

/**
 * 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 示例应用,该应用可在此示例代码库中找到。