共享存储空间和私有聚合实现快速入门

本文档是有关如何使用共享存储空间和不公开汇总的快速入门指南。您需要了解这两个 API,因为共享存储空间存储值,而不公开汇总会创建可汇总报告。

目标受众群体:广告技术平台和衡量服务提供商。

试用演示版

试用实时演示。按照演示说明中的步骤启用 Privacy Sandbox API。打开 Chrome DevTools 有助于您直观呈现不同用例的结果。演示中提供的用例:

  • 不公开汇总
    • 覆盖的唯一身份用户数
    • 受众特征衡量
    • K+ 频次衡量
  • 一般用法
    • 衡量围栏框架内的悬停事件
    • 顶级导航
    • 控制第三方写入内容的位置

如何查看共享存储空间

要查看共享存储空间中存储的内容,请使用 Chrome 开发者工具。存储的数据可以在 Application -> Shared Storage 中找到。

使用 Chrome 开发者工具查看存储在共享存储空间中的数据。

查看不公开汇总的报告

如需查看发送的可汇总报告,请前往 chrome://private-aggregation-internals。启用调试模式后,报告会立即(无延迟)发送到 [[YOUR_ORIGIN]]/.well-known/private-aggregation/debug/report-shared-storage,延迟报告会同时发送到 [[YOUR_ORIGIN]]/.well-known/private-aggregation/report-shared-storage

如需启用调试功能,请按照调试部分中的说明操作。

在 chrome://private-aggregate-internals 中查看报告。

共享存储空间 API

为了防止跨网站跟踪,浏览器已开始对所有形式的存储进行分区,包括本地存储、Cookie 等。但某些使用场景需要使用未分区存储。Shared Storage API 提供可保护隐私的读取权限,可跨不同的顶级网站提供不受限制的写入权限。

共享存储空间仅限于上下文来源(sharedStorage 的调用方)。

共享存储空间针对每个来源有容量限制,每个条目有最大字符数限制。如果达到此上限,则系统不会存储任何进一步的输入。共享存储空间说明文档中概述了数据存储限制。

调用共享存储空间

广告技术平台可以使用 JavaScript 或响应标头向共享存储空间写入数据。从共享存储空间读取的内容仅在独立的 JavaScript 环境中进行,称为 Worklet。

  • 使用 JavaScript 广告技术平台可以执行特定的共享存储空间功能,例如设置、附加和删除 JavaScript Worklet 之外的值。但是,读取共享存储空间和执行不公开汇总等功能必须通过 JavaScript Worklet 完成。您可以在 Proposed API Surface - Worklet 外中找到可在 JavaScript Worklet 之外使用的方法。

    您可以在建议的 API Surface - 在 Worklet 中中找到操作期间在 Worklet 中使用的方法。

  • 使用响应标头

    与 JavaScript 类似,只有特定函数(例如设置、附加和删除共享存储空间中的值)才能使用响应标头完成。如需在响应标头中使用共享存储空间,请求标头中必须包含 Shared-Storage-Writable: ?1

    如需从客户端发起请求,请根据您选择的方法运行以下代码:

    • 使用 fetch()

      fetch("https://a.example/path/for/updates", {sharedStorageWritable: true});
      
    • 使用 iframeimg 标记

      <iframe src="https://a.example/path/for/updates" sharedstoragewritable></iframe>
      
    • 使用带有 iframeimg 标记的 IDL 属性

      let iframe = document.getElementById("my-iframe");
      iframe.sharedStorageWritable = true;
      iframe.src = "https://a.example/path/for/updates";
      

如需了解详情,请参阅共享存储空间:响应标头

写入共享存储空间

如需写入共享存储空间,请从 JavaScript Worklet 内部或外部调用 sharedStorage.set()。如果从 Worklet 外部调用,系统会将数据写入发起调用的浏览上下文的来源。如果是在 Worklet 内调用,系统会将数据写入加载该 Worklet 的浏览上下文的来源。所设置密钥的有效期为自上次更新起 30 天。

ignoreIfPresent 字段为可选字段。如果存在并设置为 true,则如果键已存在,则不会更新。自 set() 调用起,密钥有效期会续期 30 天,即使密钥未更新也是如此。

