归因第 1 级

W3C 工作草案

关于本文档的更多详细信息
此版本:
https://www.w3.org/TR/2026/WD-attribution-20260514/
最新发布版本:
https://www.w3.org/TR/attribution/
编辑草案:
https://w3c.github.io/attribution/
先前版本:
历史:
https://www.w3.org/standards/history/attribution/
反馈:
public-patwg@w3.org 主题行为 “[attribution] … 消息主题 …”(存档
GitHub
编辑:
(Google)
(Mozilla)
(Meta)
(Meta)
(Google)
(Mozilla)

摘要

本规范定义了一种用于衡量广告效果的浏览器 API。其目标是生成有关广告如何带来转化的聚合统计信息, 同时不对单个 Web 用户的隐私造成风险。此 API 会汇集来自多个 Web 源的有关用户的信息, 这可能对他们的隐私造成重大风险。为管理这种风险,所收集的信息会使用聚合服务进行聚合, 该服务受到用户代理信任,能够在严格限制内执行聚合。此服务生成的聚合结果会加入噪声, 以提供差分隐私。网站可以从用户代理提供的已批准聚合服务列表中选择聚合服务。

本文档状态

本节描述本文档在发布时的状态。当前 W3C 出版物列表以及本 技术报告的最新修订版可在 W3C 技术报告索引中找到。

欢迎对此规范提供反馈和评论。 推荐使用 GitHub Issues 讨论此 规范。或者,也可以将评论发送到 PAT 工作组的邮件列表 public-patwg@w3.org存档)。 本草案突出显示了一些仍有待工作组讨论的待处理议题。 对于这些议题的结果,包括它们是否有效,尚未作出决定。

本文档由 Private Advertising Technology Working Group 作为工作草案发布,并使用 推荐 标准轨道

作为工作草案发布并不意味着得到 W3C 及其成员的认可。

这是一份草案文档,可能随时由其他文档更新、替换或废弃。除作为正在进行的工作外, 不宜引用本文档。

本文档会随时维护和更新。本文档的某些部分仍在进行中。

本文档由一个根据 W3C 专利政策运作的小组制作。W3C 维护着一个与该小组交付成果相关的所有专利披露公开列表; 该页面还包含披露专利的说明。实际知悉某项专利且认为该专利包含必要权利要求的个人,必须按照 W3C 专利政策第 6 节披露该信息。

本文档受 2025 年 8 月 18 日 W3C 流程文档约束。

1. 引言

本文档定义了一个浏览器 API, 该 API 能够收集经过聚合且具有差分隐私保护的指标。

此 API 的目标是为广告启用归因。

1.1. 归因

在广告中,归因 是识别先于某个感兴趣结果发生的操作, 并将价值分配给这些操作的过程。

广告主感兴趣的操作 主要是广告的展示 (也称为 展示)。 其他操作包括广告点击(或其他交互), 以及未被采用的广告展示机会。

广告所期望的结果 更加多样, 因为它们包括广告主希望通过展示广告来改善的任何结果。 期望的结果也可以称为一次转化, 指将潜在客户“转化”为客户。 可算作转化的内容可能包括 销售、订阅、页面访问和咨询。

对于此 API,操作结果都是 事件:即只发生一次的事情。 广告归因的独特之处在于, 这些事件可能不会发生在同一个站点上。 广告最常展示在广告主站点以外的站点上。

归因的主要挑战在于维护隐私。 归因涉及连接不同站点上的活动。 归因的目标是找到一次展示, 该展示在转化发生之前已向同一个人展示。

如果归因信息被直接透露, 它将导致不期望的 跨上下文识别, 从而导致跟踪

本文档通过确保使用聚合服务 来聚合归因信息,从而避免跨上下文识别。 聚合服务被信任用于计算聚合结果, 而不会暴露每个人对该聚合结果所贡献的值。

对每个浏览器实例为给定站点的聚合结果 所贡献的信息量设有严格限制。 差分隐私用于为每次贡献提供额外的隐私保护。

聚合服务操作的详细信息包含在 § 7 聚合中。 所使用的差分隐私设计概述见 § 8 差分隐私

1.2. 背景

从 Web 的早期开始, 广告就被广泛用于为站点创建提供资金支持。

Web 区别于其他广告场所的一个特征, 是能够获得有关广告活动效果的信息。

Web 广告主能够衡量覆盖率(有多少人看到了广告)、 频次(每个人看到广告的频率)、 以及转化(有多少看到广告的人 之后执行了该广告意图促使其执行的操作)等关键指标。 相比之下,这些衡量比任何其他媒介都更及时且更准确。

衡量效果的代价是隐私。 为了生成准确且全面的信息, 广告业务会对所有 Web 用户的活动进行广泛跟踪。 每个浏览器都会被分配一个跟踪标识符, 通常使用由跨站内容记录的 cookie。 每个感兴趣的操作都会针对该标识符进行记录, 从而形成一个人的在线活动的完整记录。

拥有一个人的详细操作记录使广告主能够推断人们的特征。 这些特征使选择合适广告受众变得更加容易, 从而大幅提升广告效果。 这产生了收集更多信息的强烈激励。

在线广告竞争非常激烈。 展示广告的站点寻求从每个广告位获得最多收益。 广告主则寻求在相对于成本而言最能产生效果的位置投放广告。 这些实体——以及代表它们运作的中介方——所获得的任何竞争优势, 都取决于拥有关于潜在受众的更全面信息。

随着时间推移,感兴趣的操作扩展到几乎包括在线活动的每个方面。 人们还设计出方法,将这些信息与 Web 之外的活动相关联。 一个活跃的交易行业已经形成, 其中有多个个人信息供应商将个人信息用于各种目的进行交易。

1.3. 目标

本文档的目标是定义一种执行广告归因的方式, 且不会导致跟踪。

1.4. 最终用户益处

广告效果衡量会产生新的跨站信息流。 该信息流会产生隐私风险或成本——即跨上下文识别——因此需要以最终用户收益为依据进行正当化。

最终用户通过使用归因所实现的任何收益都是间接的。

访问网站的最终用户 主要通过他们对站点向其展示的任何广告所给予的注意力, 来为“免费”内容或服务付费。 这种“价值”归属于广告主, 广告主进而向站点付款。 站点预期会使用这笔资金 来支持其内容或服务的提供。

| Advertiser | | | Attention | | +-------------+ +-----+------+ ^ | | Content and | Money | Services | | v .----+------. +------------+ | Content | | | | Production | Investment | | Profit, | / |<-----------+ Website +-------> | Service | | | Expenses, | Improvement | | | etc... '-----------' +------------+ ]]> 用户 广告主 注意力 内容和 金钱 服务 内容 生产 投资 利润、 / 网站 服务 费用、 改进 等…
广告支持的内容和服务的价值交换

参与归因衡量系统 会构成 Web 用户的次级成本。

支持归因可带来更有效的广告, 主要方式是让广告主了解哪些广告效果最好, 以及在何种情况下效果最好。 这些情况可能包括 广告展示的时间和地点、 广告展示给谁, 以及广告本身的细节。

将这些信息连接到结果, 使广告主能够了解哪些情况最常导致 他们最看重的结果。 这使广告主能够在有效广告上投入更多, 在无效广告上投入更少。 这降低了相对于所获价值而言的总体广告成本。[ONLINE-ADVERTISING]

提供广告库存的站点, 例如内容发布者和服务提供商, 会间接受益于更高效的广告。 能够更好展示广告并产生广告主所寻求结果的广告场所, 可以对广告位收取更高费用。

通过投放广告获得支持的站点, 能够更好地提供优质内容或服务。 重要的是,这种支持来自其受众的方式并不均匀。 与其他形式的资金支持相比,这可能更加公平。 那些对广告商品消费倾向或能力较低的人, 可以获得与有能力付费的人相同的广告支持内容和服务。[EU-AD][COPPACALYPSE]

提供由广告支持的“免费”服务的能力 具有可衡量的经济收益, 这些收益源自这些服务的价值。[FREE-GDP]

1.5. 集体隐私效应

如果正确实现,聚合的使用可确保提供给站点的信息 是关于群体而非个人的信息。

因此,该机制的引入代表了一种集体决策, 符合集体隐私的理念。

当参与群体更大时, 参与归因衡量所带来的隐私成本更低。 这是由于聚合会影响站点 从聚合结果中提取有关个人信息的能力。 对于中心化差分隐私尤其如此, 它是本规范所用隐私设计的数学基础。

更大的参与者群组还会产生更具代表性——因而也更有用——的 关于所衡量广告的统计信息。

如果归因是正当的, 这两个因素都会推动为所有用户启用归因。

用户代理采取行动启用归因衡量, 对某些人来说不会受到积极接受。 不同的人对参与广告所带来的成本和收益 有不同感受。 所提出的设计允许人们选择看起来参与了归因, 而不会向站点暴露这一选择;参见 § 10.2 禁用 Attribution API

1.6. 使用直方图进行归因

归因 试图衡量一个或多个广告投放(展示) 与广告主期望的结果之间的相关性。

在聚合层面考虑时, 关于个人的信息并无用处。 操作和结果需要被分组。

最简单的归因形式根据广告的属性 将展示划分为若干分组, 并统计转化次数。 分组可能由以下属性形成: 广告展示的位置、 展示的内容(“创意”)、 广告展示的时间, 或展示给谁。

这些分组 以及归因到每个分组的转化计数 构成一个直方图。 直方图的每个桶统计 某一组广告的转化次数。

example.com news.example classified.example search.example
转化计数的示例直方图, 按展示所在站点分组

不同的分组可用于不同目的。 例如,按创意(广告内容)分组 可用于了解哪个创意效果最好。

在每次转化时添加一个大于一的值, 可以支持不只是简单计数的功能。 直方图还可以聚合值, 这可用于区分不同结果。 分配给展示的值 称为转化 值。 较高的转化值可用于较大的购买, 或任何价值更高的结果。 转化值也可以在多个展示之间拆分, 以分摊功劳。

2. 操作概述

Attribution API 提供关于两类事件之间关联的聚合信息: 展示转化

展示是广告主在任何网站上执行的任何操作。 此 API 不限制可记录为展示的内容。 广告主可能希望衡量的典型操作包括:

对于此 API,转化是正在衡量的结果。 此 API 不限制什么可以被视为结果。 广告主可能希望衡量的典型结果包括:

本节其余部分描述 Attribution API 如何与聚合服务 结合运作, 以生成聚合归因衡量结果。 该操作如下面的图所示。

| | | Advertiser | | Aggregation | | Server | | Service | | |<-----------+ | +--------------+ Histogram +-------------+ ^ ^ ^ Conversion | | | Reports | | '-----------. | '-----------. | | | | +-------------+-+-+ +---------+----+ | | | | | | | | Other Users | Publisher | | | | Advertiser | | Site(s) | | | | Site | | | | | | | +------+------+-+-+ +-----+--------+ | | ^ saveImpression | measureConversion | | Conversion | | | Report v v | +-------------------------------------+---------+ | | | Private Attribution APIs | | | +-----------------------------------------------+ ^ | v .-----------. | | | Impression | | Store | | | '-----------' ]]> 转化 报告 广告主 聚合 服务器 服务 直方图 转化 报告 其他用户 发布者 广告主 站点 站点 saveImpression measureConversion 转化 报告 Private Attribution APIs 展示 存储
归因操作概述

当一个展示发生时, 可以使用 saveImpression() 方法 请求浏览器保存信息。 这包括该展示的一个标识符, 以及关于该展示的一些附加信息。 例如,广告主可能会使用附加信息 来记录该展示是广告浏览还是广告点击。

转化时,会创建一个转化报告转化报告 是一个加密的直方图贡献, 其中包含来自浏览器先前存储的任何展示的信息。

measureConversion() 方法接受一个受限查询, 该查询用于 告诉浏览器如何构造一个转化报告。 其中包括用于从浏览器已存储的展示中进行选择的值, 分配给所选展示的转化值, 以及构造该转化报告所需的其他信息。

转化报告创建的直方图按如下方式构造:

浏览器会更新隐私预算存储,以反映已报告的转化。

生成的直方图会根据所选聚合服务的要求 为聚合做好准备,并返回给站点。 这至少涉及对直方图进行加密。

调用此 API 的站点将始终收到有效的转化报告。 因此,站点不会通过此交互了解到其他站点上发生了什么。

站点可以收集它从对此 API 的调用中收到的加密直方图, 并将它们提交给聚合服务。

在从站点收到一组加密直方图后,聚合服务会:

  1. 确认它之前没有 根据所提供的输入 计算过聚合结果, 并且转化报告数量足够,

  2. 将直方图相加,并加入足够的噪声, 以生成一个具有差分隐私保护的聚合直方图,并且

  3. 将聚合结果返回给站点。

我们将最终输出称为归因结果

3. API 使用

使用 Attribution API 的站点通常会注册 展示转化,但在某些情况下, 同一站点可能 两者都做。

要注册一次展示,站点调用 saveImpression()。除收集参数值外, 使用此 API 不需要任何准备,不过 在决定是否使用 Attribution API 时,检查受支持的 aggregationServices 可能很有用。

也可以在向用户代理提供资源时, 通过在 HTTP 响应中包含 `Save-Impression` 标头来注册一次展示。

要请求转化报告,站点调用 measureConversion()。 在调用此 API 之前,站点必须 选择一个受支持的聚合服务。 页面可以从 aggregationServices 中找到的受支持服务中选择任意一个。 所选服务的名称必须在调用 measureConversion() 方法时, 作为 aggregationService 成员提供给 AttributionConversionOptions 字典。

3.1. 站点身份

此 API 依赖 HTML 对站点的定义, 并将其作为其操作所围绕的主要作用域。 它识别三类站点:

此 API 使用站点 而不是, 因为它依赖于将所有可能具有隐私后果的活动 与单个实体关联起来。 像 cookie 这样的功能允许 同站 自由交换隐私相关信息, 否则这些信息可能被用来超出隐私预算

此 API 的所有功能都附加到 navigator.attribution 属性。

partial interface Navigator {
  [SecureContext, SameObject] readonly attribute Attribution attribution;
};

这提供了三个关键功能:

3.3. 查找受支持的聚合服务

aggregationServices 属性 包含用户代理支持的一组聚合服务。页面 在调用 measureConversion() 方法时, 必须选择并指定其中一个服务。 在注册展示之前查询受支持的服务 也可能有用, 但这不是必需的, 且展示并不限定于单个聚合服务。

