Private Aggregation API 基础知识

Private Aggregation API 的关键概念

本文档的适用对象

Private Aggregation API 支持从具有跨网站数据访问权限的工作流中收集汇总数据。这里分享的概念对于在 Shared Storage API 和 Protected Audience API 中构建报告功能的开发者来说非常重要。

  • 如果您是开发者,正在构建用于跨网站衡量的报告系统。
  • 如果您是营销者数据科学家或其他摘要报告使用者,了解这些机制有助于您做出设计决策,以检索经过优化的摘要报告。

关键词

在阅读本文档之前,建议您先熟悉关键术语和概念。下面将详细介绍这些术语。

  • 汇总键(也称为“存储分区”)是一组预先确定的数据点。例如,您可能需要收集一个存储浏览器报告的国家/地区名称的位置数据存储分区。汇总键可以包含多个维度(例如,国家/地区和内容微件的 ID)。
  • 可汇总的值是收集到汇总键中的单个数据点。如果您要衡量有多少法国用户查看了您的内容,则 France 是汇总键中的维度,1viewCount 是可汇总的值。
  • 可汇总的报告是在浏览器中生成和加密的。对于 Private Aggregation API,此字段包含与单个事件相关的数据。
  • 汇总服务会处理可汇总报告中的数据,以创建摘要报告。
  • 摘要报告是汇总服务的最终输出,其中包含噪声较大的汇总用户数据和详细的转化数据。
  • worklet 是一种基础架构,可让您运行特定 JavaScript 函数并将信息返回给请求方。您可以在 worklet 中执行 JavaScript,但无法与外部网页互动或通信。

不公开汇总工作流程

当您使用汇总键和可汇总的值调用 Private Aggregation API 时,浏览器会生成可汇总的报告。报告会发送到您的服务器,由服务器进行批量处理。汇总服务稍后会处理批量报告,并生成摘要报告。

数据会从客户端流向收集器,然后流向汇总服务,以生成摘要报告。
  1. 当您调用 Private Aggregation API 时,客户端(浏览器)会生成可汇总的报告并将其发送到您的服务器进行收集。
  2. 您的服务器从客户端收集报告,并将其分批发送到汇总服务。
  3. 收集足够的报告后,您将对其进行分批处理,并将其发送到在可信执行环境中运行的汇总服务,以生成摘要报告。

本部分介绍的工作流与 Attribution Reporting API 类似。不过,归因报告会将来自展示事件和转化事件(发生在不同时间)的数据相关联。不公开汇总功能可衡量单个跨网站事件。

汇总键

汇总键(简称“键”)表示将汇总可汇总值的分桶。您可以将一个或多个维度编码到键中。维度表示您想要深入了解的某个方面,例如用户的年龄段或广告系列的展示次数。

例如,您可能在多个网站上嵌入了 widget,并希望分析查看过该 widget 的用户所在的国家/地区。您希望回答诸如“查看过我微件的用户中有多少来自 X 国家/地区?”之类的问题。如需针对此问题生成报告,您可以设置一个汇总键,用于编码两个维度:微件 ID 和国家/地区 ID。

向 Private Aggregation API 提供的键是 BigInt,它由多个维度组成。在此示例中,维度是 widget ID 和国家/地区 ID。假设 widget ID 最多可包含 4 位数字,例如 1234,并且每个国家/地区都映射到一个按字母顺序排列的数字,例如阿富汗是 1、法国是 61,津巴布韦是 195。因此,可汇总的键的长度为 7 位,其中前 4 位保留用于 WidgetID,后 3 位保留用于 CountryID

假设该键表示已查看微件 ID 3276 的法国用户(国家/地区 ID 为 061)的数量,汇总键为 3276061

汇总键
微件 ID 国家/地区 ID
3276 061

您还可以使用哈希机制(例如 SHA-256)生成汇总键。例如,字符串 {"WidgetId":3276,"CountryID":67} 可以进行哈希处理,然后转换为 42943797454801331377966796057547478208888578253058197330928948081739249096287nBigInt 值。如果哈希值超过 128 位,您可以对其进行截断,以确保其不会超过允许的最大分桶值 2^128−1