如果在同一页面加载时使用同一键多次访问共享存储空间,则会覆盖该键的值。如果键需要保留之前的值,最好使用 sharedStorage.append()

  • 使用 JavaScript

    在 Worklet 外:

    window.sharedStorage.set('myKey', 'myValue1', { ignoreIfPresent: true });
    // Shared Storage: {'myKey': 'myValue1'}
    window.sharedStorage.set('myKey', 'myValue2', { ignoreIfPresent: true });
    // Shared Storage: {'myKey': 'myValue1'}
    window.sharedStorage.set('myKey', 'myValue2', { ignoreIfPresent: false });
    // Shared Storage: {'myKey': 'myValue2'}
    

    同样,在 Worklet 内:

    sharedStorage.set('myKey', 'myValue1', { ignoreIfPresent: true });
    
  • 使用响应标头

    您还可以使用响应标头写入共享存储空间。为此,请在响应标头中使用 Shared-Storage-Write 并使用以下命令:

    Shared-Storage-Write : set;key="myKey";value="myValue";ignore_if_present
    
    Shared-Storage-Write : set;key="myKey";value="myValue";ignore_if_present=?0
    

    如果有多个项目,请用逗号分隔,并且可以组合使用 setappenddeleteclear

    Shared-Storage-Write : 
    set;key="hello";value="world";ignore_if_present, set;key="good";value="bye"
    

附加值

您可以使用附加方法为现有键附加值。如果该键不存在,则调用 append() 会创建该键并设置相应值。这可以通过 JavaScript 或响应标头来实现。

  • 使用 JavaScript

    如需更新现有键的值,请从 Worklet 内部或外部使用 sharedStorage.append()

    window.sharedStorage.append('myKey', 'myValue1');
    // Shared Storage: {'myKey': 'myValue1'}
    window.sharedStorage.append('myKey', 'myValue2');
    // Shared Storage: {'myKey': 'myValue1myValue2'}
    window.sharedStorage.append('anotherKey', 'hello');
    // Shared Storage: {'myKey': 'myValue1myValue2', 'anotherKey': 'hello'}
    

    如需在 Worklet 内附加内容,请执行以下操作:

    sharedStorage.append('myKey', 'myValue1');
    
  • 使用响应标头

    与在共享存储空间中设置值类似,您可以使用响应标头中的 Shared-Storage-Write 传入键值对。

    Shared-Storage-Write : append;key="myKey";value="myValue2"
    

从共享存储空间读取数据

您只能从 Worklet 中读取共享存储空间中的内容。

await sharedStorage.get('mykey');

加载 Worklet 模块的浏览上下文的来源决定了读取谁的共享存储空间。

正在从共享存储空间中删除

您可以使用来自 Worklet 内部或外部的 JavaScript,或者通过结合使用响应标头和 delete() 从共享存储空间执行删除操作。如需一次性删除所有键,请在任一项中使用 clear()

  • 使用 JavaScript

    要从 Worklet 外部的共享存储空间中删除内容,请执行以下操作:

    window.sharedStorage.delete('myKey');
    

    如需从 Worklet 从共享存储空间中删除内容,请执行以下操作:

    sharedStorage.delete('myKey');
    

    如需从 Worklet 外部一次性删除所有键,请执行以下操作:

    window.sharedStorage.clear();
    

    如需从 Worklet 中一次性删除所有键,请执行以下操作:

    sharedStorage.clear();
    
  • 使用响应标头

    如需使用响应标头删除值,您还可以在响应标头中使用 Shared-Storage-Write 来传递要删除的密钥。

    delete;key="myKey"
    

    如需使用响应标头删除所有密钥,请执行以下操作:

    clear;
    

上下文切换