站点可能会有一个 它所使用的聚合服务偏好顺序。 以下代码会遍历偏好列表, 并找到一个用户代理支持的服务。

const preferredServices = [
  "https://aggregator.example/tee",
  "https://aggregator.example/dap",
  "https://example.com/aggregator",
];
const supportedServices = navigator.attribution?.aggregationServices;
const serviceUrl = preferredServices.find(url => supportedServices?.has(url));

如果用户代理支持该 URL, 且其中包含一个偏好服务, 则第一个偏好服务会被保存到 名为 serviceUrl 的变量中。 否则,serviceUrl 将保持为 undefined

enum AttributionAggregationProtocol { "dap-18-histogram" };

dictionary AttributionAggregationService {
  required AttributionAggregationProtocol protocol;
};

[SecureContext, Exposed=Window]
interface AttributionAggregationServices {
  readonly maplike<USVString, AttributionAggregationService>;
};

[SecureContext, Exposed=Window]
interface Attribution {
  readonly attribute AttributionAggregationServices aggregationServices;
};

aggregationServices 属性是 从用于标识聚合服务的 URL 到 该服务元数据的映射:

protocol类型为 AttributionAggregationProtocol
聚合服务所使用的 protocol。 同一协议的不同版本使用不同的值。 即使单个服务提供方支持多个协议, 每个协议也需要使用不同的 URL。 这确保每个协议都可以通过 URL 被唯一标识, 而无需同时指定协议选择。

该 URL 会作为 aggregationService 参数传递给 measureConversion(), 以选择所标识的聚合服务。

AttributionAggregationProtocol 描述 不同聚合服务所使用的提交协议。本文档定义了两个协议:

dap-18-histogram
一种基于 DAP 的协议 [DAP],它使用 MPC;见 § 7.1 多方 计算聚合

3.4. 保存展示

saveImpression() 方法请求 用户代理展示存储中记录一次展示

为广告主展示广告的站点 可以保存一次展示。

在这种情况下,站点会直接保存展示, 标识广告主(advertiser.example), 并包含由广告主协商的信息。 在以下示例中, 这包括广告主稍后可能用于选择此广告的 matchValue 值(2)、 用于包含任何已归因值的直方图索引(histogramIndex = 3), 以及一个至少与广告主要求一样长的保留期(lifetimeDays = 7)。

navigator.attribution.saveImpression({
  histogramIndex: 3,
  matchValue: 2,
  conversionSites: ["advertiser.example"],
  lifetimeDays: 7,
});

或者,中介方, 例如供应方平台(SSP)或需求方平台(DSP), 可以从 iframe 调用同一 API。 从一个框架进行同一 API 调用, 会导致随展示一起保存中介方站点身份。

dictionary AttributionImpressionOptions {
  required unsigned long histogramIndex;
  unsigned long matchValue = 0;
  sequence<USVString> conversionSites = [];
  sequence<USVString> conversionCallers = [];
  unsigned long lifetimeDays = 30;
  long priority = 0;
};

dictionary AttributionImpressionResult {
};

[SecureContext, Exposed=Window]
partial interface Attribution {
  Promise<AttributionImpressionResult> saveImpression(AttributionImpressionOptions options);
};

saveImpression() 的参数如下:

histogramIndex类型为 unsigned long
如果 measureConversion() 将此 展示与后续转化匹配,则转化值 将被添加到由此索引标识的直方图桶中。
matchValue类型为 unsigned long,默认为 0
与展示关联的一段可选元数据。该值 可用于识别哪些展示可以从某次转化接收归因。
conversionSites类型为 sequence<USVString>,默认为 []
此展示的转化 可能发生的顶级转化 站点, 由它们的域名标识。 measureConversion() 方法 只有在由所指示站点之一调用时才会归因到此展示。 如果为空,则任何转化 站点都会匹配。
conversionCallers 类型为 sequence<USVString>, 默认为 []
能够为转化选择此展示的中介方 站点转化站点, 由它们的域名标识。 measureConversion() 方法 只有在由所指示站点之一调用时才会归因到此展示。 此选项同时包括转化站点中介方站点。 如果为空,则调用此 API 的任何站点都会匹配。
lifetimeDays类型为 unsigned long,默认为 30
一个正的“生存时间”(以天为单位),在该时间之后,展示将不再能够 接收归因。 用户代理应对生命周期施加上限, 并在此处指定的值超过该限制时静默减小该值。
priority类型为 long,默认为 0
一个整数,用于在归因期间对展示进行排序。

3.5. 请求对转化进行归因

measureConversion() 方法请求 用户代理对某次转化执行归因, 并返回一个转化 报告

measureConversion() 方法 始终返回转化报告, 无论是否找到匹配的展示。 如果没有匹配项,或者差分隐私不允许 报告归因,则返回的转化报告不会 对直方图作出贡献,即会全为零。

观察到某次转化的站点 可能会选择请求衡量 不同已存储展示的效果。

为了请求创建加密的衡量结果, 站点会调用 measureConversion() 方法。

此函数接受四种不同类型的输入:

  1. 所选聚合服务, 该服务使用 URL 标识。 选择聚合服务的示例过程 展示了如何选择浏览器支持的服务。

    const serviceDetails = {
      aggregationService: serviceUrl,
    };
    
  2. 聚合衡量的详细信息。 这些值在多个浏览器对 API 的所有调用中 都将保持一致。 这包括直方图的大小 以及可能已消耗的隐私预算量。

    const aggregatedMeasurementDetails = {
      histogramSize: 20,
      epsilon: 1,
    };
    
  3. 一组属性, 全部都是可选的, 用于选择要考虑的展示。 这包括展示可以有多旧 (lookbackDays)、 可能已保存展示的展示 站点impressionSites)、 可能已保存展示的中介方站点impressionCallers), 以及 matchValues 的选择。

    const selectionDetails = {
      lookbackDays: 14,
      impressionSites: ["publisher.example", "other.example"],
      impressionCallers: ["ad-tech.example"],
      matchValues: [2],
    };
    
  4. 归因 逻辑参数。

    const attributionDetails = {
      // top impression's histogram index gets 50% of value, the next two 25% each
      credit: [.5, .25, .25],
      value: 3,
      maxValue: 7,
    };
    

一旦这些值确定, 站点就会调用 API 以获得一个加密的转化报告

const measurement = await navigator.attribution.measureConversion({
  ...serviceDetails,
  ...aggregatedMeasurementDetails,
  ...selectionDetails,
  ...attributionDetails,
});
sendReportToServer(measurement.report);

报告可以被 收集, 并与来自此浏览器和其他浏览器的其他报告一起收集。 随后,收集到的报告可以全部提交给聚合服务, 以获得聚合直方图

dictionary AttributionConversionOptions {
  required USVString aggregationService;
  double epsilon = 1.0;

  required unsigned long histogramSize;

  unsigned long lookbackDays;
  sequence<unsigned long> matchValues = [];
  sequence<USVString> impressionSites = [];
  sequence<USVString> impressionCallers = [];

  sequence<double> credit;
  unsigned long value = 1;
  unsigned long maxValue = 1;
};

dictionary AttributionConversionResult {
  required Uint8Array report;
};

[SecureContext, Exposed=Window]
partial interface Attribution {
  Promise<AttributionConversionResult> measureConversion(AttributionConversionOptions options);
};

measureConversion() 的参数如下:

aggregationService类型为 USVString
aggregationServices 中可找到的聚合服务中作出的选择。
epsilon类型为 double,默认为 1.0
要在此转化报告上消耗的隐私 预算量。
histogramSize类型为 unsigned long
转化报告中使用的直方图桶数量。
lookbackDays类型为 unsigned long
正整数天数。只有在过去 lookbackDays 天内发生的展示才可以匹配此转化。如果 省略,则等同于最大回溯期
matchValues类型为 sequence<unsigned long>,默认为 []
一组可用于选择此展示的匹配 值集合
impressionSites类型为 sequence<USVString>,默认为 []
一组展示站点集合。 只有在展示站点 属于此集合的位置记录的展示 才有资格匹配此转化。 如果为空,则任何站点都会匹配。
impressionCallers 类型为 sequence<USVString>,默认为 []
一组站点集合, 既包括展示站点 也包括中介方 站点, 它们可能已调用 saveImpression() API。 如果非空, 只有由所列站点之一记录的展示 才有资格匹配此转化
credit类型为 sequence<double>
一个数字列表
value类型为 unsigned long,默认为 1
转化 值。如果作出了归因且隐私 限制得到满足,则该值将被编码到转化报告中。
maxValue类型为 unsigned long,默认为 1
聚合中包含的所有贡献上的最大转化 值。 与 epsilon 一起,它用于校准将添加到结果中的随机噪声分布。 它还用于确定要在此转化报告上消耗的隐私预算量。

3.6. 中介方的角色

此 API 支持中介方 代表顶级站点进行操作。 广告经常委托给负责投放、竞价和衡量的独立运营方。

由中介方保存的展示 会记录中介方站点的身份。 在为转化衡量选择展示时, 可以使用中介方站点 身份来选择展示。

3.7. 直方图构造

从概念上讲,每个已保存的展示 都有一个单一的直方图定义。 每个展示都有一个单一的直方图索引属性, 用于确定分配给该展示所得直方图中出现的位置。

因此,每次调用 measureConversion() 都需要选择具有相同直方图定义的展示。 尽管这适用于 API 的所有使用, 但当展示 由多个中介方保存衡量时, 一致定义直方图尤其重要。

调用 measureConversion() 时可能被选择的所有展示 都需要使用相同的直方图定义。 此 API 提供了几种工具, 用于确保只选择正确的展示

对于已保存的展示

作为转化通用 匹配逻辑的一部分:

这些选项为站点在归因如何选择直方图方面提供了灵活性。 它不排除转化站点使用不同直方图。 可以保存具有不同直方图定义的多个展示, 前提是 measureConversion() 调用 永远不会选择 具有不同直方图定义的展示。 这确保可以通过多次调用 measureConversion(), 将转化归因到 多个直方图。

3.8. 权限策略集成

委托给中介方的能力 由权限策略控制。

本规范定义了两个策略控制特性

这两个特性的默认允许列表 都是 *

saveImpression()measureConversion() 分别设置权限, 允许同时执行两者的页面将子资源 限制为预期类型的活动。

默认启用权限 简化了集成外部服务的任务。

权限策略只提供全有或全无的控制; 它不支持委托部分隐私预算。

4. API 内部机制

4.1. 展示存储

展示存储measureConversion() 方法用于查找匹配的 展示

尽管此 API 允许站点存储数据, 展示存储 并不使用存储键

4.1.1. 内容

展示存储是一组 集合,其元素为展示

匹配值传递给 saveImpression()matchValue
展示站点调用 saveImpression()展示 站点
中介方站点调用 saveImpression()中介方站点, 或者如果 API 由展示站点调用,则为 undefined
转化站点传递给 saveImpression()集合,其元素为转化站点
转化调用方一组站点集合, 这些站点可以是转化站点中介方站点, 它们可在调用 measureConversion() 时选择此展示
时间戳调用 saveImpression() 的时间。
生命周期展示保持有资格接收归因的持续时间,该持续时间来自 saveImpression() 调用,或来自用户代理定义的限制。
直方图索引传递给 saveImpression() 的直方图索引。
优先级一个整数,用于在归因期间对展示进行排序。

4.1.2. 维护

用户 代理应定期使用 时间戳生命周期值 来识别并删除展示存储中 任何已过期的展示

无需在展示到期后立即移除它们, 只要 measureConversion() 会将已过期的展示排除在 归因之外即可。 但是, 用户 代理不应无限期保留已过期的展示

4.1.3. Clear-Site-Data 集成

`Clear-Site-Data` 字段 [CLEAR-SITE-DATA] 赋予站点移除用户代理维护状态的能力。 `"impressions"` 类型被添加到已识别类型列表中, 该列表定义于 Clear Site Data § 3.1 Clear-Site-Data HTTP 响应标头字段

当调用 clear site data for response 算法时, 如果类型列表包含 `"impressions"`, 则调用 clear impressions for a site, 并传入 origin

为站点清除 展示, 给定一个 origin, 运行以下步骤:
  1. 如果 origin 不是元组源,则返回。

  2. site 为通过调用获得可注册域所返回的值, 并传入 origin主机部分。

  3. 对于展示 存储的每个展示 impression执行以下操作

    1. 如果 impression中介方站点undefined,且 其展示站点等于 site, 则从展示存储移除 impression继续

    2. 如果 impression 有一个等于 site中介方站点, 则从展示存储移除 impression继续

    3. 如果 impression转化站点包含 site

      1. impression转化站点移除 site

      2. 如果 impression转化站点为空, 则从展示存储移除 impression继续

    4. 如果 impression转化调用方包含 site

      1. impression转化调用方移除 site

      2. 如果 impression转化调用方为空, 则从展示存储移除 impression继续

此过程不会移除那些 使用空集合转化站点保存的展示。

4.1.4. 站点名称

展示存储 会保存关于三类站点的信息: 展示站点、 一个可选的中介方站点, 以及一组集合,其元素为转化站点

这些站点必须全部 采用scheme-and-host 形式, 并使用 "https" 方案。 这意味着,对主机 进行简单字符串序列化就足以标识该站点。 因此,此 API 能够使用简单的字符串 来表示站点

实现也可以只使用元组的主机部分 在内部表示站点。

解析站点, 返回站点或失败, 给定一个字符串 input, 运行以下步骤:
  1. host 为调用主机解析器并传入 input 所返回的值。

  2. 如果 host 为失败,则返回失败。

  3. site 为调用获取可注册域并传入 host 所返回的值。

  4. 如果 site 为 null,则返回失败。

  5. 如果 site 为 "localhost",或者如果 site ".localhost" 结尾, 则返回失败。

  6. 返回一个 ("https", site) 的方案和主机元组。

对于所含域标签数量多于可注册域的字符串, 此算法也能成功生成一个站点。 例如,"extra.example.com" 会被解析为 "example.com"。

此算法不接受 localhost 域 [RFC6761], 因此,任何依赖提取站点名称的算法在提到 localhost 域时, 或者当前站点(顶级站点或被框架嵌入的站点)是 localhost 域时, 都会失败。 这会使使用本地服务器进行测试和开发变得困难。 实现可以提供一个禁用 localhost 检查的配置, 以帮助测试和开发。