在共享存储工作流中,您可以访问 cryptoTextEncoder 模块,它们可以帮助您生成哈希。如需详细了解如何生成哈希,请参阅 MDN 上的 SubtleCrypto.digest()

以下示例介绍了如何根据经过哈希处理的值生成存储分区键:

async function convertToBucket(data) {
  // Encode as UTF-8 Uint8Array
  const encodedData = new TextEncoder().encode(data);

  // Generate SHA-256 hash
  const hashBuffer = await crypto.subtle.digest('SHA-256', encodedData);

  // Truncate the hash
  const truncatedHash = Array.from(new Uint8Array(hashBuffer, 0, 16));

  // Convert the byte sequence to a decimal
  return truncatedHash.reduce((acc, curr) => acc * 256n + BigInt(curr), 0n);
}

const data = {
  WidgetId: 3276,
  CountryID: 67
};

const dataString = JSON.stringify(data);
const bucket = await convertToBucket(dataString);

console.log(bucket); // 126200478277438733997751102134640640264n

可汇总的值

系统会对许多用户的每个键值进行求和,以便在摘要报告中以摘要值的形式生成汇总数据分析。

现在,我们回到之前提出的示例问题:“查看过我 widget 的用户中有多少来自法国?”此问题的答案将类似于“查看过我的微件 ID 3276 的用户中有大约 4881 位来自法国”。每个用户的可汇总值为 1,而“4881 位用户”是汇总值,即该汇总键的所有可汇总值的总和。

汇总键 可汇总的值
微件 ID 国家/地区 ID 观看次数
3276 061 1

在此示例中,我们会针对看到该微件的每位用户将此值递增 1。在实践中,可对可汇总的值进行缩放,以提高信噪比

贡献预算

对 Private Aggregation API 的每次调用都称为一次贡献。为了保护用户隐私,我们限制从个人收集的贡献数量。

对所有汇总键中的所有可汇总值求和时,总和必须小于贡献预算。预算的范围是按工作区 origin 和每天进行划分,并且 Protected Audience API 和 Shared Storage 工作区之间的预算是相互独立的。系统会使用大约过去 24 小时的滚动时间范围来计算当天的数据。如果新的可汇总报告会导致超出预算,系统将不会创建该报告。

贡献预算由参数 L1 表示,并设置为每天每 10 分钟 216 (65,536),回退值为 220 (1,048,576)。如需详细了解这些参数,请参阅说明文档

贡献预算的值是任意的,但噪声会按此缩放。 您可以使用此预算来最大限度地提高摘要值的信噪比(详见噪声和缩放部分)。

如需详细了解贡献预算,请参阅说明。此外,如需更多指导,请参阅贡献预算

每个报告的贡献次数上限

捐款限额可能会因来电者而异。目前,为 Shared Storage API 调用方生成的报告每份报告的贡献数量上限为 20 项。另一方面,Protected Audience API 调用方每份报告的贡献次数上限为 100 次。我们之所以选择这些限制,是为了平衡可嵌入的贡献数量与载荷大小。

对于共享存储空间,单个 run()selectURL() 操作中贡献的数据会批量汇总到一个报告中。对于 Protected Audience,单个来源在竞价中提供的贡献会汇总在一起。

带内边距的贡献

贡献内容会通过内边距功能进一步修改。对载荷进行填充可保护汇总报告中嵌入的贡献真实数量的信息。内边距会使用 null 贡献(即值为 0)来增补载荷,以达到固定长度。

可汇总的报告

用户调用 Private Aggregation API 后,浏览器会生成可汇总报告,以供汇总服务稍后处理,以生成摘要报告。可汇总的报告采用 JSON 格式,包含加密的贡献列表,每个贡献都是一个 {aggregation key, aggregatable value} 对。可汇总报告的发送会随机延迟,最长延迟一小时。

贡献内容已加密,在汇总服务之外无法读取。汇总服务会对报告进行解密并生成摘要报告。浏览器的加密密钥和汇总服务的解密密钥由协调者(充当密钥管理服务)签发。协调者会保留服务映像的二进制哈希列表,以验证调用方是否有权接收解密密钥。