共享存储空间数据会写入发起调用的浏览上下文的来源(例如 https://example.adtech.com)。

当您使用 <script> 标记加载第三方代码时,该代码会在嵌入器的浏览上下文中执行。因此,当第三方代码调用 sharedStorage.set() 时,数据将写入嵌入器的共享存储空间。在 iframe 中加载第三方代码时,该代码会收到新的浏览上下文,其来源是 iframe 的来源。因此,从 iframe 发出的 sharedStorage.set() 调用会将数据存储在 iframe 来源的共享存储空间中。

第一方环境

如果第一方网页嵌入了调用 sharedStorage.set()sharedStorage.delete() 的第三方 JavaScript 代码,则键值对会存储在第一方上下文中。

使用嵌入的第三方 JavaScript 存储在第一方网页中的数据。

第三方上下文

通过创建 iframe 并在该 iframe 内的 JavaScript 代码中调用 set()delete(),可将键值对存储在广告技术平台或第三方环境中。

在广告技术平台或第三方环境中存储的数据。

Private Aggregation API

如需衡量存储在共享存储空间中的可汇总数据,您可以使用 Private Aggregation API。

要创建报告,请在 Worklet 中使用存储分区和值调用 contributeToHistogram()。存储分区由无符号 128 位整数表示,必须作为 BigInt 传入函数。该值是一个正整数。

为了保护隐私,报告的载荷(包含存储分区和值)会在传输过程中加密,并且只能使用汇总服务解密和汇总。

浏览器还会限制网站对输出查询的贡献。具体而言,贡献预算限制了给定浏览器在指定时间范围内来自单个网站的所有报告的总和。如果超出当前预算,则不会生成报告。

privateAggregation.contributeToHistogram({
  bucket: BigInt(myBucket),
  value: parseInt(myBucketValue)
});

执行共享存储空间和私有汇总

在广告的 iframe 中,通过调用 addModule() 加载 Worklet 模块。如需在同一广告 iframe JavaScript 中运行在 sharedStorageWorklet.js worklet 文件中注册的方法,请调用 sharedStorage.run()

await window.sharedStorage.worklet.addModule('modules/sharedStorageWorklet.js');
await window.sharedStorage.worklet.run('shared-storage-report', {
  data: { campaignId: '1234' },
});

在 Worklet 脚本中,您需要创建一个具有异步 run 方法的类。并使用 register 该类在广告的 iframe 中运行。 在 sharedStorageWorklet.js 内:

class SharedStorageReportOperation {
  async run(data) {
    // Other code goes here.
    bucket = getBucket(...);
    value = getValue(...);
    privateAggregation.contributeToHistogram({
      bucket: bucket,
      value: value
    });
  }
}
register('shared-storage-report',
  SharedStorageReportOperation);

调试

如需启用调试功能,请在使用共享存储空间和不公开汇总的同一上下文中调用 enableDebugMode() JavaScript 方法。这将在同一上下文中应用于将来的报告。

privateAggregation.enableDebugMode();

为了将报告与触发报告的上下文相关联,您可以设置一个传递给 JavaScript 调用的 64 位未签名整数调试密钥。debugKeyBigInt

privateAggregation.enableDebugMode({debugKey: 1234});

调试共享存储空间

共享存储空间返回一条一般错误消息:

Promise is rejected without and explicit error message

您可以使用 try-catch 块封装调用,以调试共享存储空间。

try {
  privateAggregation.contributeToHistogram({bucket, value});
} catch (e){
  console.log(e);
}

调试不公开汇总

报告会发送至 /.well-known/private-aggregation/report-shared-storage/.well-known/private-aggregation/debug/report-shared-storage。调试报告会收到类似于以下 JSON 的载荷。此载荷将 api 字段定义为“共享存储空间”。

{
   "aggregation_coordinator_identifier": "aws-cloud",
   "aggregation_service_payloads": [ {
      "debug_cleartext_payload": "omRkYXRhgaJldmFsdWVEAAAAgGZidWNrZXRQAAAAAAAAAAAAAAEfV32BFWlvcGVyYXRpb25paGlzdG9ncmFt",
      "key_id": "9bc4afa7-2934-4779-99ff-999d91b137ec",
      "payload": "bqOFO/cHCdwefU2W4FjMYRMSLoGHPWwZbgVF4aa/ji2YtwFz+jb6v2XCwQUdmvYcZSRPKosGRpKELJ0xAFv+VBYvCiv3FXP6jjAHQD+XAJUz17A39aXijk6JnEAu86+DfTSbXYn1fWhGzIG9xH/Y"
   } ],
   "debug_key": "1234",
   "shared_info": "{\"api\":\"shared-storage\",\"debug_mode\":\"enabled\",\"report_id\":\"93f86829-cdf7-4ecd-b16d-4e415a3ee063\",\"reporting_origin\":\"https://small-free-wealth.glitch.me\",\"scheduled_report_time\":\"1681319668\",\"version\":\"0.1\"}"
}

调试明文载荷

debug_cleartext_payload 采用 Base64 CBOR 编码。您可以使用解码器查看存储分区和值,也可以使用共享存储空间解码器中的 JavaScript 代码。

后续步骤

以下页面介绍了 Shared Storage API 和 Private Aggregation API 的重要方面。

熟悉这些 API 后,您就可以开始收集报告,这些报告将以 POST 请求的形式在请求正文中以 JSON 格式发送到以下端点。

  • 调试报告 - context-origin/.well-known/private-aggregation/debug/report-shared-storage
  • 报告 - context-origin/.well-known/private-aggregation/report-shared-storage

收集报告后,您可以使用本地测试工具进行测试,或设置汇总服务的可信执行环境以获取汇总报告。

分享反馈

您可以在 GitHub 上分享对 API 和文档的反馈。