4.2. 用于隐私预算管理的状态

用户 代理会维护若干状态, 这些状态用于管理隐私预算的消耗:

隐私预算 存储全局隐私预算存储展示站点配额存储扣减隐私和安全预算更新。

展示 存储一样, 隐私预算 存储和相关存储不使用存储键。 这些存储在如何清除信息方面有一些额外约束; 详见 § 10.7 清除 API 状态

归因预算锁定义为布尔标志的选择 是出于规范编写便利。 实现可能更适合使用替代构造。 实现可能能够对此值进行分区, 例如按纪元分区, 以减小任何争用的范围。

4.2.1. 隐私预算存储

隐私预算键 是一个元组, 由以下项目组成:

epoch index

一个纪元索引

site

一个站点

隐私预算 存储是一个映射,其键为 隐私预算键, 其值为32 位无符号整数。 这些整数微 epsilon为单位存储值。 一个微 epsilon是 差分隐私 [DP] 中使用的单位 epsilon 值的 百万分之一。

选择 32 位整数会将 epsilon 的设置限制为 小于或等于 4294 的最大 epsilon。 对实现来说,这应该绰绰有余。

全局 隐私预算存储是一个映射,其键为 纪元索引,其值为 以微 epsilon为单位的 32 位无符号整数

全局隐私预算存储跟踪单一 隐私预算的消耗, 该预算适用于所有站点, 并在每个纪元刷新。 这提供了一个安全限制, 用于抵御能够跨多个站点 关联同一个人活动的对手。

不同于按站点划分的隐私预算存储全局隐私预算存储只以纪元索引为键, 而不是以站点为键。

展示 站点配额存储是一个映射,其键为 隐私预算键, 其值为以微 epsilon为单位的 32 位无符号整数

展示站点配额存储限制任何单个展示 站点在一个纪元中能够贡献的“存量” (与展示相关的隐私预算)。 这可防止单个展示站点 从可能被恶意触发的全局限制中 消耗过多额度。

扣减 隐私和安全预算, 给定一个隐私预算 键 key、 一个集合,其元素为展示 impressionsdouble epsilon、 整数 value、 整数 maxValue、 布尔值 isSingleEpoch、 整数 l1Norm、 一个集合,其元素为隐私预算键 deductedImpressionQuotas 和一个集合,其元素为纪元索引 deductedGlobalBudgets
  1. 如果 isSingleEpoch,令 l1NormSensitivityl1Norm,否则为 2 * value

  2. valueSensitivity 为 2 * value

  3. noiseScale 为 2 * maxValue / epsilon

  4. l1NormDeductionFpl1NormSensitivity / noiseScale

  5. valueDeductionFpvalueSensitivity / noiseScale

    单纪元归因 不会跨纪元产生任何级联效应。 涉及多个纪元的归因会消耗双倍预算, 因为一次变化有可能影响跨纪元的归因。 加倍扣减假定会向聚合直方图添加 与 maxValue / epsilon 成比例的 Laplace 噪声。

  6. l1NormDeductionl1NormDeductionFp * 1000000,并向正 Infinity 舍入。

  7. valueDeductionvalueDeductionFp * 1000000,并向正 Infinity 舍入。

  8. 如果归因预算锁为 true, 则等待该值变为 false, 然后将该值设置为 true。

  9. 如果使用 keyl1NormDeductionvalueDeductionimpressionsisSingleEpoch 调用检查可用隐私预算 的结果为 false,则执行以下步骤:

    1. 归因预算锁设置为 false。

    2. 返回 false。

  10. 所有预算检查均已通过,因此执行扣减:

    1. 如果 isSingleEpoch,令 deductionl1NormDeduction,否则 令 deductionvalueDeduction

    2. currentValue 为在隐私预算存储获取 key 的值的结果, 默认值为按站点隐私预算

    3. 隐私预算存储key 的值设置currentValuededuction

    4. epochkey纪元索引组成部分。

    5. 如果 deductedGlobalBudgets包含 epoch, 则将 epoch 追加deductedGlobalBudgets, 并将全局隐私预算 存储[epoch] 减少 valueDeduction

    6. 对于 impressions 中的每个 impression执行以下操作

      1. impressionSiteimpression展示站点

      2. impressionQuotaKey 为一个隐私预算 键, 其项目为 epochimpressionSite

        以下步骤确保当同一站点存在多个展示时, 不会从同一展示站点配额中扣减预算超过一次。

      3. 如果 deductedImpressionQuotas包含 impressionQuotaKey

        1. impressionQuotaKey 追加deductedImpressionQuotas

        2. currentImpressionQuotaValue 为在每纪元展示站点配额获取 impressionQuotaKey 的值的结果, 默认值为每纪元展示站点 配额

        3. 每纪元展示站点配额[impressionQuotaKey\] 的值设置currentImpressionQuotaValuevalueDeduction

  11. 归因预算锁设置为 false。

  12. 返回 true。

检查 可用隐私预算, 给定一个隐私预算 键 key、整数 l1NormDeduction、 整数 valueDeduction、 一个集合,其元素为展示 impressions 和布尔值 isSingleEpoch
  1. 如果 isSingleEpoch,令 deductionl1NormDeduction,否则令 deductionvalueDeduction

  2. currentValue 设置为从隐私预算存储获取 key 的值, 默认值为按站点隐私预算

  3. 如果 deduction 大于 currentValue,则返回 false。

  4. epochkey纪元索引组成部分。

  5. currentGlobalValue 设置为从全局隐私预算存储获取 epoch 的值, 默认值为每纪元全局隐私预算

  6. 如果 valueDeduction 大于 currentGlobalValue,则返回 false。

  7. 对于 impressions 中的每个 impression执行以下操作

    1. impressionSiteimpression展示站点

    2. impressionQuotaKey 为一个隐私预算键, 其项目为 epochimpressionSite

    3. currentImpressionQuotaValue 设置为从展示站点配额存储获取 impressionQuotaKey 的值,默认值为 每纪元展示站点配额

    4. 如果 valueDeduction 大于 currentImpressionQuotaValue, 则返回 false。

  8. 返回 true。

4.2.2. Attribution API 激活

Attribution API 大致以消耗瞬态激活的 API 为模型, 在这些 API 中,用户激活 会暂时使 API 可用。 有若干差异将此设计 与消耗瞬态激活的 API 区分开来:

这在效果上大体类似于瞬态激活。 但是,归因激活使用与瞬态激活 分离的状态, 并且该状态以不同方式跟踪。 归因激活状态在顶级可遍历对象上跟踪, 而不是在受影响的 Window 上跟踪。 因此,归因激活会在导航之间持续存在, 从而在激活导致导航的情况下, 能够在加载新页面后的一小段时间内 使用此 API。

拥有独立状态可确保 归因激活不会与消耗瞬态激活的 API 发生交互。 一个消耗激活的 API 不会阻止 Attribution API 可用; 同样,使用 Attribution API 也不会阻止 一个消耗瞬态激活的 API 可用。

独立的状态跟踪可确保 那些消耗用户激活的用户动作 能够由 Attribution API 独立测量。

在导航之间保留激活支持广告中的常见模式。 站点可以使用 Attribution API 检查 交互发生所在站点上的动作, 或后续站点上的动作。

为实现这一点, 每个顶级 可遍历对象都会为 Attribution API 跟踪两项状态:

  1. 归因启用标志是一个布尔值, 用于跟踪此 API 是否已启用。 此值初始化为 false。

  2. 归因激活时间戳是一个时刻, 用于跟踪上一次用户激活。 此值初始化为 Unix 纪元

实现还会将归因激活持续时间 配置为一个实现定义的持续时间。 这不应小于瞬态激活持续时间, 但为了确保导航造成的延迟 不会使 Attribution API 变得不可访问, 更大的值可能是可取的。

实现可能会选择延长允许的时间, 以计入页面加载时间所涉及的延迟。 固定值可能无法反映设备 或其所用网络中的性能差异。 实现可以基于对性能特性的理解, 扩展归因激活持续时间的值。 或者,实现可以在页面加载期间暂停任何计时器。

当用户交互导致在 Document document 中触发激活触发输入事件时, 用户代理必须执行以下步骤——除激活通知步骤之外——并且要在分派该事件之前执行。 在这种情况下,将可导航对象 navigable 设置为 null。

或者,当导航开始, 且用户导航参与"browser UI" 时, 执行以下步骤, 将 navigable 设置为受影响的可导航对象, 并将 document 设置为 null。

步骤为:

  1. 如果 navigable 不为 null,则令 nnavigable

  2. 否则,令 n 为获取 document节点可导航对象的结果。

  3. top 为获取 n顶级 可遍历对象的结果。

  4. top归因激活时间戳 设置为当前高分辨率时间

当一个顶级 可遍历对象 top导航时, 作为导航算法的一部分, 在文档状态 documentState 已确定, 并且响应 responseOrigin 已知之后, 执行以下步骤:
  1. 如果 documentState发起者源responseOrigin同站,则返回。

  2. top归因启用标志设置为 false。

检查 Attribution API 激活, 给定一个 Document document, 并在失败时抛出 "NotAllowedError" DOMException
  1. n 为获取 document节点可导航对象的结果。

  2. top 为获取 n顶级 可遍历对象的结果。

  3. 如果 top归因启用标志为 true,则返回。

  4. lastActivationtop归因激活时间戳

  5. 如果 lastActivation 加上归因激活持续时间 小于当前高分辨率时间, 则抛出 "NotAllowedError" DOMException

  6. top归因启用标志设置为 true。

4.2.3. 纪元开始时间

隐私预算周期(或周期) 标识一段时间。 一个周期的长度固定为一周或 7 , 其中定义为 86400 秒。

周期开始时间 是来自挂钟的一个时刻。 对于每个用户代理,一个周期会在一周中随机选择的某个小时开始。 这确保了因隐私 预算达到零而在聚合中产生的任何偏差, 会在所有用户的所有贡献中被平均化。

在同一设备上, 所有隐私预算和配额 都会根据周期开始时间在同一时间刷新。

开始时间 由用户代理在首次需要周期时随机选择——作为调用 获取当前 周期算法的副作用。

周期索引是一个整数, 指代给定的周期周期索引用于访问 impression周期开始时间

正如一个时刻是一个抽象概念, 只能表示为相对于另一个时刻持续时间周期也是 抽象的。

周期索引作为 相对于某个设定参考点的整数 存储。 本规范中的周期索引 使用周期开始 时间 作为参考点。 用户代理可以选择使用不同的时刻 来表示“零”或参考周期

本规范中的算法全都使用具体的周期索引, 而不是更抽象的周期时间 点会使用获取当前 周期算法, 被转换为对应周期周期索引

要在给定一个时刻 t 的情况下获取当前 周期, 返回一个周期索引
  1. period 为一个周期持续时间

  2. 如果周期 开始时间未设置, 则按如下方式将其设置为在上一个周期内随机选择的一个小时:

    1. randt 减去一个持续时间, 该持续时间从 0(包含)到 period(不包含)之间 随机选择。

    2. ms 为从 Unix 纪元rand持续时间中的毫秒数。

    3. hourms 除以 3600000 (一小时的毫秒数) 向零舍入 然后乘以 3600000。

    4. 周期开始时间设置为 Unix 纪元 加上作为持续时间hour

  3. start周期开始时间

  4. elapsed 为 (tstart) / period

  5. elapsed 作为整数返回,并向负无穷舍入。

4.2.4. 上次清除浏览历史记录的时间

上次浏览 历史清除是一个使用挂钟时刻, 用于跟踪浏览历史最后一次被清除的时间。 当任何站点级状态 应用户请求被清除时, 上次浏览历史清除值会被更新 为当前粗化挂钟时间。 该值初始为未设置。

作为可选优化, 如果以下所有条件都为 true,则可以跳过更新上次浏览历史清除

如果这三个条件都为 true, 则不需要更新上次浏览历史清除。 相反,必须更新隐私 预算存储, 方法是为可以从每个受影响的站点周期 形成的所有隐私预算 键组合设置值 0 (使用对应的周期索引)。

此优化依赖于用户代理 已保留关于受影响站点 在受影响周期中交互的信息。 这之所以可行,只是因为任何被保留的交互 都可能已经导致预算耗尽。 重置预算是必要的, 以确保不会暴露关于浏览历史空缺的信息。

要在给定时刻 now 的情况下获取归因的起始周期, 返回一个周期索引
  1. earliestEpochIndex 为用 now最大回溯天数获取当前周期的结果。

    这确保可以查询所有可能的展示

  2. startEpochearliestEpochIndex

  3. 如果上次浏览历史清除已设置, 则执行以下步骤:

    1. clearEpoch 为用上次浏览历史清除的值获取当前 周期的结果。

      这里使用获取当前周期 可能会返回负值。 这是因为周期开始时间 很可能会被设置为浏览历史最后一次清除之后的时间。

    2. clearEpoch 设置为 clearEpoch + 1。

      加上是必要的,这样归因的周期范围 就不会与浏览历史被清除之前的周期 重叠。

    3. 如果 clearEpoch 大于 startEpoch, 则返回 clearEpoch

  4. 返回 startEpoch

清除归因的浏览历史, 给定一个由站点 sites 组成的集合, 一个布尔值 forgetVisits, 以及一个时刻 now
  1. 如果 forgetVisits 为 false:

    1. 断言sites 不是 空的

    2. sites 中的每个 site

      1. startingEpoch 为 在给定 now 的情况下调用获取归因的起始周期 的结果。

      2. currentEpoch 为 在给定 now 的情况下调用获取当前周期 的结果。

      3. 对从 startingEpochcurrentEpoch闭区间范围 中的每个 epoch

        1. key 为由 siteepoch 形成的隐私 预算键

        2. 隐私预算 存储[key] 设置为 0。

    3. 返回。

  2. 如果 sites 为空

    1. 清空展示存储

    2. 清空隐私预算 存储

    3. 清空展示站点配额存储

    4. 清空全局 隐私预算存储

  3. 如果 sites 不是空的

    1. 展示存储中的 每个 impression, 如果 sites 包含 impression展示站点, 则从展示存储移除 impression

    2. 隐私预算存储 中的每个 key, 如果 sites 包含 key站点组成部分, 则移除隐私预算 存储[key]。

    3. 展示站点配额存储 中的每个 key, 如果 sites 包含 key站点组成部分, 则移除展示站点配额 存储[key]。

      此过程不会触碰全局 隐私预算存储。 这主要是为了确保隐私预算 一旦被花费,就不会被遗忘。

  4. 上次浏览历史清除设置为 now

    在仅清除某些站点的状态时 (即,当 sites 不是 空的时) 设置上次浏览历史清除 会使不在该集合中的站点无法访问某些展示。 实现也可以移除任何不可用的展示 以及任何因此无法使用的预算记录 (例如全局隐私预算存储中的记录)。