启用了调试模式的可汇总报告示例:

  "aggregation_service_payloads": [
    {
      "debug_cleartext_payload": "omRkYXRhgaJldmFsdWVEAAAAgGZidWNrZXRQAAAAAAAAAAAAAAAAAAAE0mlvcGVyYXRpb25paGlzdG9ncmFt",
      "key_id": "2cc72b6a-b92f-4b78-b929-e3048294f4d6",
      "payload": "a9Mk3XxvnfX70FsKrzcLNZPy+00kWYnoXF23ZpNXPz/Htv1KCzl/exzplqVlM/wvXdKUXCCtiGrDEL7BQ6MCbQp1NxbWzdXfdsZHGkZaLS2eF+vXw2UmLFH+BUg/zYMu13CxHtlNSFcZQQTwnCHb"
    }
  ],
  "debug_key": "777",
  "shared_info": "{\"api\":\"shared-storage\",\"debug_mode\":\"enabled\",\"report_id\":\"5bc74ea5-7656-43da-9d76-5ea3ebb5fca5\",\"reporting_origin\":\"https://localhost:4437\",\"scheduled_report_time\":\"1664907229\",\"version\":\"0.1\"}"

您可以在 chrome://private-aggregation-internals 页面中检查可汇总报告:

Private Aggregation API 内部页面的屏幕截图

出于测试目的,您可以使用“发送所选报告”按钮立即将报告发送到服务器。

收集和批量处理可汇总报告

浏览器使用列出的知名路径,将可聚合的报告发送到包含对 Private Aggregation API 的调用的 Worklet 的来源:

  • 对于 Shared Storage:/.well-known/private-aggregation/report-shared-storage
  • 对于 Protected Audience:/.well-known/private-aggregation/report-protected-audience

在这些端点上,您需要运行一台服务器(充当收集器),用于接收从客户端发送的可汇总报告。

然后,服务器应将报告分批并将批量数据发送到汇总服务。根据可汇总报告的未加密载荷中提供的信息(例如 shared_info 字段)创建批次。理想情况下,每个批次应包含 100 份或更多报告。

您可以选择每天或每周批量处理。此策略非常灵活,您可以针对预计会带来更多流量的特定事件(例如,预计会带来更多展示次数的年份日期)更改批量处理策略。批处理应包含使用相同 API 版本、报告来源和安排报告时间的报告。

过滤 ID

借助 Private Aggregation API 和 Aggregation Service,您可以使用过滤 ID 在更精细的级别(例如按广告系列)处理衡量结果,而不是在更大范围的查询中处理结果。

PAA SS 图

如需立即开始使用,请参考以下粗略步骤,将其应用于您当前的实现。

共享存储空间步骤

如果您在流程中使用 Shared Storage API

  1. 定义您将在何处声明和运行新的共享存储模块。在以下示例中,我们将模块文件命名为 filtering-worklet.js,并在 filtering-example 下注册。

    (async function runFilteringIdsExample () {
      await window.sharedStorage.worklet.addModule('filtering-worklet.js');
      await window.sharedStorage.run('filtering-example', {
        keepAlive: true,
        privateAggregationConfig: {
          contextId: 'example-id',
          filteringIdMaxBytes: 8 // optional
        }
      }});
    })();
    

    请注意,filteringIdMaxBytes 可按报告进行配置,如果未设置,则默认为 1。此默认值旨在防止不必要地增加载荷大小,从而降低存储和处理费用。 如需了解详情,请参阅灵活贡献说明

  2. 在您上面使用的文件(在本例中为 filtering-worklet.js)中,当您在共享存储工作流内将贡献内容传递给 privateAggregation.contributeToHistogram(...) 时,可以指定过滤 ID。

    // Within  filtering-worklet.js
    class FilterOperation {
        async run() {
          let contributions = [{
            bucket: 1234n,
            value: 56,
            filteringId: 3n // defaults to 0n if not assigned, type bigint
          }];
    
          for (const c of contributions) {
            privateAggregation.contributeToHistogram(c);
          }
          …
      }
    });
    
    register('filtering-example', FilterOperation);
    
  3. 系统会将可聚合报告发送到您定义的端点 /.well-known/private-aggregation/report-shared-storage 所在的位置。请继续参阅过滤 ID 指南,了解需要对汇总服务作业参数进行哪些更改。