4.3. 保存展示算法

saveImpression(options) 方法步骤 如下:
  1. implicitInputs 为从 this 获取 隐式 API 输入的结果。

  2. 断言implicitInputs 不为 null。

  3. 返回使用 optionsimplicitInputs 运行保存展示的结果。

要在给定 AttributionImpressionOptions options隐式 API 输入 implicitInputs 的情况下保存一个 展示
  1. documentimplicitInputs关联文档

  2. realmdocument相关领域

  3. 如果 document被允许使用名为 "save-impression" 的策略控制特性, 则返回在 realm 一个 "NotAllowedError" DOMException 拒绝的 promise。

  4. 在给定 document 的情况下检查 Attribution API 激活, 对任何抛出的原因返回以其拒绝的 promise

  5. 验证页面提供的 API 输入:

    1. 如果 options.histogramIndex 大于或等于实现定义最大直方图大小, 则返回在 realm一个 RangeError 拒绝的 promise。

    2. 如果 options.lifetimeDays 为 0, 则返回在 realm一个 RangeError 拒绝的 promise。

    3. options.lifetimeDays 钳制到 最大回溯

    4. 如果 options.conversionSites大小 大于实现定义每个展示的最大 转化站点数, 则返回在 realm一个 RangeError 拒绝的 promise。

    5. conversionSites 为一个集合,它是 对 options.conversionSites 中的每个值 调用解析 站点 的结果。

    6. 如果 conversionSites 中有任何结果为失败,则返回在 realm一个 "SyntaxError" DOMException 拒绝的 promise。

    7. 如果 options.conversionCallers大小 大于实现定义每个展示的最大 转化调用方数, 则返回在 realm一个 RangeError 拒绝的 promise。

    8. conversionCallers 为一个集合,它是 对 options.conversionCallers 中的每个值 调用解析站点 的结果。

    9. 如果 conversionCallers 中有任何结果为失败,则返回在 realm一个 "SyntaxError" DOMException 拒绝的 promise。

  6. 并行运行以下步骤:

    1. impression 构造为一个已保存的展示,由以下内容组成:

      匹配值

      options.matchValue

      展示站点

      implicitInputs顶级站点

      中介站点

      implicitInputs中介站点

      转化站点

      conversionSites

      转化调用方

      conversionCallers

      时间戳

      implicitInputs时间戳

      生命周期

      options.lifetimeDays

      直方图索引

      options.histogramIndex

      优先级

      options.priority

    2. 如果 Attribution API 已启用, 则将 impression 保存到展示存储

  7. result 为一个新的 AttributionImpressionResult

  8. 返回在 realm result 兑现的 promise。

saveImpression() 不返回指示该展示是否被记录的状态。 这会最大限度地降低检测 Attribution API 是否已禁用的能力。

实现必须尝试缓解可能暴露 API 状态的侧信道。 例如,返回的 promise 的兑现 不以将 impression 保存到展示存储为前提,以确保 兑现所需时间不依赖于 现有展示的数量或 API 是否已启用。

隐式 API 输入是一个具有以下字段的结构体

顶级站点一个站点
中介站点一个站点undefined
时间戳一个时刻
关联文档一个 Document
要在给定 领域 realm 以及 可选的(默认为 null)的情况下,从 realm 获取 隐式 API 输入
  1. windowrealm全局对象

  2. 如果 window 不是一个 Window, 则返回 null。

  3. settingsrealm设置对象

  4. timestampsettings当前挂钟时间

  5. topLevelOriginsettings顶级源

  6. 如果 origin 为 null,则将 origin 设置为 settings

  7. topLevelSite 为从 topLevelOrigin 获取 站点的结果。

  8. intermediarySite 为:

    1. 如果 origintopLevelOrigin 同站, 则为 undefined 值,

    2. 否则,为从 origin 获取站点的结果。

  9. 返回一个具有以下字段的隐式 API 输入

    顶级站点

    topLevelSite

    中介站点

    intermediarySite

    时间戳

    timestamp

    关联文档

    window关联文档

4.4. 衡量转化算法

measureConversion() 方法异步完成, 在 Attribution 任务源上排队工作。

measureConversion(options) 方法 步骤为:
  1. implicitInputs 为从 this 获取隐式 API 输入的结果。

  2. 断言implicitInputs 不为 null。

  3. 返回用 optionsimplicitInputs 运行测量一次转化的结果。

要在给定 AttributionConversionOptions options隐式 API 输入 implicitInputs 的情况下测量一次 转化
  1. documentimplicitInputs关联文档

  2. realmdocument相关领域

  3. 如果 document被允许使用名为 "measure-conversion" 的策略控制特性, 则返回在 realm 一个 "NotAllowedError" DOMException 拒绝的 promise。

  4. 检查归因 API 激活 给定 document,返回 一个被拒绝的 promise,其拒绝原因是 任何抛出的原因。

  5. validatedOptions验证 options 的结果, 对任何抛出的原因返回以其拒绝的 promise

  6. promiserealm一个新的 promise

  7. 并行运行以下步骤:

    1. report 为用 validatedOptions直方图大小调用创建一个全零直方图的结果。

    2. 如果 Attribution API 已启用, 则将 report 设置为用 validatedOptionsimplicitInputs顶级站点implicitInputs中介站点以及 implicitInputs时间戳 运行执行归因并填充 直方图的结果。

    3. aggregationServicevalidatedOptions聚合 服务

    4. 切换 aggregationService.protocol 的值:

      dap-18-histogram

      执行以下步骤:

      1. encryptedReport 为调用构造 DAP 报告并给定 validatedOptionsimplicitInputs顶级站点implicitInputs中介 站点implicitInputs时间戳,以及 report 所得的结果。

    5. result 为一个具有以下项的 AttributionConversionResult

      report

      encryptedReport

    6. Attribution 任务源排队一个任务, 以用 result 兑现 promise

  8. 返回 promise

实现必须尝试缓解可能暴露 API 状态的侧信道。 例如,理想情况下,返回的 promise 的兑现所需时间 不应依赖于已存储或匹配的展示数量 或 API 是否已启用。

已验证的 转化选项是一个具有以下字段的结构体

聚合 服务一个 AttributionAggregationService 实例。
Epsilon一个有限正数。
直方图大小一个32 位无符号整数
回溯一个正持续时间
匹配值一个由32 位无符号整数组成的集合
展示站点一个由站点组成的集合
展示 调用方一个由站点组成的集合
权重一个由数字组成的列表
一个32 位无符号整数
最大值一个32 位无符号整数
验证 AttributionConversionOptions options
  1. 如果 aggregationServices包含 一个条目,其options.aggregationService, 则抛出 ReferenceError

  2. aggregationService 为从 AttributionAggregationServices 获取值的结果, 给定 options.aggregationService

  3. 如果 options.epsilon 小于或等于 0,或者大于最大 epsilon, 则抛出 RangeError

  4. 如果 options.histogramSize 为 0,或者大于实现定义最大直方图 大小, 或者大于 options.aggregationService最大聚合服务 直方图大小(如果有), 则抛出 RangeError

  5. 如果 options.value 为 0, 则抛出 RangeError

  6. 如果 options.value 大于 options.maxValue, 则抛出 RangeError

  7. 如果 options.credit 存在,则令 credit 为它,否则为 «1»。

  8. 如果 credit 为空,则抛出 RangeError

  9. 如果 credit 的任何小于或等于 0,则抛出 RangeError

  10. 如果 credit大小超过实现定义最大权重值数量,则抛出 RangeError

  11. 如果 options.lookbackDays 存在,则令 lookback 为其天数, 否则为最大回溯天数

  12. 如果 lookback 大于最大值,则将 lookback 设置为最大回溯天数

  13. 如果 lookback 为 0 ,则抛出 RangeError

  14. 如果 options.matchValues大小 大于实现定义最大 匹配值数量, 则抛出 RangeError

  15. matchValues 为用 options.matchValues 运行创建集合的结果。

  16. 如果 options.impressionSites大小大于 实现定义转化的最大展示 站点数, 则抛出 RangeError

  17. impressionSites 为一个集合,它是 对 options.impressionSites 中的每个值 调用解析 站点 的结果。

  18. 如果 impressionSites 中有任何结果为失败,则抛出一个 "SyntaxError" DOMException

  19. 如果 options.impressionCallers大小大于 实现定义转化的最大 展示调用方数, 则抛出 RangeError

  20. impressionCallers 为一个集合,它是 对 options.impressionCallers 中的每个值 调用解析 站点 的结果。

  21. 如果 impressionCallers 中有任何结果为失败,则抛出一个 "SyntaxError" DOMException

  22. 返回一个具有以下字段的已验证转化选项

    聚合服务

    aggregationService

    Epsilon

    options.epsilon

    直方图大小

    options.histogramSize

    回溯

    lookback

    匹配值

    matchValues

    展示站点

    impressionSites

    展示调用方

    impressionCallers

    权重

    credit

    options.value

    最大值

    options.maxValue

4.4.1. 归因逻辑

归因逻辑 确定转化值如何分配到直方图桶。

要在给定 已验证转化选项 options站点 topLevelSite站点undefined intermediarySite,以及 时刻 now 的情况下执行 归因并填充直方图
  1. currentEpoch 为使用 now 调用获取当前纪元 的结果。

  2. startEpoch 为使用 now 调用获取归因的起始 纪元 的结果。

  3. earliestEpoch 为调用获取当前纪元的结果, 并传入 (nowoptions回溯)。

  4. 如果 currentEpoch 等于 earliestEpoch,则令 isSingleEpoch 为 true,否则为 false。

  5. l1Norm 为 0。

  6. 如果 isSingleEpoch 为 true:

    1. impressions 为使用 optionstopLevelSiteintermediarySitecurrentEpochnow 调用通用匹配 逻辑的结果。

    2. 如果 impressions 为 空,则返回使用 options直方图大小 调用创建全零直方图的结果。

    3. histogram 为使用 impressionsoptions直方图大小optionsoptions功劳 调用使用最后 N 次触达归因 填充直方图的结果。

    4. l1Norm 设置为 histogram的和。

    5. 断言l1Norm 小于或等于 options

  7. deductedImpressionQuotas 为一个新的集合

  8. deductedGlobalBudgets 为一个新的集合

  9. matchedImpressions 为一个集合

  10. 对于从 startEpochcurrentEpoch(包含两端)的每个 epoch

    1. impressions 为使用 optionstopLevelSiteintermediarySiteepochnow 调用通用匹配 逻辑的结果。

      在单纪元情况下,这会重新计算 matchedImpressions。 实现会希望避免重复执行这项工作。

    2. 如果 impressions 非 空

      1. key 为一个隐私预算键,其项目为 epochtopLevelSite

      2. budgetAndSafetyOk 为使用 keyimpressionsoptionsepsilonoptionsoptions最大值isSingleEpochl1NormdeductedImpressionQuotasdeductedGlobalBudgets 调用扣减隐私和安全 预算的结果。

      3. 如果 budgetAndSafetyOk 为 true, 则用 impressions 扩展 matchedImpressions

  11. 如果 matchedImpressions 为 空,则返回使用 options直方图大小 调用创建全零直方图的结果。

  12. histogram 为使用 matchedImpressionsoptions直方图大小optionsoptions功劳 调用使用最后 N 次触达归因 填充直方图的结果。

  13. 返回 histogram

创建 全零直方图,给定整数 size
  1. 返回一个列表,其大小size,其全为 0。

4.4.2. 通用展示匹配逻辑

要执行通用 匹配逻辑,给定 已验证转化选项 options站点 topLevelSite站点undefined intermediarySite周期索引 epoch,以及 时刻 now
  1. matching 为一个 集合

  2. 对于展示存储中的每个 impression执行以下操作

    1. impressionEpoch 为调用获取当前 纪元的结果, 并传入 impression时间戳

    2. 如果 impressionEpoch 不等于 epoch,则继续

    3. 如果 now 晚于 impression时间戳 加上 impression生命周期, 则继续

    4. 如果 now 晚于 impression时间戳加上 options回溯, 则继续

    5. 如果 impression转化站点非空, 且不包含 topLevelSite, 则继续

    6. 如果 intermediarySite 不是 undefined, 则令 conversionCallerintermediarySite, 否则为 topLevelSite

    7. 如果 impression转化调用方非空, 且不包含 conversionCaller, 则继续

    8. 如果 options匹配值非空, 且不包含 impression匹配值, 则继续

    9. 如果 options展示站点 非空,并且 不包含 impression展示站点, 则继续

    10. 如果 impression中介方站点 不是 undefined,则令 impressionCaller 为它, 否则为 impression展示站点

    11. 如果 options展示调用方 非空, 且不包含 impressionCaller, 则继续

    12. impression 追加matching

  3. 返回 matching

4.4.2.1. 最后 N 次触达归因
公平分配 功劳,给定一个 double 列表 credit 和整数 value
  1. 断言credit 非空

  2. sumCreditcredit之和。

  3. roundedCredit 为一个新的列表

  4. 对于 credit 的每个 item执行以下操作

    1. normalizedCreditvalue * item / sumCredit

    2. normalizedCredit 追加roundedCredit

  5. idx1 为 0。

  6. 对于 roundedCredit索引中移除第一个后的每个 n执行以下操作

    1. idx2n

    2. frac1roundedCredit[idx1] − floor(roundedCredit[idx1])。

    3. frac2roundedCredit[idx2] − floor(roundedCredit[idx2])。

    4. 如果 frac1frac2 都等于零,则继续

    5. 如果 frac1 + frac2 大于 1,则令 incr1 为 1 − frac1,并令 incr2 为 1 − frac2

    6. 否则,令 incr1 为 −frac1,并令 incr2 为 −frac2

      incr1 表示要增加 roundedCredit[idx1] 的量,以使其成为整数; incr2idx2 也类似。 注意,这些值可以为负。

    7. p1incr2 / (incr1 + incr2)。

      p1 的值表示 idx1 中的被舍入为整数的概率。 当 incr1 + incr2 为 0 时会发生除以零, 这只有在 frac1frac2 都为整数(要么都恰好为 0,要么都恰好为 1)时才可能。在这种情况下,idx2 不需要 舍入,因此我们直接跳过它。

    8. r 为 0 到 1(包含两端)之间的随机 double。

    9. 如果 r 小于 p1,则令 incrincr1, 并交换 idx1idx2 的值。

    10. 否则,令 incrincr2

    11. roundedCredit[idx2] 增加 incr

    12. roundedCredit[idx1] 减少 incr

  7. integerCredit 为将 roundedCredit每个通过舍入到最接近的整数 转换为整数的结果, 半值情况向远离零的方向舍入。

  8. 返回 integerCredit

    这个最终舍入步骤仅用于处理微小的浮点 加法和减法误差未能完全移除 roundedCredit[idx1] 的小数部分的情况。半值舍入模式 实际上永远不会发生,选择该模式是为了匹配 C++ std::round 行为,以便实现。

    该算法旨在:1)在各分配之间精确分配总计 value 的值; 2)保持 integerCredit 的期望值恰好等于 归一化功劳 (即 credit * value / sumCredit,其中 * 表示逐元素 相乘); 3)任何分配都不会产生大于 1 的误差。

使用最后 N 次触达 归因填充直方图,给定一个集合,其元素为 展示 matchedImpressions、整数 histogramSize、整数 value,以及 double 列表 credit
  1. 断言matchedImpressions 非 空

  2. sortedImpressionsmatchedImpressions,按 优先级排序,然后按时间戳降序排序

  3. Ncredit大小sortedImpressions大小 中的较小值。

  4. lastNImpressionssortedImpressions 的前 N 个条目。

  5. 移除 credit 中除前 N 个条目之外的所有条目。

  6. normalizedCredit 为使用 creditvalue 公平分配 功劳的结果。

  7. histogram 为使用 histogramSize 调用创建 全零直方图的结果。

  8. 对于 lastNImpressions索引中的每个 i执行以下操作

    1. impressionlastNImpressions[i]。

    2. valuenormalizedCredit[i]。

    3. indeximpression直方图索引

    4. 如果 index 小于 histogram大小, 则将 histogram[index] 增加 value

  9. 返回 histogram

4.5. 设置实现定义值

本规范标识了若干实现定义值。 本节包括一些给实现的建议, 关于如何最好地设置这些值。

实现会为 lifetimeDayslookbackDays 设置一个实现定义最大回溯最大回溯是一个 正整数数。 为这些值设置不同最大值没有意义, 因为两个值中较小的那个 将决定哪些已保存的展示可用于转化。

实现必须最大回溯设置为至少 30 天。 在此期间内,实现应当尝试为每个展示站点保留 至少 1000 个展示。

在可能的情况下,实现应当在超出这些关于时间和数量的推荐限制后 继续保留展示。 可用于存储展示的容量同时取决于 保留展示数据所需的存储空间 以及生成转化报告所需的处理时间。 如果站点请求存储超出可用容量的展示、 如果用户请求这样做(见§ 10.2 禁用 Attribution API), 或出于实现定义原因, 实现可以在达到这些限制之前丢弃展示。

实现可能选择不保留展示的一个可能原因是, 该站点未获得足够的用户参与度。

对于传递给 saveImpression()measureConversion() 的站点列表,会选择一个实现定义值。 每个展示的最大转化站点数 是对 conversionSites 的值数量的限制; 实现必须将此值设置为至少 5。 每个展示的最大转化调用方数转化的最大展示调用方数 分别是对 conversionCallersimpressionCallers 的值数量的限制; 实现必须将这些值分别设置为至少 10。 转化的最大展示站点数 是对 impressionSites 的值数量的限制; 实现必须将此值设置为至少 30。

会为 最大 权重值数量选择一个实现定义值, 该值是对 credit 的值数量的限制; 实现必须将此值设置为至少 10。 会为 最大 匹配值数量选择一个实现定义值, 该值是对 matchValues 的值数量的限制; 实现必须将此值设置为至少 30。

measureConversion() 生成的直方图大小 同时受一个实现定义最大直方图大小最大聚合服务直方图大小约束。 没有为最大直方图大小设置最小值, 因为预期聚合技术的选择 将会设置一个限制。 最大聚合服务直方图大小 将是一个由聚合服务所使用技术的选择 决定的固定值; 它不是实现定义的。

4.5.1. 隐私和安全限制参数配置

用户 代理通过为以下内容定义值, 来配置隐私预算安全限制

安全限制配置为每站点预算的倍数, 会决定多个站点可以如何使用该 API。 在设置此倍数时, 实现需要考虑它们预期中 可能会使用其预算的站点数量, 也许还要向下调整, 以允许存在未完全使用其预算的站点。

安全限制设置为每站点预算的倍数, 可确保耗尽共享限制需要许多站点协作, 使其主要作为一种防止滥用的手段有用, 而不是作为主要的隐私机制。

5. HTTP API

5.1. 保存展示

`Save-Impression` 是一个 字典结构化标头, 设置在响应上,请求用户代理调用 saveImpression() API。

这是JavaScript saveImpression 示例的 HTTP 等价物:
Save-Impression: histogram-index=3, match-value=2, conversion-sites=("advertiser.example"), lifetime-days=7

定义了以下键,对应于传递给 saveImpression()AttributionImpressionOptions 字典的成员。被省略的 可选键的默认值会按与对应 AttributionImpressionOptions 字段相同的方式处理。未知字典键会被忽略, 未知参数也是如此。

conversion-sites
conversionSites 的值, 是一个包含字符串内部列表。 每个字符串值仅使用 A-label 包含一个域名; 因此,国际化 域名需要使用 punycode。 此键是可选的。
conversion-callers
conversionCallers 的值, 是一个包含字符串内部列表。 每个字符串值仅使用 A-label 包含一个域名; 因此,国际化 域名需要使用 punycode。 此键是可选的。
histogram-index
histogramIndex 的值, 是一个位于32 位无符号整数范围内的整数。此键是必需的。
priority
priority 的值, 是一个位于32 位有符号整数范围内的整数。此键是可选的。
match-value
matchValue 的值, 是一个位于32 位无符号整数范围内的整数。此键是可选的。
lifetime-days
lifetimeDays 的值, 是一个正整数。此键是可选的。
解析 Save-Impression 标头,给定一个标头值 input,运行以下步骤:
  1. dict 为使用 input_bytes 设置为 inputfield_type 设置为 "dictionary" 解析 结构化字段的结果。

  2. 如果解析失败,则返回错误。

  3. histogramIndexdict["histogram-index"] 带默认值 undefined

  4. 如果 histogramIndex 不是位于32 位无符号整数范围内的整数,则返回错误。

  5. opts 为一个新的 AttributionImpressionOptions, 其项目如下:

    histogramIndex

    histogramIndex

  6. 如果 dict["conversion-sites"] 存在

    1. conversionSites 为其

    2. 如果 conversionSites 不是内部 列表,或者 conversionSites 的任何 不是字符串, 则返回错误。

    3. opts.conversionSites 设置为 conversionSites

  7. 如果 dict["conversion-callers"] 存在

    1. conversionCallers 为其

    2. 如果 conversionCallers 不是内部 列表,或者 conversionCallers 的任何 不是字符串, 则返回错误。

    3. opts.conversionCallers 设置为 conversionCallers

  8. 如果 dict["match-value"] 存在

    1. matchValue 为其

    2. 如果 matchValue 不是位于 32 位无符号整数范围内的整数, 则返回错误。

    3. opts.matchValue 设置为 matchValue

  9. 如果 dict["lifetime-days"] 存在

    1. lifetimeDays 为其

    2. 如果 lifetimeDays 不是正整数, 则返回错误。

    3. opts.lifetimeDays 设置为 lifetimeDays

  10. 如果 dict["priority"] 存在

    1. priority 为其

    2. 如果 priority 不是位于 32 位有符号整数范围内的整数, 则返回错误。

    3. opts.priority 设置为 priority

  11. 返回 opts

5.2. 衡量转化

`Measure-Conversion` 是一个 字典结构化标头, 设置在响应上,请求用户代理调用 measureConversion() API。

这是JavaScript measureConversion 示例的 HTTP 等价物, 并额外带有一个 report-url,生成的报告将被 POST 到该 URL:
Measure-Conversion: aggregation-service="https://aggregator.example/tee", histogram-size=20, epsilon=1.0, lookback-days=14, impression-sites=("publisher.example" "other.example"), impression-callers=("ad-tech.example"), match-values=(2), credit=(0.25 0.25 0.5), value=3, max-value=7, report-url="https://report-handler.example/foo"

定义了以下键,对应于传递给 measureConversion()AttributionConversionOptions 字典的成员。被省略的 可选键的默认值会按与对应 AttributionConversionOptions 字段相同的方式处理。未知字典键会被忽略, 未知参数也是如此。

aggregation-service
aggregationService 的值, 是一个字符串。此键是必需的。
epsilon
epsilon 的值, 是一个正小数整数。此键是 可选的。
histogram-size
histogramSize 的值, 是一个正整数。此键是必需的。
lookback-days
lookbackDays 的值, 是一个正整数。此键是可选的。
match-values
matchValues 的值, 是一个包含非负整数内部列表。 此键是可选的。
impression-sites
impressionSites 的值, 是一个包含字符串内部列表。 每个字符串值仅使用 A-label 包含一个域名; 因此,国际化 域名需要使用 punycode。 此键是可选的。
impression-callers
impressionCallers 的值, 是一个包含字符串内部列表。 每个字符串值仅使用 A-label 包含一个域名; 因此,国际化 域名需要使用 punycode。 此键是可选的。
credit
credit 的值, 是一个包含正小数 或正整数内部列表。此键是可选的。
value
value 的值, 是一个正整数。此键是可选的。
max-value
maxValue 的值, 是一个正整数。此键是可选的。
report-url
一个字符串, 其中包含生成的报告(如果有)将被 POST 到的潜在可信 URL。 该 URL 可以相对于响应 URL。其方案 必须是 "https"。 此键是必需的。
解析 Measure-Conversion 标头,给定一个标头值 input 和一个URL baseUrl,运行以下步骤:
  1. dict 为使用 input_bytes 设置为 inputfield_type 设置为 "dictionary" 解析 结构化字段的结果。

  2. 如果解析失败,则返回错误。

  3. aggregationServicedict["aggregation-service"] 带默认值 undefined

  4. 如果 aggregationService 不是字符串,则返回 错误。

  5. histogramSizedict["histogram-size"] 带默认值 undefined

  6. 如果 histogramSize 不是位于32 位无符号整数范围内的正整数,则返回错误。

  7. reportUrlStringdict["report-url"] 带默认值 undefined

  8. 如果 reportUrlString 不是字符串,则返回 错误。

  9. reportUrl 为使用 baseUrlURL 解析器应用于 reportUrlString 的结果。

  10. 如果 reportUrl 为失败,则返回错误。

  11. 如果 reportUrl 不是潜在可信 URL,则返回错误。

  12. 如果 reportUrl方案不是 "https",则返回错误。

  13. opts 为一个新的 AttributionConversionOptions, 其项目如下:

    aggregationService

    aggregationService

    histogramSize

    histogramSize

  14. 如果 dict["epsilon"] 存在

    1. epsilon 为其

    2. 如果 epsilon 不是小数整数,则返回错误。

    3. opts.epsilon 设置为 epsilon

  15. 如果 dict["lookback-days"] 存在

    1. lookbackDays 为其

    2. 如果 lookbackDays 不是正整数, 则返回错误。

    3. opts.lookbackDays 设置为 lookbackDays

  16. 如果 dict["match-values"] 存在

    1. matchValues 为其

    2. 如果 matchValues 不是内部 列表,或者 matchValues 的任何 不是位于 32 位无符号整数范围内的整数,则返回 错误。

    3. opts.matchValues 设置为 matchValues

  17. 如果 dict["impression-sites"] 存在

    1. impressionSites 为其

    2. 如果 impressionSites 不是内部 列表,或者 impressionSites 的任何 不是字符串, 则返回错误。

    3. opts.impressionSites 设置为 impressionSites

  18. 如果 dict["impression-callers"] 存在

    1. impressionCallers 为其

    2. 如果 impressionCallers 不是内部 列表,或者 impressionCallers 的任何 不是字符串, 则返回错误。

    3. opts.impressionCallers 设置为 impressionCallers

  19. 如果 dict["credit"] 存在

    1. credit 为其

    2. 如果 credit 不是内部 列表,或者 credit 的任何 不是小数整数,则返回错误。

    3. opts.credit 设置为 credit

  20. 如果 dict["value"] 存在

    1. value 为其

    2. 如果 value 不是位于 32 位无符号整数范围内的正整数, 则返回错误。

    3. opts.value 设置为 value

  21. 如果 dict["max-value"] 存在

    1. maxValue 为其

    2. 如果 maxValue 不是位于 32 位无符号整数范围内的正整数, 则返回错误。

    3. opts.maxValue 设置为 maxValue

  22. 返回 (opts, reportUrl)。

发送报告,给定一个 字节 序列 report、 一个 URL url,以及一个环境设置对象 settings
  1. 断言url 是一个潜在可信 URL

  2. 断言url方案为 "https"。

  3. headers 为一个新的标头列表,其中包含一个名为 "Content-Type"、值为 "application/dap-report" 的标头

    注:如果 AttributionAggregationProtocol 将来获得除 dap-18-histogram 之外的值,则这里需要更新。

  4. request 为一个具有以下属性的新请求

    方法

    "POST"

    URL

    url

    标头列表

    headers

    主体

    report

    客户端

    settings

    模式

    "cors"

    缓存模式

    "no-store"

    keepalive

    true

    凭据模式

    "omit"

    引用来源

    url

  5. 获取 request,并可在发生错误时重试。

5.3. Fetch 猴子补丁