批处理完成并发送到已部署的汇总服务后,过滤后的结果应会反映在最终摘要报告中。

Protected Audience 步骤

如果您在流程中使用 Protected Audience API

  1. 在您目前的 Protected Audience 实现中,您可以设置以下代码以钩入 Private Aggregation。与共享存储空间不同,目前还无法配置过滤 ID 的大小上限。默认情况下,过滤 ID 的大小上限为 1 字节,并将设置为 0n。请注意,这些参数将在 [Protected Audience 报告函数](Protected Audience 报告函数)(例如 reportResult()generateBid())中设置。

    const contribution = {
        ...
        filteringId: 0n
    };
    
    privateAggregation.contributeToHistogram(contribution);
    
  2. 系统会将可聚合报告发送到您定义的端点 /.well-known/private-aggregation/report-protected-audience 所在的位置。批处理完成并发送到已部署的汇总服务后,过滤后的结果应会反映在最终摘要报告中。提供了以下有关 Attribution Reporting API 和 Private Aggregation API 的说明以及初始提案。

请继续阅读汇总服务中的过滤 ID 指南,或前往 Attribution Reporting API 部分,了解更详细的说明。

汇总服务

该服务在 TEE 中运行,解密可汇总的报告并添加噪声以生成最终的摘要报告。

汇总服务会从收集器接收经过加密的可汇总报告,并生成摘要报告。如需详细了解如何在收集器中批量处理可汇总的报告,请参阅我们的批处理指南

该服务在可信执行环境 (TEE) 中运行,可为数据完整性、数据机密性和代码完整性提供一定程度的保证。如果您想详细了解如何将协调器与 TEE 搭配使用,请详细了解其角色和用途

摘要报告

通过摘要报告,您可以查看添加了噪声的收集数据。您可以请求针对给定一组键生成摘要报告。

摘要报告包含一组 JSON 字典式键值对。每个对包含:

  • bucket:汇总键(以二进制数字字符串表示)。如果使用的汇总键为“123”,则该存储分区为“1111011”。
  • value:指定衡量目标的摘要值,是从添加了噪声的所有可汇总报告中汇总得出的。

例如:

[
  {"bucket":` `"111001001",` `"value":` `"2558500"},
  {"bucket":` `"111101001",` `"value":` `"3256211"},
  {"bucket":` `"111101001",` `"value":` `"6536542"},
]

噪声和缩放

为保护用户隐私,每次请求摘要报告时,汇总服务都会向每个摘要值添加一次噪声。噪声值是从拉普拉斯概率分布中随机抽取的。虽然您无法直接控制添加噪声的方式,但可以影响噪声对衡量数据的影响。

无论所有可汇总值的总和如何,噪声分布都是相同的。因此,可汇总的值越高,噪声的影响就越小。

例如,假设噪声分布的标准差为 100,且中心为零。如果收集的可汇总报告值(或“可汇总值”)仅为 200,则噪声的标准差将为汇总值的 50%。但是,如果可汇总的值为 2 万,则噪声的标准差只会占汇总值的 0.5%。因此,可汇总的值为 2 万时,信噪比会高得多。

因此,将可汇总的值乘以缩放比例有助于减少噪声。缩放比例表示您希望对给定可汇总值进行的缩放比例。

无论汇总值如何,噪声都是不变的。

通过选择较大的放大系数来放大值可以减少相对噪声。不过,这也会导致所有广告系列所带来的贡献总和更快达到贡献预算上限。通过选择较小的缩放系数常量来缩小值会增加相对噪声,但会降低达到预算上限的风险。

将可汇总的值按贡献预算进行缩放。

如需计算适当的放大系数,请将贡献预算除以所有键的可汇总值的最大总和。

如需了解详情,请参阅贡献预算文档

互动和分享反馈

不公开汇总 API 正在积极讨论中,未来可能会发生变化。如果您试用此 API 并有反馈,我们非常期待收到您的反馈。