处理 Attribution 标头,给定一个请求 request响应 response,运行以下步骤:
  1. 如果 request目标不是以下之一, 则返回:"""audio""image""script""track""video"

  2. 如果 request客户端不是安全上下文,则返回。

  3. 如果 responseURL 不是潜在可信 URL,则返回。

  4. 如果 responseURL方案不是 "https",则返回。

  5. implicitInputs 为从 request客户端 获取隐式 API 输入的结果, 并使用 responseURL

  6. 如果 implicitInputs 为 null,则返回。

  7. saveImpressionHeader 为从 response标头列表获取 `Save-Impression` 的结果。

  8. 如果 saveImpressionHeader 不是 null:

    1. impressionOptions解析 saveImpressionHeader 的结果。

    2. 如果 impressionOptions 不是错误,则用 implicitInputs 保存 impressionOptions

  9. measureConversionHeader 为从 response标头列表获取 `Measure-Conversion` 的结果。

  10. 如果 measureConversionHeader 不是 null:

    1. parseConversionResult解析 measureConversionHeader 的结果。

    2. 如果 parseConversionResult 不是错误:

      1. 令 (conversionOptions, reportUrl) 为 parseConversionResult

      2. reportPromise 为使用 conversionOptionsimplicitInputs 运行衡量 转化的结果。

      3. 并行

        1. reportPromise 兑现时,令 result 为兑现值。

        2. 使用 result.reportreportUrlrequest客户端 发送报告

按如下方式修改 HTTP-network fetch

在步骤

如果 includeCredentials 为 true,则用户代理应该在给定 requestresponse 的情况下解析并存储响应 Set-Cookie 标头。

之后添加以下步骤

  1. 使用 requestresponse 处理 Attribution 标头

6. 实现考虑事项

7. 聚合

聚合 服务会接收多份归因信息, 并生成一个聚合指标。

用户代理实现会有不同的聚合要求。 但是,聚合过程具有一些共同要素。

首先,用户代理需要配置 或以其他方式获取 有关聚合服务的信息。 这包括受支持的聚合方法 以及所需的任何配置。

每种聚合方法都需要定义 如何对直方图进行以下处理:

聚合方法还需要定义 站点如何获得聚合结果。

7.1. 多方计算聚合

多方计算 (MPC) 系统是指 涉及多个独立实体 协同计算某个约定函数的系统。

本规范使用一个基于 Prio [PRIO]Distributed Aggregation Protocol (DAP) [DAP] 的 MPC 系统。 这是一个两方 MPC 系统,其特点是 依赖客户端提供的输入正确性证明。 这允许非常高效的 MPC 操作, 代价是提交给系统的数据大小适度增加。

使用 MPC 的聚合服务 由两个或更多独立服务组成, 它们协作计算预定义函数。

MPC 提供的基本保证是: 只有函数定义的输出 加上明确定义的泄露 会暴露给任何实体。

MPC 保证仅在 参与实体的一个子集诚实的范围内成立。 对于 Prio 中使用的两方 MPC, 只要任一 MPC 操作方保持诚实, 隐私——即输入的机密性——就会得到维护。 这种 MPC 配置不防止 任一 MPC 操作方破坏输出。

7.1.1. Prio 和 DAP

dap-18-histogram 聚合方法使用 Prio [PRIO] 和分布式聚合协议(DAP)[DAP]。 具体来说,此聚合方法使用 Prio3 可验证分布式聚合函数(VDAF)[VDAF]Prio3L1BoundSum 实例化 [PRIO-L1]

DAP 和 Prio3L1BoundSum 实例化定义了报告如何准备、 加密并提交以进行聚合。 DAP 还定义了如何获得聚合结果, 以及用户代理需要获取关于聚合服务的哪些配置。

在使用 Prio3L1BoundSum 时, 报告包含一个分布式零知识证明, 允许参与 MPC 的节点 确认所提交直方图的总和小于某个设定值。 Prio3L1BoundSum 只能 验证直方图总和 严格小于二的幂。 也就是说,证明会确认 该总和小于 2n,其中 n 为正整数。

为了构造报告, 会基于一个值生成证明, 该值是大于 maxValue 的下一个二的幂。 这意味着聚合服务无法拒绝 介于 maxValue 和下一个二的幂之间的报告。 因此,恶意用户代理可能会生成一个报告, 其对聚合直方图的贡献最多可达 maxValue 值的两倍。 当 maxValue 等于 2n − 1 时, 该证明确保没有超额贡献的机会; 通过在其他约束允许的情况下 将 maxValue 设置得尽可能接近 2n − 1, 可以降低任何此类攻击的相对影响。

7.1.2. DAP 扩展

DAP 的扩展 [DAP-ATTRIBUTION] 对此应用是必要的:

用户代理使用这些扩展来构造 它们生成的报告。

7.1.3. DAP 的报告加密

构造 DAP 报告, 生成一个字节序列 report, 给定已验证的转化选项 options站点 topLevelSite站点undefined intermediarySite时刻 now, 以及一个由列表形式的整数 histogram
  1. field 为 Field128, 如 第 6.1.3 节 [VDAF] 中所定义。

  2. lengthhistogram大小

  3. maxValueoptions.最大值

  4. chunkLength 为 (Math.ceil(log2(maxValue + 1)) + 1) * length 的平方根, 并四舍五入到最接近的整数。

  5. vdaf 为一个新的 PrioL1BoundSum VDAF [PRIO-L1] 实例, 传入 fieldlengthmaxValuechunkLength

  6. microEpsilonoptions.epsilon 乘以 1,000,000,然后向正无穷方向舍入。

  7. callerintermediarySite, 如果 intermediarySite 不是 undefined; 否则为 topLevelSite

  8. taskConfig 为通过编码 TaskConfiguration 实例生成的字节 序列, 该实例按 第 4.2 节 [DAP] 中的定义, 使用以下值:

    1. 一个空的 task_info

    2. 一个 leader_aggregator_endpoint,设置为 DAP Leader 的 URL, 该 URL 取自 options.Aggregation Service 中所选聚合服务实现定义的定义。 编码后的值通过用已配置的 URL 和 false(用于排除片段)调用URL 序列化器产生。

    3. 一个 helper_aggregator_endpoint,设置为 DAP Helper 的 URL, 该 URL 取自 options.Aggregation Service 中所选聚合服务实现定义的定义, 并使用与 leader_aggregator_endpoint 值相同的过程生成。

    4. 一个值为 5 的 time_precision

    5. 一个值为 20 的 min_batch_size

    6. 一个值为 TBD 的 batch_mode(见 Attribution API 的分布式 聚合协议(DAP)扩展 § batch-mode)。

    7. 一个空的 batch_config

    8. 一个值为 7 的 vdaf_type(见 具有贡献 L1 范数界的向量和的 Prio 实例化 § dap)。

    9. 一个 vdaf_configuration,按照 PrioL1BoundSum 具有贡献 L1 范数界的向量和的 Prio 实例化 § dap进行编码, 其带有 lengthmaxValuechunkLength

    10. 一组任务扩展 extensions, 即一个从16 位无符号整数字节序列映射

  9. taskID 为通过 DAP 的任务 绑定与带内配置 § task-id 中描述的过程,并传入 taskConfig 后生成的字节 序列

  10. ctx 为通过连接 字符串 dap-18编码后值 和 taskID 而形成的字节 序列, 如 第 4.4.2.1 节 [DAP] 中所定义。

  11. reportID 为从密码学安全随机源 [RFC4086] 中采样的 16 个字节。

  12. rand 为从密码学安全随机源 [RFC4086] 中采样的 128 个字节。

  13. publicShareinputShares 为调用 vdaf.shard() 的结果, 如 第 4.1 节 [VDAF] 中所定义, 传入 ctxhistogramreportID(作为 VDAF 的 "nonce" 参数) 和 rand

  14. time 为一个整数,该整数由 从Unix 纪元now持续时间 除以 5 秒的持续时间得到, 并向负无穷方向舍入。

  15. extensions 为一个从16 位无符号整数字节序列映射, 由以下内容组成:

    • 隐私 预算的扩展码点, 映射到 microEpsilon 的值, 该值通过使用 UINT32、 值 microEpsilonfalse(用于 isLittleEndian)调用 NumericToRawBytes 来编码。

  16. reportMetadata 为从 reportIDtimeextensions 生成的已编码 DAP ReportMetadata

  17. encryptedInputShares 为一个 列表

  18. inputShares 的每个 share 执行以下步骤, 遵循 第 4.4.2.1 节中描述的加密份额的方法:

    1. pkR 为来自相应角色的公钥, 该公钥来自为 options.Aggregation Service 所指示的聚合服务获取的聚合服务 HPKE 配置

      "dap-18-histogram" 的 URL 预期标识 DAP Leader 角色。 实现需要静态获取两个 Aggregator 的 HPKE 配置。 HPKE 配置不得按需获取, 因为所花费的时间会向 measureConversion() 的调用者泄漏信息。

    2. serverRole 对第一项(Leader)为 2, 对第二项(Helper)为 3。

    3. info 为通过连接以下内容形成的字节 序列: 字符串 dap-18 input share编码后值、 一个值为 0x01 的字节,以及 serverRole

    4. inputShareAADtaskIDreportMetadatapublicSharetaskConfig 按照 InputShareAad 的结构构造。

    5. plaintextShare 由 一个空集合(用于 private_extensions)和 share(用于 payload) 按照 PlaintextInputShare 的结构构造。

    6. hpke 为一个基于同一个 HPKE 配置的 HPKE [RFC9180] 配置。

    7. encryptedShare 为调用 hpke.Seal<mode_base>() 的结果, 传入 pkRinfoinputShareAADplaintextShare

    8. encryptedShare 追加encryptedInputShares

  19. report 为从 reportMetadatapublicShareencryptedInputShares (这两个值分别为 leader 和 helper 加密输入份额), 以及从 DAP 聚合器获得的聚合服务 HPKE 配置 生成的已编码 DAP Report

  20. 返回 report

7.2. 防重放要求

浏览器生成的转化报告 会绑定到请求该报告的站点所消耗的隐私 预算数额。

聚合 服务必须保证 不会多次接受同一报告。

8. 差分隐私

此设计使用差分隐私概念 作为其隐私设计的基础。[PPA-DP]

差分隐私 是一种隐私的数学定义, 它可以保证系统所揭示的 私有信息量。[DP] 差分隐私并不是此系统中 保护隐私的唯一手段, 但它是定义和分析最严格的一种。 因此,它提供了最强的隐私保证。

差分隐私使用随机噪声 来隐藏对聚合数据集的 私有数据贡献。 噪声的作用是隐藏 对数据集的个体贡献, 同时保留任何聚合分析的有用性。

为了应用差分隐私, 有必要定义受保护的信息是什么。 在此系统中,受保护的信息是 单个用户配置文件在单个用户代理上, 跨单个纪元, 针对注册转化的单个网站所产生的展示§ 8.1 隐私单元更详细地描述了此设计 的含义。

此归因设计使用一种称为 个体差分隐私的差分隐私形式。 在此模型中,各用户代理分别负责 确保限制其贡献的信息量。

此 API 的个体差分隐私设计 具有三个主要组成部分:

  1. 用户代理会限制(使用隐私预算)通过转化报告 离开设备的关于展示的 信息量。 § 8.2 隐私预算对此进行了更深入的探讨。

  2. 聚合 服务确保任何给定的转化报告 只按照用户代理为其计入的隐私预算使用。 § 7.2 防重放要求更详细地描述了对聚合 服务的要求。

  3. 噪声由聚合服务添加。 § 8.3 差分隐私机制详细说明了可能 使用的机制。

这些措施共同限制了 针对每个隐私单元所释放的信息。

8.1. 隐私单元

差分隐私的实现 需要对受保护对象作出清晰定义。 这称为隐私 单元, 它表示受到隐私保护的实体。

此系统采用的隐私单元 是三个值的组合:

  1. 一个用户代理配置档案。 即由单个人使用的一个用户代理实例。

  2. 请求关于展示的信息的站点 (即转化站点)。

    注册展示的站点(即展示站点) 不予考虑。 这些站点不会直接从此系统接收信息。

  3. 当前纪元

这些值中的任何一个发生变化都会产生一个新的隐私单位, 从而产生一个单独的隐私预算。 用户访问的每个站点都会在每个纪元 获得有界数量的信息。

理想情况下,隐私单位是 单个人。 尽管理想如此,但由于多种原因, 无法开发出一个有用且保证与个人完全对应的系统:

8.1.1. 隐私属性及其限制的形式化分析

Attribution 中的隐私保护是多层的:

  1. 按站点预算会限制任何单个转化站点能够获知的关于用户的信息量。

  2. 全局预算为所有站点能够获知的关于用户的信息量提供后备限制。

  3. 展示站点配额会限制转化站点能够获知的关于用户在任何单个 展示站点上的活动信息量。

  4. 每次用户操作后维护的计数器会限制有多少站点可以向 API 中存储数据 或从 API 中获知信息。

本规范中的形式化隐私分析基于两篇论文。 第一篇 [PPA-DP] 建立了设备端个体 DP 核算的理论。 第二篇 [PPA-DP-2] 将分析扩展到按站点预算和全局预算 所提供的数学隐私保证。

按站点预算应被视为主要的隐私保护。按站点预算应配置为 提供有意义的 DP 保证。 然而,[PPA-DP-2] 中的分析识别出了两个会限制这些保证的假设:

  1. 数据生成中没有跨站适应性。 某个站点的可查询数据流(展示 和转化)必须独立于其他站点过去的 DP 归因 结果生成。

  2. 没有通过跨站共享限制产生泄露。 来自一个站点的查询不得影响 发往其他站点的报告。

简而言之,这两个假设在实践中都无法成立。

没有跨站适应性的假设是必要的, 因为该系统涉及多个站点, 它们可能会随时间与同一用户交互。 站点会基于彼此的 DP 衡量结果 改变向用户展示的广告。例如,如果一个广告主 从归因 结果中了解到如何制作更好的广告, 某些用户可能会在其站点上转化, 而不是在竞争对手站点上转化。在这种情况下,一个站点所获知的信息——只计入 它自己的按站点预算——会改变其竞争对手可见的数据(或数据缺失),但 这并未计入这些竞争对手的按站点预算。

任何提供持续衡量的系统都具有此属性,因此唯一的结论只能是接受 这种限制。该限制也是设置全局 DP 预算和共享配额的部分理由, 而这些又引出了第二个假设。

当存在跨多个站点的共享限制时, 没有跨站泄露的假设是必要的。 此类共享限制的一个例子是旨在提供全局 DP 保证的全局安全限制。 如果来自某些站点的 measureConversion() 请求导致 共享限制被达到,发往其他站点的报告可能会被过滤。 例如,知道自身拥有展示的站点会获知一些关于共享限制是否已经达到的信息。 虽然此信息是聚合且带噪声的, 但它是关于耗尽预算的站点的信息, 超出了该站点的按站点预算。

通过共享限制产生的泄露促使这些限制仅作为限制滥用的手段使用。 将共享限制设置为按站点预算的大倍数,会使得 试图利用共享限制需要至少同样数量的站点协同。 更大的倍数会使共享限制作为隐私保护手段的作用更弱, 而更适合作为防止拒绝服务或类似滥用形式的手段。

相比之下,分析表明,全局预算可以在没有这些限制的情况下 被实现为提供健全的全局个体 DP 保证。 然而,为了支持许多站点使用该 API, 全局预算需要配置为按站点预算的显著倍数。 这意味着它所提供的 DP 保证虽不依赖任何假设, 却无法单独提供有意义的 DP 保护。 因此,按站点预算提供主要的 DP 保证。 全局预算可以被视为恶意站点协同攻击时的后备措施。

全局 DP 预算还可以防范能够跨许多站点关联用户身份 以组合按站点预算的站点。 按站点模型没有考虑这种可能性, 尽管某些站点具有这种能力很常见。 尤其包括身份提供方、接收用户标识符(例如电子邮件地址或电话号码)的站点、 成功使用导航跟踪 [NAV-TRACKING-MITIGATIONS] 的站点, 以及因任何原因能够使用跨站 cookie 的站点 [WEB-WITHOUT-3P-COOKIES]。 对于这些站点来说,跨多个站点使用 Attribution 可能带来协调挑战, 但在对系统隐私进行任何整体分析时, 不能忽视站点可能具备将活动关联到单个人的能力。

8.1.2. 浏览器实例

每个浏览器实例都管理一个单独的隐私预算

浏览器实例之间的协调可能是可行的, 但并非预期如此。 这种协调可能通过减少释放的信息总量 来改善隐私。 它也可能通过允许一个浏览器实例上的展示 在另一个浏览器实例上转化, 来提高归因的实用性。

跨不同实现的协调 目前不在此工作的范围内。 实现可以在已知属于同一人的实例之间 执行某些协调, 但这不是强制性的。

8.1.3. 按站点限制

释放给网站的信息是基于站点进行的。 这与其他隐私相关功能中使用的边界一致。

更细粒度的隐私单元,例如, 会使获取额外信息变得非常容易。 关于同一个人的信息可以从多个源收集。 然后,这些信息可以通过利用站点内部信息的自由流动 使用 cookie [COOKIES] 或类似机制进行组合。

§ 8.2.2 安全限制讨论了利用此限制的攻击, 以及用户代理可能实现的一些额外安全 限制, 以防范这些攻击。

8.1.4. 隐私预算纪元

站点会收到一个单独的差分隐私预算, 用于查询记录在每个隐私 预算纪元 (或纪元) 中的展示

此预算适用于已向用户代理 注册并稍后被查询的展示, 而不是转化

从分析 [PPA-DP] 的角度来看, 每个纪元中的展示 构成一个单独的数据库。 一个有限的隐私预算 会在对每个数据库执行的所有查询中被强制执行。

从跨多个纪元展示 生成转化 报告 会产生隐私后果。 对网站的一次访问可以让该站点获得 关于跨许多纪元的活动的信息。 这只需要 在整个期间内转化站点 被标识为展示的目的地。 可查询的纪元数量由用户代理限制。

目标是将纪元 设置得尽可能大。 更长的时间段允许获得更好的隐私/实用性平衡, 因为站点可以在任何时间点 被分配更大的总体预算, 同时保持较低的总体隐私损失速率。 然而,更长的间隔意味着更容易 完全耗尽隐私预算, 从而在下一次刷新之前无法提供任何信息。

纪元持续时间设置为一周的决定 在很大程度上是任意的。 预计一周足以让站点 在如何花费隐私预算方面 具有一定灵活性, 而不需要进行谨慎规划以考虑 未来数天或数周可能发生的变化。

§ 8.2 隐私预算更详细地描述了预算过程。

8.2. 隐私预算

浏览器维护隐私 预算, 这是一种限制隐私损失量的手段。

本规范使用一种个体形式的 (ε, δ)-差分隐私作为其基础。 在此模型中,隐私损失使用 ε 值来度量。 δ 值由聚合服务 在向聚合结果添加噪声时处理。

每个用户代理实例都负责 管理隐私预算。

每个被请求的转化报告 都会指定一个 ε 值, 表示该报告消耗的隐私预算量, 以及转化报告中可返回值的上限。

8.2.1. 隐私预算扣减

在为转化报告搜索展示时, 用户代理会从保存这些展示所在的隐私预算纪元的预算中 扣减指定的 ε 值。 如果该纪元隐私预算 不足, 则不会使用来自该纪元的展示。

每次转化 站点调用 measureConversion() 时, 都会针对归因 逻辑所选择的展示 所来自的纪元 扣减隐私预算

在下图中, 展示记录来自若干不同站点, 并用圆圈表示。
time `--. .--' `--. .--' `--. .--' `--. .--' ^ | | | | | week 1 week 2 week 3 week 4 now ]]> 站点 A 站点 B 站点 C 站点 D 站点 E 时间 第 1 周 第 2 周 第 3 周 第 4 周 现在
随时间推移的展示存储示例

可能会在标记为 "now" 的时间请求一个转化 报告。 该转化报告选择以黑色圆圈标记的展示, 对应于来自站点 B、C 和 E 的展示。

因此,转化站点隐私 预算 会从纪元 1、3、4 和 5 中被扣除纪元 2 中没有记录任何展示, 因此不会从该纪元扣除任何预算

用户 代理如何管理隐私预算耗尽, 取决于所选择的归因 逻辑

8.2.2. 安全限制

基本隐私单元 容易受到能够跨多个站点 关联同一个人活动的对手攻击。

站点组有时可以协调其活动, 例如当它们具有共同所有权或强协议时。 如果一组站点可以确信某个特定访问者是同一个人——使用任何手段,包括 类似 FedCM [FEDCM] 的东西—— 就可以组合从此 API 获得的信息。

这可用于提高站点通过归因获得信息的速率, 其增幅与发生协调的站点数量成正比。 默认隐私单元 对以这种方式释放的信息不施加限制。

为了抵消这种影响,用户代理可以实现安全限制, 即不考虑站点的额外隐私预算。 安全限制可能显著高于按站点预算, 以使其在大多数正常浏览活动中不会被达到。 目标是确保它们只对密集活动 或受到攻击时有效。

与按站点隐私预算一样, 关键是站点不能确定 它们对转化报告的请求是否导致 安全限制被超过。

8.3. 差分隐私机制

差分隐私机制——也就是添加噪声的具体方法——可以由 聚合 服务选择。

预计添加拉普拉斯噪声会产生良好结果, 在噪声的总体大小 与实现和分析的简单性之间取得平衡。 当前设计使用基于 L1 范数的 DP 敏感度, 这支持在聚合中添加拉普拉斯噪声。 支持其他噪声机制可能需要对敏感度的计算和信令方式 进行额外变更。

在一个中心位置添加噪声, 如这些聚合服务中任一项所定义的那样, 可确保噪声总量不会随着 报告总数的增加而增加。 相比在生成报告时添加噪声的差分隐私设计 (也就是局部差分隐私模型), 这提供了实用性优势; 在后者中,噪声会随报告总数成比例增加。

9. 安全考虑事项

9.1. 展示存储

Attribution API 使用的展示存储 保存与浏览活动相关的信息, 并且会跨浏览会话持久存在。 尽管通过展示存储的信息流 受到严格控制, 但它仍会在源之间携带一定量的信息。

以下措施限制了 通过展示存储产生有害信息流的可能性:

9.2. 实现中的侧信道风险

必须谨慎实现 Attribution API, 以维护所需的安全和隐私属性。 调用 API 的站点不能获知:

注意,显式返回值或抛出的异常 并不是站点从 Attribution API 获知信息的唯一方式。 也可能从如下侧信道 推断出敏感信息:

API 中函数执行时间的变化 是维护保证时的主要考虑因素。 对执行时间而言,有两个尤其值得关注的因素:

全局隐私预算存储展示站点配额存储 以及纪元开始时间中的 共享全局状态 风险较低, 因为这些值从不直接影响算法运行时间。 实现仍需要确保任何全局状态 不会构成指纹 或其他信息泄露。

虽然完全消除所有侧信道并不现实, 但实现必须作出合理努力, 防止来自归因 API 的敏感信息泄露。 防止泄露的策略包括:

9.3. 聚合服务

尽管聚合服务并不是 Web 平台的一部分, 但聚合服务的安全性 对 Attribution 机制的整体安全性相当重要。 由 measureConversion() 生成的转化报告 使用聚合服务的加密密钥进行加密。 因此,这些报告中所含信息 潜在披露的很大一部分可能性 取决于聚合服务的细节。

用户 代理开发者应在将某个聚合服务 添加为 Attribution API 支持的服务之前, 仔细考虑该聚合服务的设计 以及聚合服务运营者的可信度。 关于这些问题的更多讨论 可见 § 7 聚合§ 10 隐私 考虑事项

9.4. 组合来自多个站点的报告

Attribution API 中的隐私机制 主要以站点为粒度运行。 恶意运营者 可能会尝试为多个站点注册展示, 从而超过原本会通过归因 释放的信息量。 § 8.2.2 安全限制讨论了建立额外的跨站 隐私预算,以缓解这种可能性。

9.5. 广告欺诈

与许多技术一样, Web 上的广告 一直是各种欺诈行为的对象。

展示的欺诈性注册 是 Attribution API 的一个特别关注点, 因为展示只存储在设备上。 无法应用服务器端智能 来识别欺诈性展示并将其 从归因中排除。相反,尽管转化报告 是加密的,但由于报告会发送 到服务器,服务器可以判断 该转化很可能是欺诈性的,并将其从 聚合中排除。

防止恶意使用 Attribution API 的 一项重要缓解措施是: 在注册展示时明确指定 符合条件的转化站点, 并在注册转化时明确指定 符合条件的展示站点和直方图索引。 这会防止任意恶意站点上的展示 干扰对预期候选展示集合的归因。

10. 隐私考虑事项

此 API 的主要隐私目标是 确保向站点提供执行归因的能力 不会提升它们执行跨站识别的能力。

本节提供更多信息, 说明实现此目标所需的保护。 额外讨论还涉及次要隐私目标, 例如防止同站识别

10.1. Attribution API 暴露的信息

展示存储隐私预算 存储 包含关于浏览活动横截面的信息。 随着 API 使用增加, 这些信息的范围也会扩大。 然而,写入这些存储的大部分信息 从不会被披露。 因为归因是在设备上执行的 (设备端归因), Attribution API 只会暴露关于已归因转化的信息。 这与其他方案形成对比: 在那些方案中,关于展示和转化的信息 都会发送给聚合服务以进行设备外归因。 在后一类方案中, 聚合服务遭入侵 (或与聚合服务通信遭入侵) 时可能被揭示的信息量 要显著更大。

当 Attribution API 进行归因时, 关于该归因的信息 只会在差分隐私限制允许的范围内 从设备释放。

虽然 Attribution API 旨在衡量 相对不频繁的转化事件 与有限相关展示候选集之间的关联, 但仍需考虑该 API 可能如何 被误用于更大规模的数据收集。 要求展示枚举可能的转化 站点(反之亦然) 在防止 API 被滥用于大规模数据收集、 以及使此类滥用尝试更明显方面 发挥重要作用。

10.2. 禁用 Attribution API

用户代理必须为用户提供 禁用 Attribution API 的控制项。

Attribution API 设计为只揭示聚合信息。 使用差分隐私 会限制确定任何特定用户 是否对聚合输出作出贡献的可能性。 然而,一些用户仍可能偏好 不参与归因衡量。

实现可以向用户提供选择退出的选项, 通过 Attribution API 的专用控制项, 或通过适用于多个特性的统一隐私控制项。

用户代理开发者应考虑 其他隐私模式与 Attribution API 的交互。 例如,归因可能在隐私浏览模式中被禁用, 或者当用户已选择不参与诊断数据收集时 被禁用。

按照设计,网站无法检测用户是否已选择退出。

为了尽量降低指纹识别风险, 并防止歧视选择禁用 Attribution API 的用户, 站点不得能够检测 API 已被禁用。 具体而言,所有在其他方面有效的 Attribution API 调用 即使在 API 被禁用时也会成功完成。 行为上的唯一区别是: API 被禁用时返回的转化 报告 永远不会报告任何转化值。 由于报告是加密的, 接收转化报告的站点 无法检测到这种差异。

10.3. 可见性

实现应该为用户提供一种方式, 用于查看展示存储的状态 并审查过去的报告提交。

这些界面可以限制为摘要信息, 显示各站点对 Attribution API 的聚合使用情况。 用于检查展示和已提交报告细节的界面 可以使用户和 Web 开发者 都能诊断 API 的运行情况。

10.4. 未配置的浏览器

此 API 假定用户代理实例 具有回答 measureConversion() 请求所需的 所有配置。

如果调用 measureConversion() 所需的聚合 服务配置 缺失或已过期, 那可能会被站点观察到。

如果配置的获取 可能会延迟 measureConversion() 调用的兑现, 这会产生一个时序侧信道。 如果改为生成伪响应,则来自正确配置的用户代理 的响应与伪响应之间的差异 可能会被观察到。 这可能是密钥标识符 或其他未加密元数据的使用。 密文长度的差异也可能揭示被加密内容的变化 或算法选择的变化。

检测到过期或缺失的配置可能会被用于 指纹识别用户代理

因此,用户 代理应当 以站点无法观察到的方式 优先获取聚合服务配置。 这可以通过在启动时、 开始加载任何内容之前获取配置来实现。

如果无法获取必要的配置, 或配置明显过期, 实现可以选择在调用 measureConversion() 时 立即拒绝。 这会泄露信息, 但它泄露的信息可能少于尝试生成伪值。

10.5. 在已保存展示中包含标识信息

站点能够使用 matchValue 或其他字段, 在展示中编码一定量的数据。 该 API 并不阻止站点 在这些字段中编码用户标识符。 归因过程可以在构造转化报告时使用这些数据, 这意味着这些标识信息 有一定风险会被接收该报告的站点获得。 以下措施可缓解此风险:

10.6. 在第三方上下文中使用

Attribution API 即使在第三方上下文中也可用。 特别是,第三方 iframe 可以调用 saveImpression()。 但请注意,展示会使用顶级导航上下文的站点 记录,而不是使用 iframe 的

虽然 API 在第三方上下文中的可用性 会带来一定隐私风险增加, 但这种支持被认为是必要的, 因为 iframe 常用于展示广告。

10.7. 清除 API 状态

用户 代理可能会提供清除存储的选项。 这些选项存在有两个原因:

清除跟踪隐私预算消耗的状态, 会对面向站点的隐私产生不利影响。 这样,站点就能够从归因中 获得更多信息。

用户 代理可以在 API 被禁用时, 从隐私 预算存储纪元开始时间中清除数据。 在这种情况下,如果 API 被重新启用, 就无法确定在 API 被禁用之前 消耗了多少预算。 在这种情况下,用户代理可以更新 上次清除浏览历史的值, 以确保隐私 预算不会被无意超出。

10.7.1. 清除站点数据

在应用户请求清除站点数据, 但保留浏览历史时, 用户 代理调用为归因清除浏览历史, 给定受影响站点集合、 false(用于 forgetVisits), 以及采取该操作的时间。 这会将该站点的隐私预算设置为零, 防止在该站点上使用任何转化测量。 这不会从展示存储中移除已保存的展示; 从逻辑上说,展示在被保存时 就已转移给转化站点

当应站点请求, 通过使用 `Clear-Site-Data` 标头清除站点数据时, 用户 代理移除展示, 而不更改隐私预算存储纪元开始 时间

10.7.2. 清除浏览历史

在清除浏览历史时, 更新隐私 预算存储是不充分的。 保留防止面向站点的隐私损失所必需的、按站点划分的 信息, 会留下关于站点访问的信息, 供计算机的其他用户发现。

清除浏览历史的用户代理 调用为归因清除浏览历史, 给定受影响站点集合、 true(用于 forgetVisits), 以及发起该操作的时间。

清除浏览历史时, 用户 代理需要 移除所有按站点划分的隐私预算信息 (也就是从隐私预算存储中移除条目)。 用户 代理还需要确保 后续任何隐私 预算消耗 都不会由于丢失该信息而造成 超过配置限制的隐私损失。

这可以通过在丢弃浏览历史所在的纪元 禁用归因来实现。 否则,一个在清除历史前 立即消耗其预算的站点 将能够通过此 API 获知 比不清除状态时更多的信息。

这会在受影响站点纪元 剩余时间内禁用此 API。 由于纪元开始 时间未被清除, 纪元 时间线会保持连续。

用户 代理会在上次清除浏览历史值中记住上次清除历史的时间。 这用于阻止预算消耗, 直到能够保证某个站点不会超过 用户 代理所选择的最大允许隐私预算为止。

获取归因起始纪元 算法 确保转化 站点 无法查询任何在状态被清除后一个纪元持续时间 内开始的纪元中的展示

10.7.3. 清除展示

必须提供一种机制来清除展示存储。 例如,可以在激活禁用 Attribution API 的控件时 清除展示存储。

建议将用户代理提供的任何 用于清除已存储数据(历史、Cookie 等)的机制 扩展为覆盖展示存储。 § 10.7 清除 API 状态提供了关于 清除已存储数据的更详细信息。

为某个站点 清除状态的用户 代理 必须丢弃所有在受影响期间保存、 且具有匹配展示站点转化站点已保存 展示。 对于展示站点, 这些展示与 已被清除的活动有关。 已清除状态的转化站点 将无法使用这些展示

具有匹配中介站点展示 可以被保留。

10.8. 时钟选择

此 API 使用挂钟作为其时间基础。 这主要是因为该 API 依赖于一种持久的时间概念。 单调时钟只在用户 代理的一次执行期间定义, 因此如果用户代理被重启, 它无法保证一致性。

挂钟可以被调整,以修正 由于时钟漂移而可能累积的误差。 因此,挂钟不保证始终以 一致的速率前进, 包括有时可能倒退的可能性。

挂钟的倒退不会影响 此 API 提供的隐私保证。 只有时钟的前进, 才可能产生不利的隐私影响。 超过时间正常推进幅度的前进 可能导致隐私预算 比预期更快地更新。

对于在每个纪元内经历校正的时钟, 时钟调整不会产生隐私影响。 一次足够大的校正 可能导致隐私 预算提前更新, 从而导致隐私损失的一次性增加。 持续的大幅校正对隐私的影响最为严重, 因为每次纪元之间的转换 都会释放额外的隐私预算

一次非常大的时间增加 如果跳过了整个纪元, 不会导致额外的隐私损失。 除非某个展示可以被保存, 否则不可能发生隐私损失。

当然,任何需要对其时钟进行大幅 或持续 校正的用户代理,都可能由于其报告的时间 而具有很高的可识别性。 单凭这一点就很可能足以导致不希望发生的跨站识别

11. 致谢

本规范是许多人大量工作的成果。 这一层级 API 的大致形态基于 Luke Winstrom 的想法。 隐私架构由 [PPA-DP] 的作者提供。

符合性

文档 约定

符合性要求通过描述性断言 和 RFC 2119 术语的组合来表达。 规范性部分中的关键词 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、 “MAY” 和 “OPTIONAL” 应按 RFC 2119 中所述进行解释。 但是,为了可读性, 本规范中这些词并不全部以大写字母出现。

本规范的所有文本都是规范性的, 但明确标记为非规范性的章节、示例和注释除外。[RFC2119]

本规范中的示例会以 “for example” 这些词引入, 或者通过 class="example" 与规范性文本分开, 如下所示:

这是一个资料性示例。

资料性注释以 “Note” 一词开头, 并通过 class="note" 与规范性文本分开, 如下所示:

注:这是一个资料性注释。

符合性 算法

作为算法一部分以祈使语气表述的要求 (例如 "strip any leading space characters" 或 "return false and abort these steps") 应按引入该算法时所使用的关键词 ("must"、"should"、"may" 等) 的含义来解释。

以算法或具体步骤表述的符合性要求 可以用任何方式实现, 只要最终结果等价即可。 特别是,本规范中定义的算法 旨在易于理解, 并非旨在具有高性能。 鼓励实现者进行优化。

索引

本规范定义的术语

由引用定义的术语

参考文献

规范性参考文献

[CLEAR-SITE-DATA]
Mike West. Clear Site Data。2017年11月30日。WD。URL:https://www.w3.org/TR/clear-site-data/
[CSS-2025]
Chris Lilley; et al. CSS Snapshot 2025。2025年9月18日。NOTE。URL:https://www.w3.org/TR/css-2025/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4。2024年3月12日。WD。URL:https://www.w3.org/TR/css-values-4/
[CSS2]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification。2011年6月7日。REC。URL:https://www.w3.org/TR/CSS2/
[DAP]
Tim Geoghegan; et al. Distributed Aggregation Protocol for Privacy Preserving Measurement。2024-04-29。URL:https://datatracker.ietf.org/doc/html/draft-ietf-ppm-dap-16
[DAP-ATTRIBUTION]
Martin Thomson. Distributed Aggregation Protocol (DAP) Extensions for the Attribution API。2025-01-15。URL:https://datatracker.ietf.org/doc/html/draft-thomson-ppm-dap-attribution-00
[DAP-TASKPROV]
Shan Wang; Christopher Patton. Task Binding and In-Band Provisioning for DAP。2025-09-05。URL:https://datatracker.ietf.org/doc/html/draft-ietf-ppm-dap-taskprov-03
[DOM]
Anne van Kesteren. DOM Standard。现行标准。 URL:https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification。URL:https://tc39.es/ecma262/multipage/
[FETCH]
Anne van Kesteren. Fetch Standard。活 标准。URL:https://fetch.spec.whatwg.org/
[HR-TIME-3]
Yoav Weiss. High Resolution Time。2026年3月24日。 WD。URL:https://www.w3.org/TR/hr-time-3/
[HTML]
Anne van Kesteren; et al. HTML Standard。 现行标准。URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard。现行标准。URL:https://infra.spec.whatwg.org/
[PERMISSIONS-POLICY-1]
Ian Clelland. Permissions Policy。 2025年10月6日。WD。URL:https://www.w3.org/TR/permissions-policy-1/
[PRIO-L1]
Martin Thomson; David Cook. A Prio Instantiation for Vector Sums with an L1 Norm Bound on Contributions。2024-10-21。URL:https://datatracker.ietf.org/doc/draft-thomson-ppm-l1-bound-sum/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels。1997年3月。当前最佳实践。URL:https://datatracker.ietf.org/doc/html/rfc2119
[SECURE-CONTEXTS]
Mike West. Secure Contexts。2023年11月10日。 CRD。URL:https://www.w3.org/TR/secure-contexts/
[URL]
Anne van Kesteren. URL Standard。现行标准。 URL:https://url.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard。现行标准。URL:https://webidl.spec.whatwg.org/

非规范性参考文献

[COOKIES]
A. Barth. HTTP State Management Mechanism。 2011年4月。拟议标准。URL:https://httpwg.org/specs/rfc6265.html
[COPPACALYPSE]
Garrett Johnson; et al. COPPAcalypse? The Youtube Settlement's Impact on Kids Content。2024-03-14。URL:https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4430334
[DP]
Cynthia Dwork; Aaron Roth. The Algorithmic Foundations of Differential Privacy。2014。URL:https://doi.org/10.1561/0400000042
[EU-AD]
Niklas FOURBERG; et al. Online advertising: the impact of targeted advertising on advertisers, market access and consumer choice。2021-06。URL:https://www.europarl.europa.eu/thinktank/en/document/IPOL_STU(2021)662913
[FEDCM]
Nicolas Pena Moreno. Federated Credential Management API。2024年8月20日。FPWD。URL:https://www.w3.org/TR/fedcm-1/
[FREE-GDP]
Leonard Nakamura; Jon D. Samuels; Rachel Soloveichik. Measuring the "Free" Digital Economy within the GDP and Productivity Accounts。2017-10。URL:https://www.bea.gov/research/papers/2017/measuring-free-digital-economy-within-gdp-and-productivity-accounts
[NAV-TRACKING-MITIGATIONS]
Navigational-Tracking Mitigations。编辑草案。URL:https://privacycg.github.io/nav-tracking-mitigations/
[ONLINE-ADVERTISING]
Avi Goldfarb; Catherine Tucker. Online Advertising。URL:https://doi.org/10.1016/B978-0-12-385514-5.00006-9
[PPA-DP]
Pierre Tholoniat; et al. Cookie Monster: Efficient On-device Budgeting for Differentially-Private Ad-Measurement Systems。URL:https://arxiv.org/abs/2405.16719
[PPA-DP-2]
Pierre Tholoniat; et al. Big Bird: Privacy Budget Management for W3C's Privacy-Preserving Attribution API。URL:https://arxiv.org/abs/2506.05290
[PRIO]
Henry Corrigan-Gibbs; Dan Boneh. Prio: Private, Robust, and Scalable Computation of Aggregate Statistics。2017-03-14。URL:https://crypto.stanford.edu/prio/paper.pdf
[RFC3492]
A. Costello. Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)。2003年3月。拟议 标准。URL:https://www.rfc-editor.org/rfc/rfc3492
[RFC4086]
D. Eastlake 3rd; J. Schiller; S. Crocker. Randomness Requirements for Security。2005年6月。当前最佳实践。URL:https://www.rfc-editor.org/rfc/rfc4086
[RFC5890]
J. Klensin. Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework。2010年8月。拟议标准。 URL:https://www.rfc-editor.org/rfc/rfc5890
[RFC6761]
S. Cheshire; M. Krochmal. Special-Use Domain Names。2013年2月。拟议标准。URL:https://www.rfc-editor.org/rfc/rfc6761
[RFC9180]
R. Barnes; et al. Hybrid Public Key Encryption。2022年2月。资料性。URL:https://www.rfc-editor.org/rfc/rfc9180
[STORAGE]
Anne van Kesteren. Storage Standard。活 标准。URL:https://storage.spec.whatwg.org/
[UNSANCTIONED-TRACKING]
Mark Nottingham. Unsanctioned Web Tracking。2015年7月17日。TAG 结论。URL:https://www.w3.org/2001/tag/doc/unsanctioned-tracking/
[VDAF]
Richard L. Barnes; et al. Verifiable Distributed Aggregation Functions。2026-01-30。URL:https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-18
[WEB-WITHOUT-3P-COOKIES]
A Web Without Third-Party Cookies。URL:https://www.w3.org/2001/tag/doc/web-without-3p-cookies/

IDL 索引

partial interface Navigator {
  [SecureContext, SameObject] readonly attribute Attribution attribution;
};

enum AttributionAggregationProtocol { "dap-18-histogram" };

dictionary AttributionAggregationService {
  required AttributionAggregationProtocol protocol;
};

[SecureContext, Exposed=Window]
interface AttributionAggregationServices {
  readonly maplike<USVString, AttributionAggregationService>;
};

[SecureContext, Exposed=Window]
interface Attribution {
  readonly attribute AttributionAggregationServices aggregationServices;
};

dictionary AttributionImpressionOptions {
  required unsigned long histogramIndex;
  unsigned long matchValue = 0;
  sequence<USVString> conversionSites = [];
  sequence<USVString> conversionCallers = [];
  unsigned long lifetimeDays = 30;
  long priority = 0;
};

dictionary AttributionImpressionResult {
};

[SecureContext, Exposed=Window]
partial interface Attribution {
  Promise<AttributionImpressionResult> saveImpression(AttributionImpressionOptions options);
};

dictionary AttributionConversionOptions {
  required USVString aggregationService;
  double epsilon = 1.0;

  required unsigned long histogramSize;

  unsigned long lookbackDays;
  sequence<unsigned long> matchValues = [];
  sequence<USVString> impressionSites = [];
  sequence<USVString> impressionCallers = [];

  sequence<double> credit;
  unsigned long value = 1;
  unsigned long maxValue = 1;
};

dictionary AttributionConversionResult {
  required Uint8Array report;
};

[SecureContext, Exposed=Window]
partial interface Attribution {
  Promise<AttributionConversionResult> measureConversion(AttributionConversionOptions options);
};