1. 引言
本文档定义了一个浏览器 API, 该 API 能够收集经过聚合且具有差分隐私保护的指标。
此 API 的目标是为广告启用归因。
1.1. 归因
在广告中,归因 是识别先于某个感兴趣结果发生的操作, 并将价值分配给这些操作的过程。
广告主感兴趣的操作 主要是广告的展示 (也称为 展示)。 其他操作包括广告点击(或其他交互), 以及未被采用的广告展示机会。
广告所期望的结果 更加多样, 因为它们包括广告主希望通过展示广告来改善的任何结果。 期望的结果也可以称为一次转化, 指将潜在客户“转化”为客户。 可算作转化的内容可能包括 销售、订阅、页面访问和咨询。
对于此 API,操作和结果都是 事件:即只发生一次的事情。 广告归因的独特之处在于, 这些事件可能不会发生在同一个站点上。 广告最常展示在广告主站点以外的站点上。
归因的主要挑战在于维护隐私。 归因涉及连接不同站点上的活动。 归因的目标是找到一次展示, 该展示在转化发生之前已向同一个人展示。
如果归因信息被直接透露, 它将导致不期望的 跨上下文识别, 从而导致跟踪。
本文档通过确保使用聚合服务 来聚合归因信息,从而避免跨上下文识别。 聚合服务被信任用于计算聚合结果, 而不会暴露每个人对该聚合结果所贡献的值。
对每个浏览器实例为给定站点的聚合结果 所贡献的信息量设有严格限制。 差分隐私用于为每次贡献提供额外的隐私保护。
聚合服务操作的详细信息包含在 § 6 聚合中。 所使用的差分隐私设计概述见 § 7 差分隐私。
1.2. 背景
从 Web 的早期开始, 广告就被广泛用于为站点创建提供资金支持。
Web 区别于其他广告场所的一个特征, 是能够获得有关广告活动效果的信息。
Web 广告主能够衡量覆盖率(有多少人看到了广告)、 频次(每个人看到广告的频率)、 以及转化(有多少看到广告的人 之后执行了该广告意图促使其执行的操作)等关键指标。 相比之下,这些衡量比任何其他媒介都更及时且更准确。
衡量效果的代价是隐私。 为了生成准确且全面的信息, 广告业务会对所有 Web 用户的活动进行广泛跟踪。 每个浏览器都会被分配一个跟踪标识符, 通常使用由跨站内容记录的 cookie。 每个感兴趣的操作都会针对该标识符进行记录, 从而形成一个人的在线活动的完整记录。
拥有一个人的详细操作记录使广告主能够推断人们的特征。 这些特征使选择合适广告受众变得更加容易, 从而大幅提升广告效果。 这产生了收集更多信息的强烈激励。
在线广告竞争非常激烈。 展示广告的站点寻求从每个广告位获得最多收益。 广告主则寻求在相对于成本而言最能产生效果的位置投放广告。 这些实体——以及代表它们运作的中介方——所获得的任何竞争优势, 都取决于拥有关于潜在受众的更全面信息。
随着时间推移,感兴趣的操作扩展到几乎包括在线活动的每个方面。 人们还设计出方法,将这些信息与 Web 之外的活动相关联。 一个活跃的交易行业已经形成, 其中有多个个人信息供应商将个人信息用于各种目的进行交易。
1.3. 目标
本文档的目标是定义一种执行广告归因的方式, 且不会导致跟踪。
1.4. 最终用户益处
广告效果衡量会产生新的跨站信息流。 该信息流会产生隐私风险或成本——即跨上下文识别——因此需要以最终用户收益为依据进行正当化。
最终用户通过使用归因所实现的任何收益都是间接的。
访问网站的最终用户 主要通过他们对站点向其展示的任何广告所给予的注意力, 来为“免费”内容或服务付费。 这种“价值”归属于广告主, 广告主进而向站点付款。 站点预期会使用这笔资金 来支持其内容或服务的提供。
参与归因衡量系统 会构成 Web 用户的次级成本。
支持归因可带来更有效的广告, 主要方式是让广告主了解哪些广告效果最好, 以及在何种情况下效果最好。 这些情况可能包括 广告展示的时间和地点、 广告展示给谁, 以及广告本身的细节。
将这些信息连接到结果, 使广告主能够了解哪些情况最常导致 他们最看重的结果。 这使广告主能够在有效广告上投入更多, 在无效广告上投入更少。 这降低了相对于所获价值而言的总体广告成本。[ONLINE-ADVERTISING]
提供广告库存的站点, 例如内容发布者和服务提供商, 会间接受益于更高效的广告。 能够更好展示广告并产生广告主所寻求结果的广告场所, 可以对广告位收取更高费用。
通过投放广告获得支持的站点, 能够更好地提供优质内容或服务。 重要的是,这种支持来自其受众的方式并不均匀。 与其他形式的资金支持相比,这可能更加公平。 那些对广告商品消费倾向或能力较低的人, 可以获得与有能力付费的人相同的广告支持内容和服务。[EU-AD][COPPACALYPSE]
提供由广告支持的“免费”服务的能力 具有可衡量的经济收益, 这些收益源自这些服务的价值。[FREE-GDP]
1.5. 集体隐私效应
如果正确实现,聚合的使用可确保提供给站点的信息 是关于群体而非个人的信息。
因此,该机制的引入代表了一种集体决策, 符合集体隐私的理念。
当参与群体更大时, 参与归因衡量所带来的隐私成本更低。 这是由于聚合会影响站点 从聚合结果中提取有关个人信息的能力。 对于中心化差分隐私尤其如此, 它是本规范所用隐私设计的数学基础。
更大的参与者群组还会产生更具代表性——因而也更有用——的 关于所衡量广告的统计信息。
如果归因是正当的, 这两个因素都会推动为所有用户启用归因。
用户代理采取行动启用归因衡量, 对某些人来说不会受到积极接受。 不同的人对参与广告所带来的成本和收益 有不同感受。 所提出的设计允许人们选择看起来参与了归因, 而不会向站点暴露这一选择;参见 § 9.2 禁用 Attribution API。
1.6. 使用直方图进行归因
归因 试图衡量一个或多个广告投放(展示) 与广告主期望的结果之间的相关性。
在聚合层面考虑时, 关于个人的信息并无用处。 操作和结果需要被分组。
最简单的归因形式根据广告的属性 将展示划分为若干分组, 并统计转化次数。 分组可能由以下属性形成: 广告展示的位置、 展示的内容(“创意”)、 广告展示的时间, 或展示给谁。
这些分组 以及归因到每个分组的转化计数 构成一个直方图。 直方图的每个桶统计 某一组广告的转化次数。
不同的分组可用于不同目的。 例如,按创意(广告内容)分组 可用于了解哪个创意效果最好。
在每次转化时添加一个大于一的值, 可以支持不只是简单计数的功能。 直方图还可以聚合值, 这可用于区分不同结果。 分配给展示的值 称为转化 值。 较高的转化值可用于较大的购买, 或任何价值更高的结果。 转化值也可以在多个展示之间拆分, 以分摊功劳。
2. 操作概述
Attribution API 提供关于两类事件之间关联的聚合信息: 展示和转化。
展示是广告主在任何网站上执行的任何操作。 此 API 不限制可记录为展示的内容。 广告主可能希望衡量的典型操作包括:
-
显示广告。
-
让用户以某种方式与广告交互。
-
不显示广告(尤其用于旨在确认某个广告活动是否有效的受控实验)。
对于此 API,转化是正在衡量的结果。 此 API 不限制什么可以被视为结果。 广告主可能希望衡量的典型结果包括:
-
完成购买。
-
注册账户。
-
访问网页。
本节其余部分描述 Attribution API 如何与聚合服务 结合运作, 以生成聚合归因衡量结果。 该操作如下面的图所示。
2.1. 记录展示
当一个展示发生时, 可以使用 saveImpression() 方法 请求浏览器保存信息。 这包括该展示的一个标识符, 以及关于该展示的一些附加信息。 例如,广告主可能会使用附加信息 来记录该展示是广告浏览还是广告点击。
2.2. 转化或查询展示
在转化时,会创建一个转化报告。 转化报告 是一个加密的直方图贡献, 其中包含来自浏览器先前存储的任何展示的信息。
measureConversion() 方法接受一个受限查询, 该查询用于 告诉浏览器如何构造一个转化报告。 其中包括用于从浏览器已存储的展示中进行选择的值, 分配给所选展示的转化值, 以及构造该转化报告所需的其他信息。
由转化报告创建的直方图按如下方式构造:
-
如果查询未找到展示, 或者该站点的隐私 预算已耗尽, 则构造一个全部由零(0)组成的直方图。
-
如果找到一个或多个匹配展示,浏览器会运行最后 n 次触达 归因逻辑来选择相关展示。提供的转化 值会被添加到直方图中,位置是在归因展示发生时指定的桶。 所有其他桶都设置为零。
浏览器会更新隐私预算存储,以反映已报告的转化。
生成的直方图会根据所选聚合服务的要求 为聚合做好准备,并返回给站点。 这至少涉及对直方图进行加密。
调用此 API 的站点将始终收到有效的转化报告。 因此,站点不会通过此交互了解到其他站点上发生了什么。
2.3. 聚合
站点可以收集它从对此 API 的调用中收到的加密直方图, 并将它们提交给聚合服务。
在从某个站点接收到一组加密直方图后,聚合服务会:
-
确认它先前没有 根据所提供的输入 计算过聚合结果, 并且有足够的转化报告,
-
对直方图求和,包括足够的 噪声, 以生成一个差分隐私的聚合直方图,并且
-
将该聚合结果返回给站点。
我们将聚合服务的最终输出称为 归因结果。
浏览器实现需要拥有一组受信任的聚合服务, 以可靠地执行上述功能。 从所提供的服务集合中, 转化站点 需要 与其所选择的服务达成协议, 由该服务执行聚合。
浏览器可能会建立用于注册聚合服务的项目, 其性质类似于 根存储项目, 用于授权浏览器在验证 Web PKI 证书时 使用的证书颁发机构。 建立这样的项目 不在本文档范围内。
3. API 使用
使用 Attribution API 的站点通常会注册 展示或转化,但在某些情况下, 同一站点可能 两者都做。
要注册一次展示,站点调用 saveImpression()。除收集参数值外, 使用此 API 不需要任何准备,不过 在决定是否使用 Attribution API 时,检查受支持的 aggregationServices 可能很有用。
也可以在向用户代理提供资源时,
通过在 HTTP 响应中包含
`Save-Impression`
标头来注册一次展示。
要请求转化报告,站点调用
measureConversion()。
在调用此 API 之前,站点必须
选择一个受支持的聚合服务。
页面可以从
aggregationServices
中找到的受支持服务中选择任意一个。
所选服务的名称必须在调用
measureConversion() 方法时,
作为
aggregationService
成员提供给
AttributionConversionOptions
字典。
3.1. 站点身份
此 API 依赖 HTML 对站点的定义, 并将其作为其操作所围绕的主要作用域。 它识别三类站点:
-
展示 站点是注册一次展示的站点。 此展示 站点源自 在调用
saveImpression()以存储一次展示时, 顶级源 的相关设置对象。 -
转化 站点是发生转化的站点。 转化站点 源自 在调用
measureConversion()时, 顶级源 的相关设置对象。 -
中介方站点是从任何跨站框架(例如 iframe) 调用 API 的站点。 中介方 站点源自 在调用
saveImpression()或measureConversion()时, 源 的相关设置对象, 除非此源分别与展示站点 或转化 站点同站。
此 API 使用站点 而不是源, 因为它依赖于将所有可能具有隐私后果的活动 与单个实体关联起来。 像 cookie 这样的功能允许 同站源 自由交换隐私相关信息, 否则这些信息可能被用来超出隐私预算。
3.2. Navigator 接口
此 API 的所有功能都附加到
属性。
navigator.attribution
partial interface Navigator { [SecureContext ,SameObject ]readonly attribute Attribution ; };attribution
这提供了三个关键功能:
-
浏览器支持的聚合服务列表(§ 3.3 查找 受支持的聚合服务)
-
请求浏览器保存展示的手段(§ 3.4 保存 展示)
-
请求转化测量的方法(§ 3.5 请求 对转化进行归因)
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;见 § 6.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()
方法。
此函数接受四种不同类型的输入:
-
所选聚合服务, 该服务使用 URL 标识。 选择聚合服务的示例过程 展示了如何选择浏览器支持的服务。
const serviceDetails= { aggregationService: serviceUrl, }; -
聚合衡量的详细信息。 这些值在多个浏览器对 API 的所有调用中 都将保持一致。 这包括直方图的大小 以及可能已消耗的隐私预算量。
const aggregatedMeasurementDetails= { histogramSize: 20 , epsilon: 1 , }; -
一组属性, 全部都是可选的, 用于选择要考虑的展示。 这包括展示可以有多旧 (
lookbackDays)、 可能已保存展示的展示 站点 (impressionSites)、 可能已保存展示的中介方站点 (impressionCallers), 以及matchValues的选择。const selectionDetails= { lookbackDays: 14 , impressionSites: [ "publisher.example" , "other.example" ], impressionCallers: [ "ad-tech.example" ], matchValues: [ 2 ], }; -
归因 逻辑参数。
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 的站点, 包括 展示站点 和 中介 站点。 如果非空, 则只有由所列站点之一记录的 展示 才有资格匹配此 转化。
value, 类型为 unsigned long,默认为1- 转化 值。如果进行了归因且满足隐私 限制,则此值将被编码进 转化报告。
maxValue, 类型为 unsigned long,默认为1- 聚合中包含的所有贡献里的最大 转化 值。 与 epsilon 一起,用于校准将被添加到结果中的随机噪声的分布。 它还用于确定要在此 转化报告 上支出的 隐私预算 量。
credit, 类型为 sequence<double>- 一个由有限正数组成的列表, 描述如何在多个展示之间分配 转化值。 该值会按列表中值的比例 在选中的展示列表之间拆分, 顺序按指定顺序。 如果选中的展示少于此列表中的值, 则忽略此列表中的任何额外项。 缺省时,转化值会分配给单个展示。
3.6. 中介方的角色
此 API 支持中介方 代表顶级站点进行操作。 广告经常委托给负责投放、竞价和衡量的独立运营方。
由中介方保存的展示 会记录中介方站点的身份。 在为转化衡量选择展示时, 可以使用中介方站点 身份来选择展示。
3.7. 直方图构造
从概念上讲,每个已保存的展示 都有一个单一的直方图定义。 每个展示都有一个单一的直方图索引属性, 用于确定分配给该展示的值 在所得直方图中出现的位置。
因此,每次调用 measureConversion()
都需要选择具有相同直方图定义的展示。
尽管这适用于 API 的所有使用,
但当展示
由多个中介方保存和衡量时,
一致定义直方图尤其重要。
调用 measureConversion()
时可能被选择的所有展示
都需要使用相同的直方图定义。
此 API 提供了几种工具,
用于确保只选择正确的展示。
对于已保存的展示:
-
展示用于转化的使用 可以被限制为 仅对一组转化站点上的
measureConversion()可见。 -
展示用于转化的使用 可以被限制为 仅对由一组站点调用的
measureConversion()可见。
这些选项为站点在归因如何选择直方图方面提供了灵活性。
它不排除转化站点使用不同直方图。
可以保存具有不同直方图定义的多个展示,
前提是 measureConversion()
调用
永远不会选择
具有不同直方图定义的展示。
这确保可以通过多次调用 measureConversion(),
将转化归因到
多个直方图。
3.8. 权限策略集成
委托给中介方的能力 由权限策略控制。
本规范定义了两个策略控制特性:
-
调用 saveImpression() API, 由字符串 “
” 标识。save-impression -
调用 measureConversion() API, 由字符串 “
” 标识。measure-conversion
为 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。
4.1.4. 站点名称
展示存储 会保存关于三类站点的信息: 展示站点、 一个可选的中介方站点, 以及一组集合,其元素为转化站点。
这些站点必须全部
采用scheme-and-host 形式,
并使用 "https" 方案。
这意味着,对主机
进行简单字符串序列化就足以标识该站点。
因此,此 API 能够使用简单的字符串
来表示站点。
实现也可以只使用元组的主机部分 在内部表示站点。
-
令 host 为调用主机解析器并传入 input 所返回的值。
-
如果 host 为失败,则返回失败。
-
令 site 为调用获取可注册域并传入 host 所返回的值。
-
如果 site 为 null,则返回失败。
-
如果 site 为 "
localhost",或者如果 site 以 ".localhost" 结尾, 则返回失败。 -
返回一个 ("
https", site) 的方案和主机元组。
对于所含域标签数量多于可注册域的字符串,
此算法也能成功生成一个站点。
例如,"extra.example.com" 会被解析为 "example.com"。
此算法不接受 localhost 域 [RFC6761], 因此,任何依赖提取站点名称的算法在提到 localhost 域时, 或者当前站点(顶级站点或被框架嵌入的站点)是 localhost 域时, 都会失败。 这会使使用本地服务器进行测试和开发变得困难。 实现可以提供一个禁用 localhost 检查的配置, 以帮助测试和开发。
4.2. 用于隐私预算管理的状态
用户 代理会维护若干状态, 这些状态用于管理隐私预算的消耗:
-
纪元开始 时间用于确定纪元何时开始。 此值作为调用 measureConversion() 的副作用进行初始化。
-
一个单一的上次清除浏览历史记录值, 用于跟踪某个站点的浏览活动上次被清除的时间。
-
一个单一的归因预算锁是一个布尔标志, 用于防止对隐私预算存储进行并发操作, 否则可能导致预算超额消耗。
隐私预算 存储、全局隐私预算存储 和展示站点配额存储由扣减隐私和安全预算更新。
与展示 存储一样, 隐私预算 存储和相关存储不使用存储键。 这些存储在如何清除信息方面有一些额外约束; 详见 § 9.7 清除 API 状态。
将归因预算锁定义为布尔标志的选择 是出于规范编写便利。 实现可能更适合使用替代构造。 实现可能能够对此值进行分区, 例如按纪元分区, 以减小任何争用的范围。
4.2.1. 隐私预算存储
隐私预算键 是一个元组, 由以下项目组成:
隐私预算 存储是一个映射,其键为 隐私预算键, 其值为32 位无符号整数。 这些整数以微 epsilon为单位存储值。 一个微 epsilon是 差分隐私 [DP] 中使用的单位 epsilon 值的 百万分之一。
选择 32 位整数会将 epsilon 的设置限制为 小于或等于 4294 的最大 epsilon。 对实现来说,这应该绰绰有余。
全局 隐私预算存储是一个映射,其键为 纪元索引,其值为 以微 epsilon为单位的 32 位无符号整数。
全局隐私预算存储跟踪单一 隐私预算的消耗, 该预算适用于所有站点, 并在每个纪元刷新。 这提供了一个安全限制, 用于抵御能够跨多个站点 关联同一个人活动的对手。
不同于按站点划分的隐私预算存储, 全局隐私预算存储只以纪元索引为键, 而不是以站点为键。
展示 站点配额存储是一个映射,其键为 隐私预算键, 其值为以微 epsilon为单位的 32 位无符号整数。
展示站点配额存储限制任何单个展示 站点在一个纪元中能够贡献的“存量” (与展示相关的隐私预算)。 这可防止单个展示站点 从可能被恶意触发的全局限制中 消耗过多额度。
-
如果 isSingleEpoch,则令 l1NormSensitivity 为 l1Norm,否则为 2 * value。
-
令 valueSensitivity 为 2 * value。
-
令 noiseScale 为 2 * maxValue / epsilon。
-
令 l1NormDeductionFp 为 l1NormSensitivity / noiseScale。
-
令 valueDeductionFp 为 valueSensitivity / noiseScale。
单时期归因 不会跨时期造成任何级联效应。 涉及多个时期的归因会消耗两倍预算, 因为一次变更可能会影响跨时期的归因。 将扣减量加倍是假定已向聚合直方图中添加 与 maxValue / epsilon 成比例的拉普拉斯噪声。
-
令 l1NormDeduction 为 l1NormDeductionFp * 1000000,并朝正 Infinity 舍入。
-
令 valueDeduction 为 valueDeductionFp * 1000000,并朝正 Infinity 舍入。
-
如果 归因预算锁 为 true, 等待直到该值变为 false, 然后将该值设为 true。
-
如果 isSingleEpoch 为 true,则令 deduction 为 l1NormDeduction,否则为 valueDeduction。
-
如果用 key、deduction、valueDeduction 和 impressions 调用检查可用隐私预算的结果 为 false,则执行以下步骤:
-
将 归因预算锁 设为 false。
-
返回 false。
-
-
所有预算检查均已通过,因此执行扣减:
-
令 epoch 为 key 的时期索引组件。
-
如果 deductedGlobalBudgets 不包含 epoch, 则将 epoch 追加到 deductedGlobalBudgets, 并将全局隐私预算 存储[epoch] 减少 valueDeduction。
-
对 impressions 中的每个 impression:
-
将 归因预算锁 设为 false。
-
返回 true。
4.2.2. Attribution API 激活
Attribution API 大致以消耗瞬态激活的 API 为模型, 在这些 API 中,用户激活 会暂时使 API 可用。 有若干差异将此设计 与消耗瞬态激活的 API 区分开来:
-
当发生以下任一情况时,该 API 会在短时间内变得可用:
-
在上次激活之后的实现定义的时长内调用 saveImpression() 或 measureConversion(), 会为该站点启用该 API。
-
每次激活最多使该 API 对一个顶级站点可用。 类似于 瞬态激活, 其中消耗该激活 会导致其他类似 API 不可用, 直到另一次激活发生; 在一个站点上使用该 API 会使该 API 对其他站点不可用。
-
当该 API 被成功使用时, 该 API 会被启用,以供后代可导航对象使用, 这些后代可导航对象属于顶级可遍历对象的活动文档 (也就是说,当前页面上的所有框架,包括跨站点框架) 可以在无需进一步可用性检查的情况下访问该 API。
-
每次激活最多使该 API 对一个站点可用。 导航顶级可遍历对象 到不同的站点时,会禁用该 API。 不过,任何激活, 其中可能包括发起导航的操作, 都可能使该 API 再次可用。
这在效果上大体类似于瞬态激活。
但是,归因激活使用与瞬态激活
分离的状态,
并且该状态以不同方式跟踪。
归因激活状态在顶级可遍历对象上跟踪,
而不是在受影响的 Window
上跟踪。
因此,归因激活会在导航之间持续存在,
从而在激活导致导航的情况下,
能够在加载新页面后的一小段时间内
使用此 API。
拥有独立状态可确保 归因激活不会与消耗瞬态激活的 API 发生交互。 一个消耗激活的 API 不会阻止 Attribution API 可用; 同样,使用 Attribution API 也不会阻止 一个消耗瞬态激活的 API 可用。
独立的状态跟踪可确保 那些消耗用户激活的用户动作 能够由 Attribution API 独立测量。
在导航之间保留激活支持广告中的常见模式。 站点可以使用 Attribution API 检查 交互发生所在站点上的动作, 或后续站点上的动作。
为实现这一点, 每个顶级 可遍历对象都会为 Attribution API 跟踪两项状态:
实现还会将归因激活持续时间 配置为一个实现定义的持续时间。 这不应小于瞬态激活持续时间, 但为了确保导航造成的延迟 不会使 Attribution API 变得不可访问, 更大的值可能是可取的。
实现可以选择延长允许的时间, 以考虑导航期间加载页面内容所涉及的延迟。 固定值可能无法考虑设备或网络中的性能差异。 实现可以基于对性能特征的理解, 延长 归因激活持续时间的值。 或者,实现也可以在页面加载期间暂停任何计时器。
Document
document 中触发激活触发输入事件时,
用户代理必须执行以下步骤——除激活通知步骤之外——并且要在分派该事件之前执行。
在这种情况下,将可导航对象 navigable 设置为 null。
或者,当导航开始,
且用户导航参与为
"browser UI" 时,
执行以下步骤,
将 navigable 设置为受影响的可导航对象,
并将 document 设置为 null。
步骤为:
Document
document,
并在失败时抛出 "NotAllowedError"
DOMException:
-
令 n 为获取 document 的节点可导航对象的结果。
-
令 top 为获取 n 的顶级 可遍历对象的结果。
-
如果 top 的归因启用标志为 true,则返回。
-
令 lastActivation 为 top 的归因激活时间戳。
-
如果 lastActivation 加上归因激活持续时间 小于当前高分辨率时间, 则抛出一个
"NotAllowedError"DOMException。 -
将归因激活时间戳设置为 unix epoch。
-
将 top 的归因启用标志设置为 true。
4.2.3. 纪元开始时间
隐私预算周期(或周期) 标识一段时间。 一个周期的长度固定为一周或 7 天, 其中天定义为 86400 秒。
周期开始时间 是来自挂钟的一个时刻。 对于每个用户代理,一个周期会在一周中随机选择的某个小时开始。 这确保了因隐私 预算达到零而在聚合中产生的任何偏差, 会在所有用户的所有贡献中被平均化。
开始时间 由用户代理在首次需要周期时随机选择——作为调用 获取当前 周期算法的副作用。
周期索引是一个整数, 指代给定的周期。 周期索引用于访问 impression 和周期开始时间。
周期索引作为 相对于某个设定参考点的整数 存储。 本规范中的周期索引 使用周期开始 时间 作为参考点。 用户代理可以选择使用不同的时刻 来表示“零”或参考周期。
本规范中的算法全都使用具体的周期索引, 而不是更抽象的周期。 时间 点会使用获取当前 周期算法, 被转换为对应周期的周期索引。
-
令 start 为周期开始时间。
-
令 elapsed 为 (t − start) / period。
-
将 elapsed 作为整数返回,并向负无穷舍入。
4.2.4. 上次清除浏览历史记录的时间
上次浏览 历史清除是一个使用挂钟的时刻, 用于跟踪浏览历史最后一次被清除的时间。 当任何站点级状态 应用户请求被清除时, 上次浏览历史清除值会被更新 为当前粗化挂钟时间。 该值初始为未设置。
作为可选优化, 如果以下所有条件都为 true,则可以跳过更新上次浏览历史清除:
如果这三个条件都为 true, 则不需要更新上次浏览历史清除。 相反,必须更新隐私 预算存储, 方法是为可以从每个受影响的站点和周期 形成的所有隐私预算 键组合设置值 0 (使用对应的周期索引)。
此优化依赖于用户代理 已保留关于受影响站点 在受影响周期中交互的信息。 这之所以可行,只是因为任何被保留的交互 都可能已经导致预算耗尽。 重置预算是必要的, 以确保不会暴露关于浏览历史空缺的信息。
4.3. 保存展示算法
saveImpression(options) 方法步骤
如下:
-
令 implicitInputs 为从 this 获取 隐式 API 输入的结果。
-
断言:implicitInputs 不为 null。
-
返回使用 options 和 implicitInputs 运行保存展示的结果。
AttributionImpressionOptions
options
和隐式 API
输入 implicitInputs 的情况下保存一个
展示:
-
令 document 为 implicitInputs 的关联文档。
-
令 realm 为 document 的相关领域。
-
如果 document 不被允许使用名为 "
save-impression" 的策略控制特性, 则返回在 realm 中以 一个"NotAllowedError"DOMException拒绝的 promise。 -
在给定 document 的情况下检查 Attribution API 激活, 对任何抛出的原因返回以其拒绝的 promise。
-
验证页面提供的 API 输入:
-
如果 options.
histogramIndex大于或等于实现定义的最大直方图大小, 则返回在 realm 中以一个RangeError拒绝的 promise。 -
如果 options.
lifetimeDays为 0, 则返回在 realm 中以一个RangeError拒绝的 promise。 -
将 options.
lifetimeDays钳制到 最大回溯。 -
如果 options.
conversionSites的大小 大于实现定义的 每个展示的最大 转化站点数, 则返回在 realm 中以一个RangeError拒绝的 promise。 -
令 conversionSites 为一个集合,它是 对 options.
conversionSites中的每个值 调用解析 站点 的结果。 -
如果 conversionSites 中有任何结果为失败,则返回在 realm 中 以一个
"SyntaxError"DOMException拒绝的 promise。 -
如果 options.
conversionCallers的大小 大于实现定义的 每个展示的最大 转化调用方数, 则返回在 realm 中以一个RangeError拒绝的 promise。 -
令 conversionCallers 为一个集合,它是 对 options.
conversionCallers中的每个值 调用解析站点 的结果。 -
如果 conversionCallers 中有任何结果为失败,则返回在 realm 中 以一个
"SyntaxError"DOMException拒绝的 promise。
-
-
并行运行以下步骤:
-
将 impression 构造为一个已保存的展示,由以下内容组成:
-
-
令 result 为一个新的
AttributionImpressionResult。 -
返回在 realm 中以 result 兑现的 promise。
saveImpression() 不返回指示该展示是否被记录的状态。 这会最大限度地降低检测 Attribution API 是否已禁用的能力。
实现必须尝试缓解可能暴露 API 状态的侧信道。 例如,返回的 promise 的兑现 不以将 impression 保存到展示存储为前提,以确保 兑现所需时间不依赖于 现有展示的数量或 API 是否已启用。
隐式 API 输入是一个具有以下字段的结构体:
4.4. 衡量转化算法
measureConversion() 方法异步完成, 在 Attribution 任务源上排队工作。
measureConversion(options) 方法
步骤为:
-
令 implicitInputs 为从 this 获取隐式 API 输入的结果。
-
断言:implicitInputs 不为 null。
-
返回用 options 和 implicitInputs 运行测量一次转化的结果。
AttributionConversionOptions
options
和隐式 API
输入 implicitInputs 的情况下测量一次
转化:
-
令 document 为 implicitInputs 的关联文档。
-
令 realm 为 document 的相关领域。
-
如果 document 不被允许使用名为 "
measure-conversion" 的策略控制特性, 则返回在 realm 中以 一个"NotAllowedError"DOMException拒绝的 promise。 -
检查归因 API 激活 给定 document,返回 一个被拒绝的 promise,其拒绝原因是 任何抛出的原因。
-
令 validatedOptions 为 验证 options 的结果, 对任何抛出的原因返回以其拒绝的 promise。
-
令 promise 为 realm 中一个新的 promise。
-
并行运行以下步骤:
-
如果 Attribution API 已启用, 则将 report 设置为用 validatedOptions、 implicitInputs 的顶级站点、 implicitInputs 的中介站点以及 implicitInputs 的时间戳 运行执行归因并填充 直方图的结果。
-
令 aggregationService 为 validatedOptions 的聚合 服务。
-
切换 aggregationService.
protocol的值:dap-18-histogram-
执行以下步骤:
-
令 result 为一个具有以下项的
AttributionConversionResult:report-
encryptedReport
-
在 Attribution 任务源上排队一个任务, 以用 result 兑现 promise。
-
返回 promise。
实现必须尝试缓解可能暴露 API 状态的侧信道。 例如,理想情况下,返回的 promise 的兑现所需时间 不应依赖于已存储或匹配的展示数量 或 API 是否已启用。
已验证的 转化选项是一个具有以下字段的结构体:
| 聚合 服务: | 一个 AttributionAggregationService
实例。
|
|---|---|
| Epsilon: | 一个有限正数。 |
| 直方图大小: | 一个32 位无符号整数。 |
| 回溯: | 一个正持续时间。 |
| 匹配值: | 一个由32 位无符号整数组成的集合。 |
| 展示站点: | 一个由站点组成的集合。 |
| 展示 调用方: | 一个由站点组成的集合。 |
| 权重: | 一个由数字组成的列表。 |
| 值: | 一个32 位无符号整数。 |
| 最大值: | 一个32 位无符号整数。 |
AttributionConversionOptions
options:
-
如果 aggregationServices 不包含 一个条目,其键为 options.
aggregationService, 则抛出ReferenceError。 -
令 aggregationService 为从
AttributionAggregationServices获取值的结果, 给定 options.aggregationService。 -
如果 options.
epsilon小于或等于 0,或者大于最大 epsilon, 则抛出RangeError。 -
如果 options.
histogramSize为 0,或者大于实现定义的最大直方图 大小, 或者大于 options.aggregationService的最大聚合服务 直方图大小(如果有), 则抛出RangeError。 -
如果 options.
value为 0, 则抛出RangeError。 -
如果 options.
value大于 options.maxValue, 则抛出RangeError。 -
如果 credit 为空,则抛出
RangeError。 -
如果 credit 的任何项 不是有限的, 或者小于或等于 0, 则抛出一个
RangeError。 -
如果 credit 的大小超过实现定义的 最大权重值数量,则抛出
RangeError。 -
如果 options.
lookbackDays存在,则令 lookback 为其天数, 否则为最大回溯天数。 -
如果 lookback 为 0 天,则抛出
RangeError。 -
如果 options.
matchValues的大小 大于实现定义的最大 匹配值数量, 则抛出RangeError。 -
令 matchValues 为用 options.
matchValues运行创建集合的结果。 -
如果 options.
impressionSites的大小大于 实现定义的转化的最大展示 站点数, 则抛出RangeError。 -
令 impressionSites 为一个集合,它是 对 options.
impressionSites中的每个值 调用解析 站点 的结果。 -
如果 impressionSites 中有任何结果为失败,则抛出一个
"SyntaxError"DOMException。 -
如果 options.
impressionCallers的大小大于 实现定义的转化的最大 展示调用方数, 则抛出RangeError。 -
令 impressionCallers 为一个集合,它是 对 options.
impressionCallers中的每个值 调用解析 站点 的结果。 -
如果 impressionCallers 中有任何结果为失败,则抛出一个
"SyntaxError"DOMException。 -
返回一个具有以下字段的已验证转化选项:
4.4.1. 归因逻辑
归因逻辑 确定转化值如何分配到直方图桶。
undefined intermediarySite,以及
时刻
now 的情况下执行
归因并填充直方图:
-
令 currentEpoch 为使用 now 调用获取当前纪元 的结果。
-
令 startEpoch 为使用 now 调用获取归因的起始 纪元 的结果。
-
如果 currentEpoch 等于 earliestEpoch,则令 isSingleEpoch 为 true,否则为 false。
-
令 l1Norm 为 0。
-
如果 isSingleEpoch 为 true:
-
令 deductedImpressionQuotas 为一个新的集合。
-
令 deductedGlobalBudgets 为一个新的集合。
-
对于从 startEpoch 到 currentEpoch(包含两端)的每个 epoch:
-
如果 matchedImpressions 为 空,则返回使用 options 的直方图大小 调用创建全零直方图的结果。
-
令 histogram 为使用 matchedImpressions、 options 的直方图大小、 options 的值和 options 的功劳 调用使用最后 N 次触达归因 填充直方图的结果。
-
返回 histogram。
4.4.2. 通用展示匹配逻辑
undefined intermediarySite、
周期索引 epoch,以及
时刻
now:
4.4.2.1. 最后 N 次触达归因
-
令 sumCredit 为 credit 的项之和。
-
令 roundedCredit 为一个新的列表。
-
对于 credit 的每个 item,执行以下操作:
-
令 normalizedCredit 为 value * item / sumCredit。
-
将 normalizedCredit 追加到 roundedCredit。
-
-
令 idx1 为 0。
-
对于 roundedCredit 的索引中移除第一个项后的每个 n,执行以下操作:
-
令 idx2 为 n。
-
令 frac1 为 roundedCredit[idx1] − floor(roundedCredit[idx1])。
-
令 frac2 为 roundedCredit[idx2] − floor(roundedCredit[idx2])。
-
如果 frac1 和 frac2 都等于零,则继续。
-
如果 frac1 + frac2 大于 1,则令 incr1 为 1 − frac1,并令 incr2 为 1 − frac2。
-
否则,令 incr1 为 −frac1,并令 incr2 为 −frac2。
incr1 表示要增加 roundedCredit[idx1] 的量,以使其成为整数; incr2 和 idx2 也类似。 注意,这些值可以为负。
-
令 p1 为 incr2 / (incr1 + incr2)。
p1 的值表示 idx1 中的项被舍入为整数的概率。 当 incr1 + incr2 为 0 时会发生除以零, 这只有在 frac1 和 frac2 都为整数(要么都恰好为 0,要么都恰好为 1)时才可能。在这种情况下,idx2 不需要 舍入,因此我们直接跳过它。
-
令 r 为 0 到 1(包含两端)之间的随机 double。
-
如果 r 小于 p1,则令 incr 为 incr1, 并交换 idx1 和 idx2 的值。
-
否则,令 incr 为 incr2。
-
将 roundedCredit[idx2] 增加 incr。
-
将 roundedCredit[idx1] 减少 incr。
-
-
令 integerCredit 为将 roundedCredit 中每个项通过舍入到最接近的整数 转换为整数的结果, 半值情况向远离零的方向舍入。
-
返回 integerCredit。
这个最终舍入步骤仅用于处理微小的浮点 加法和减法误差未能完全移除 roundedCredit[idx1] 的小数部分的情况。半值舍入模式 实际上永远不会发生,选择该模式是为了匹配 C++
std::round行为,以便实现。该算法旨在:1)在各分配之间精确分配总计 value 的值; 2)保持 integerCredit 的期望值恰好等于 归一化功劳 (即 credit * value / sumCredit,其中 * 表示逐元素 相乘); 3)任何分配都不会产生大于 1 的误差。
4.5. 设置实现定义值
本规范标识了若干实现定义值。 本节包括一些给实现的建议, 关于如何最好地设置这些值。
实现会为 lifetimeDays
和
lookbackDays
设置一个实现定义的最大回溯。
最大回溯是一个
正整数天数。
为这些值设置不同最大值没有意义,
因为两个值中较小的那个
将决定哪些已保存的展示可用于转化。
实现必须将最大回溯设置为至少 30 天。 在此期间内,实现应当尝试为每个展示站点保留 至少 1000 个展示。
在可能的情况下,实现应当在超出这些关于时间和数量的推荐限制后 继续保留展示。 可用于存储展示的容量同时取决于 保留展示数据所需的存储空间 以及生成转化报告所需的处理时间。 如果站点请求存储超出可用容量的展示、 如果用户请求这样做(见§ 9.2 禁用 Attribution API), 或出于实现定义原因, 实现可以在达到这些限制之前丢弃展示。
实现可能选择不保留展示的一个可能原因是, 该站点未获得足够的用户参与度。
对于传递给 saveImpression()
和 measureConversion()
的站点列表,会选择一个实现定义值。
每个展示的最大转化站点数
是对 conversionSites
的值数量的限制;
实现必须将此值设置为至少
5。
每个展示的最大转化调用方数
和 转化的最大展示调用方数
分别是对 conversionCallers
和 impressionCallers
的值数量的限制;
实现必须将这些值分别设置为至少 10。
转化的最大展示站点数
是对 impressionSites
的值数量的限制;
实现必须将此值设置为至少
30。
会为
最大
权重值数量选择一个实现定义值,
该值是对 credit
的值数量的限制;
实现必须将此值设置为至少
10。
会为
最大
匹配值数量选择一个实现定义值,
该值是对 matchValues
的值数量的限制;
实现必须将此值设置为至少
30。
由 measureConversion() 生成的直方图大小 同时受一个实现定义的最大直方图大小 和最大聚合服务直方图大小约束。 没有为最大直方图大小设置最小值, 因为预期聚合技术的选择 将会设置一个限制。 最大聚合服务直方图大小 将是一个由聚合服务所使用技术的选择 决定的固定值; 它不是实现定义的。
4.5.1. 隐私和安全限制参数配置
用户 代理通过为以下内容定义值, 来配置隐私预算和安全限制:
-
每站点 隐私预算(εsite)是实现定义的。 使用差分隐私聚合的实验表明, 在 1(更注重隐私)到 10(更注重性能)之间的范围内取值, 可以实现合理的性能。
-
每周期全局隐私预算(εglobal) 是每个周期内 跨所有站点可用的 最大隐私预算, 以微 epsilon为单位指定。 实现应当将此值设置为每个站点每个周期的隐私预算的倍数。
-
每周期展示站点配额 (εimp-quota)是每个周期内 单个展示站点 能使其从全局隐私预算中被消耗的 最大隐私预算, 以微 epsilon为单位指定。 实现应当将此值设置为每个站点每个周期的隐私预算的倍数。
将安全限制配置为每站点预算的倍数, 会决定多个站点可以如何使用该 API。 在设置此倍数时, 实现需要考虑它们预期中 可能会使用其预算的站点数量, 也许还要向下调整, 以允许存在未完全使用其预算的站点。
将安全限制设置为每站点预算的倍数, 可确保耗尽共享限制需要许多站点协作, 使其主要作为一种防止滥用的手段有用, 而不是作为主要的隐私机制。
5. HTTP API
5.1. 保存展示
`Save-Impression` 是一个
字典结构化标头,
设置在响应上,请求用户代理调用
saveImpression() API。
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,运行以下步骤:
-
令 dict 为使用 input_bytes 设置为 input、 field_type 设置为 "
dictionary" 解析 结构化字段的结果。 -
如果解析失败,则返回错误。
-
令 histogramIndex 为 dict["
histogram-index"] 带默认值undefined。 -
令 opts 为一个新的
AttributionImpressionOptions, 其项目如下:histogramIndex-
histogramIndex
-
如果 dict["
conversion-sites"] 存在:-
令 conversionSites 为其值。
-
如果 conversionSites 不是内部 列表,或者 conversionSites 的任何项 不是字符串, 则返回错误。
-
将 opts.
conversionSites设置为 conversionSites。
-
-
如果 dict["
conversion-callers"] 存在:-
令 conversionCallers 为其值。
-
如果 conversionCallers 不是内部 列表,或者 conversionCallers 的任何项 不是字符串, 则返回错误。
-
将 opts.
conversionCallers设置为 conversionCallers。
-
-
如果 dict["
match-value"] 存在:-
令 matchValue 为其值。
-
将 opts.
matchValue设置为 matchValue。
-
-
如果 dict["
lifetime-days"] 存在:-
令 lifetimeDays 为其值。
-
如果 lifetimeDays 不是正整数, 则返回错误。
-
将 opts.
lifetimeDays设置为 lifetimeDays。
-
-
返回 opts。
5.2. 衡量转化
`Measure-Conversion` 是一个
字典结构化标头,
设置在响应上,请求用户代理调用
measureConversion() API。
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,运行以下步骤:
-
令 dict 为使用 input_bytes 设置为 input、 field_type 设置为 "
dictionary" 解析 结构化字段的结果。 -
如果解析失败,则返回错误。
-
令 aggregationService 为 dict["
aggregation-service"] 带默认值undefined。 -
如果 aggregationService 不是字符串,则返回 错误。
-
令 histogramSize 为 dict["
histogram-size"] 带默认值undefined。 -
令 reportUrlString 为 dict["
report-url"] 带默认值undefined。 -
如果 reportUrlString 不是字符串,则返回 错误。
-
令 reportUrl 为使用 baseUrl 将URL 解析器应用于 reportUrlString 的结果。
-
如果 reportUrl 为失败,则返回错误。
-
如果 reportUrl 不是潜在可信 URL,则返回错误。
-
如果 reportUrl 的方案不是 "
https",则返回错误。 -
令 opts 为一个新的
AttributionConversionOptions, 其项目如下:aggregationService-
aggregationService
histogramSize-
histogramSize
-
如果 dict["
lookback-days"] 存在:-
令 lookbackDays 为其值。
-
如果 lookbackDays 不是正整数, 则返回错误。
-
将 opts.
lookbackDays设置为 lookbackDays。
-
-
如果 dict["
match-values"] 存在: -
如果 dict["
impression-sites"] 存在:-
令 impressionSites 为其值。
-
如果 impressionSites 不是内部 列表,或者 impressionSites 的任何项 不是字符串, 则返回错误。
-
将 opts.
impressionSites设置为 impressionSites。
-
-
如果 dict["
impression-callers"] 存在:-
令 impressionCallers 为其值。
-
如果 impressionCallers 不是内部 列表,或者 impressionCallers 的任何项 不是字符串, 则返回错误。
-
将 opts.
impressionCallers设置为 impressionCallers。
-
-
返回 (opts, reportUrl)。
-
令 headers 为一个新的标头列表,其中包含一个名为
"Content-Type"、值为 "application/dap-report" 的标头。注:如果
AttributionAggregationProtocol将来获得除dap-18-histogram之外的值,则这里需要更新。 -
令 request 为一个具有以下属性的新请求:
-
获取 request,并可在发生错误时重试。
5.3. Fetch 猴子补丁
-
如果 request 的目标不是以下之一, 则返回:
""、"audio"、"image"、"script"、"track"、"video"。 -
令 implicitInputs 为从 request 的客户端 获取隐式 API 输入的结果, 并使用 response 的URL 的源。
-
如果 implicitInputs 为 null,则返回。
-
令 saveImpressionHeader 为从 response 的标头列表中 获取
`的结果。Save-Impression` -
如果 saveImpressionHeader 不是 null:
-
令 measureConversionHeader 为从 response 的标头列表中 获取
`的结果。Measure-Conversion` -
如果 measureConversionHeader 不是 null:
-
令 parseConversionResult 为解析 measureConversionHeader 的结果。
-
如果 parseConversionResult 不是错误:
-
按如下方式修改 HTTP-network fetch:
如果 includeCredentials 为 true,则用户代理应该在给定 request 和 response 的情况下解析并存储响应
Set-Cookie标头。
之后添加以下步骤
-
使用 request 和 response 处理 Attribution 标头。
6. 聚合
聚合 服务接收多份归因信息, 并生成一个聚合指标。
用户代理实现对于聚合会有不同的要求。 但是,聚合过程具有一些共同要素。
首先,用户代理将需要被配置, 或以其他方式获得, 关于聚合服务的信息。 这包括所支持的聚合方法 以及任何所需的配置。
每种聚合方法都需要定义 直方图如何:
-
为聚合做准备,
-
加密,
-
标注任何必要的元数据,以及
-
提交给聚合服务以进行聚合。
聚合方法还需要定义 站点如何获得聚合结果。
6.1. 多方计算聚合
多方计算 (MPC) 系统是指 涉及多个独立实体, 它们协同计算一个约定函数的系统。
本规范使用基于 Prio [PRIO] 和 Distributed Aggregation Protocol(DAP) [DAP] 的 MPC 系统。 这是一个两方 MPC 系统,其特征在于 依赖客户端提供的输入正确性证明。 这允许非常高效的 MPC 操作, 代价只是提交到系统的数据大小适度增加。
使用 MPC 的聚合服务 由两个或更多独立服务组成, 它们协作计算预定义函数。
MPC 提供的基本保证是: 只会向任何实体揭示函数的已定义输出, 以及明确定义的泄露。
MPC 保证仅在 参与实体的某个子集是诚实的范围内成立。 对于 Prio 中使用的两方 MPC, 只要任一 MPC 操作者保持诚实, 隐私——即输入的机密性——就会得到维护。 这种 MPC 配置不防止 任一 MPC 操作者 破坏输出。
6.1.1. Prio 和 DAP
dap-18-histogram
聚合方法使用 Prio [PRIO]
和 Distributed Aggregation Protocol(DAP)[DAP]。
具体来说,此聚合方法使用
Prio3L1BoundSum [PRIO-L1]
可验证分布式聚合函数(VDAF)[VDAF]。
DAP 和 Prio3L1BoundSum 实例化定义了报告如何准备、 加密并提交以进行聚合。 DAP 还定义了如何获得聚合值, 以及用户代理需要获得 关于聚合服务的哪些配置。
在使用 Prio3L1BoundSum 时, 报告包含一个分布式零知识证明, 该证明允许参与 MPC 的节点 确认所提交直方图的和小于某个设定值。 Prio3L1BoundSum 只能 验证直方图的和 严格小于二的幂。 也就是说,证明确认 该和小于 2n,其中 n 为正整数值。
为了构造报告,
会基于一个值生成证明,
该值是大于 maxValue
的下一个二的幂。
这意味着 聚合服务无法拒绝
介于 maxValue
和下一个二的幂之间的报告。
因此,恶意的用户代理可能会生成一个报告,
其对聚合直方图的贡献
最多可达到 maxValue
值的两倍。
该证明确保当 maxValue
等于 2n − 1 时,
不存在超额贡献的机会;
任何此类攻击的相对影响都可以通过
将 maxValue
设置得尽可能接近 2n − 1
且受其他约束允许来降低。
6.1.2. DAP 扩展
对于此应用,需要 DAP 的扩展 [DAP-ATTRIBUTION] :
-
收集者 身份 (
collector_identity) 标识负责 请求聚合的实体。 此扩展的值编码 API 调用者的身份, 即中介站点或转化站点。 收集者身份扩展适用于整个 DAP 任务。 -
预算 来源 (
budget_source) 标识已经支出隐私预算的实体。 此扩展的值编码转化站点的身份。 预算来源扩展适用于整个 DAP 任务。 -
隐私 预算 (
privacy_budget) 确保聚合服务不会聚合 所获得隐私预算 少于聚合任务配置值的报告。 隐私预算扩展适用于每个报告。
用户代理使用这些扩展来构造 它们生成的报告。
6.1.3. 用于 DAP 的报告加密
undefined intermediarySite,
时刻
now,
以及由整数组成的列表 histogram:
-
令 length 为 histogram 的大小。
-
令 maxValue 为 options.最大值。
-
令 chunkLength 为 (Math.ceil(log2(maxValue + 1)) + 1) * length 的平方根, 四舍五入到最接近的整数。
-
令 vdaf 为新的 PrioL1BoundSum VDAF [PRIO-L1] 实例, 传入 length、maxValue 和 chunkLength。
-
令 microEpsilon 为 options.epsilon 乘以 1,000,000,然后向正无穷方向舍入。
-
如果 intermediarySite 不是
undefined, 则令 caller 为 intermediarySite, 否则为 topLevelSite。 -
令 taskConfig 为对
TaskConfiguration实例进行编码 所产生的字节 序列, 如 第 4.2 节 的 [DAP] 中所定义,并具有 以下值:-
空的
task_info。 -
leader_aggregator_endpoint设置为 DAP Leader 的序列化 URL, 取自 options.Aggregation Service 中所选聚合服务的 实现定义的定义。 通过使用配置的 URL 和false(用于排除片段)调用URL 序列化器 来产生编码后的值。 -
helper_aggregator_endpoint设置为 DAP Helper 的序列化 URL, 取自 options.Aggregation Service 中所选聚合服务的 实现定义的定义, 使用与leader_aggregator_endpoint值相同的过程产生。 -
time_precision值为 5。 -
min_batch_size值为 20。 -
batch_mode值为 TBD(参见 Distributed Aggregation Protocol (DAP) Extensions for the Attribution API § batch-mode)。 -
空的
batch_config。 -
vdaf_type值为 7(参见 A Prio Instantiation for Vector Sums with an L1 Norm Bound on Contributions § dap)。 -
vdaf_configuration按照 PrioL1BoundSum A Prio Instantiation for Vector Sums with an L1 Norm Bound on Contributions § dap 编码, 并使用 length、maxValue 和 chunkLength。
-
-
令 taskID 为字节 序列,该字节序列通过 Task Binding and In-Band Provisioning for DAP § task-id 中描述的过程产生, 并传入 taskConfig。
-
令 ctx 为通过拼接 字符串
dap-18的编码值 和 taskID 而形成的字节 序列, 如 第 4.4.2.1 节 的 [DAP] 中所定义。 -
令 reportID 为从密码学安全随机源采样的 16 字节 [RFC4086]。
-
令 rand 为从密码学安全随机源采样的 128 字节 [RFC4086]。
-
令 publicShare、inputShares 为调用 vdaf.
shard()的结果, 如 第 4.1 节 的 [VDAF] 中所定义, 并使用 ctx、histogram、reportID(作为 VDAF 的 "nonce" 参数) 和 rand。 -
令 time 为如下整数:将从 Unix 纪元到 now 的持续时间 除以 5 秒的持续时间所得的结果, 并向负无穷方向舍入。
-
令 extensions 为从16 位无符号整数到字节序列的映射, 由以下内容组成:
-
隐私 预算的扩展码点, 映射到 microEpsilon 的值, 该值通过使用 UINT32、 值 microEpsilon 和
false(用于isLittleEndian)调用NumericToRawBytes来编码。
-
-
令 reportMetadata 为编码后的 DAP
ReportMetadata, 它由 reportID、time 和 extensions 生成。 -
令 encryptedInputShares 为空的 列表。
-
对 inputShares 的每个 share, 遵循 第 4.4.2.1 节中描述的用于加密 share 的方法:
-
令 pkR 为来自对应角色的公钥,该公钥来自为 options.Aggregation Service 所指示的聚合服务 获取的聚合服务 HPKE 配置。
"dap-18-histogram" 的 URL 预期用于标识 DAP Leader 角色。 实现需要静态地获取两个 Aggregator 的 HPKE 配置; 参见 § 9.4 未配置的浏览器。 HPKE 配置不得按需获取, 因为所花费的时间会向
measureConversion()的调用者泄漏信息。 -
令 serverRole 为一个字节,其值 对第一个条目(Leader)为 2, 对第二个条目(Helper)为 3。
-
令 info 为通过拼接以下内容形成的字节 序列: 字符串
dap-18 input share的编码值、 值为 0x01 的字节,以及 serverRole。 -
令 inputShareAAD 由 taskID、reportMetadata、publicShare 和 taskConfig 按照
InputShareAad的结构构造。 -
令 plaintextShare 由 空集合(用于
private_extensions)和 share(用于payload) 按照PlaintextInputShare的结构构造。 -
令 encryptedShare 为调用 hpke.
Seal<mode_base>()的结果, 传入 pkR、info、inputShareAAD 和 plaintextShare。 -
将 encryptedShare 追加到 encryptedInputShares。
-
-
令 report 为编码后的 DAP
Report, 它由 reportMetadata、publicShare、 encryptedInputShares (这两个值分别为 leader 和 helper 加密输入 share), 以及从 DAP aggregators 获取的聚合服务 HPKE 配置 生成。 -
返回 report。
此算法复现了 DAP 相关规范的一些细节。 如果本文档与那些规范之间存在差异, 则这是本文档中的非故意错误。 与 DAP 交互时始终遵循被引用的规范。
6.2. 抗重放要求
浏览器生成的转化报告 被绑定到请求该报告的站点 所支出的隐私 预算金额。
聚合 服务必须保证 它不会多次接受同一报告。
7. 差分隐私
此设计使用差分隐私的概念 作为其隐私设计的基础。 [PPA-DP]
差分隐私 是隐私的一种数学定义, 可以保证系统所揭示的 私有信息量。 [DP] 差分隐私不是此系统中 保护隐私的唯一手段, 但它是定义和分析最严格的一种。 因此,它提供最强的隐私保证。
差分隐私使用随机噪声 来隐藏对聚合数据集的 私有数据贡献。 噪声的作用是隐藏 对数据集的个体贡献, 同时保留任何聚合分析的有用性。
要应用差分隐私, 必须定义要保护哪些信息。 在此系统中,受保护的信息是 单个用户配置文件的展示, 位于单个用户代理上, 跨单个周期, 针对注册转化的单个网站。 § 7.1 隐私单元更详细地描述了此设计的含义。
此归因设计使用一种 称为个体差分隐私的差分隐私形式。 在此模型中,每个用户代理都分别负责 确保限制其贡献的 信息。
此 API 的个体差分隐私设计 有三个主要组成部分:
-
用户代理限制(使用隐私预算) 通过转化报告离开设备的 关于展示的信息量。 § 7.2 隐私预算对此进行了更深入的探讨。
-
聚合 服务确保任何给定的转化报告 仅按照用户代理 为其核算的隐私预算使用。 § 6.2 抗重放要求更详细地描述了对聚合 服务的要求。
-
噪声由聚合服务添加。 § 7.3 差分隐私机制详述了可能 使用的机制。
这些措施共同限制了 为每个隐私单元释放的信息。
7.1. 隐私单元
差分隐私的实现 需要清晰定义要保护的内容。 这称为隐私 单元, 它表示接收隐私保护的实体。
此系统采用的隐私单元 是三个值的组合:
这些值中的任何一个发生变化都会产生新的隐私单元, 从而产生单独的隐私预算。 一个人访问的每个站点 在每个周期中 都会收到有界数量的信息。
理想情况下,隐私单元是 单个人。 虽然这很理想,但由于多种原因, 无法开发一个有用的系统 来保证与某个人完全对应:
-
人们使用多个浏览器和多个设备, 通常并不协调。
-
覆盖所有网站的单元 可能会被一个站点耗尽, 从而拒绝其他站点获得任何信息。
-
广告是一项持续活动。 如果不为新数据分配隐私预算, 站点可能会永远耗尽其预算。
7.1.1. 隐私属性及其局限性的形式化分析
Attribution 中的隐私保护是多层的:
-
按站点预算限制任何单个转化站点可以了解用户多少信息。
-
全局预算提供后备限制,限制所有站点可以了解用户多少信息。
-
展示站点配额限制转化站点可以了解用户在任何单个 展示站点上的活动多少信息。
-
每次用户操作后维护的计数器限制有多少站点可以向 API 存储数据或从 API 学习信息。
本规范中的形式化隐私分析基于两篇论文。 第一篇 [PPA-DP] 建立了设备上个体 DP 核算的理论。 第二篇 [PPA-DP-2] 将分析扩展到 按站点预算和全局预算所提供的数学隐私保证。
按站点预算应被视为主要隐私保护。按站点预算应配置为 提供有意义的 DP 保证。 但是,[PPA-DP-2] 中的分析 确定了两个会限制这些保证的假设:
-
数据生成中没有跨站点自适应性。 站点的可查询数据流(展示 和转化)必须独立于来自其他站点的过去 DP 归因 结果生成。
-
没有通过跨站点共享限制发生泄露。 来自一个站点的查询不得影响向其他站点发出哪些报告。
简而言之,这两个假设在实践中都无法成立。
需要“没有跨站点自适应性”这一假设,是因为系统涉及多个站点, 它们可能会随时间与同一用户交互。 站点会基于彼此的 DP 测量来改变向用户展示的广告。例如,如果一个 广告主从归因 结果中了解到如何制作更好的广告,那么一些用户可能会在他们的站点上转化, 而不是在竞争对手的站点上转化。在这种情况下,一个站点学到的内容——只计入 其自身按站点预算——改变了其竞争对手可见的数据(或数据缺失),但 这并未计入这些竞争对手的按站点预算。
任何提供连续测量的系统都具有此属性,因此唯一的结论只能是接受 这一局限。这一局限也是设置全局 DP 预算和共享配额的理由之一, 它们引出了第二个假设。
当存在跨多个站点的共享限制时,需要“没有跨站点泄露”这一假设。 这种共享限制的一个例子是旨在提供全局 DP 保证的全局安全限制。 如果某些站点的 measureConversion() 请求导致 达到共享限制,则发送给其他站点的报告可能会被过滤。例如,知道自己有展示的站点 会了解到共享限制是否已达到的某些信息。尽管这些信息是聚合且有噪声的, 但它仍然是关于耗尽其预算的站点的信息,超出了该站点的按站点预算。
通过共享限制发生的泄露促使这些限制只作为限制滥用的手段来使用。将共享 限制设置为按站点预算的大倍数,会使得试图利用共享限制至少需要同样多的站点 进行协调。倍数越大,共享限制作为隐私保护手段就越不有用, 而更适合作为防止拒绝服务或类似形式滥用的手段。
相比之下,分析表明,全局预算可以在没有这些局限的情况下实现并提供可靠的 全局个体 DP 保证。但是,为了支持许多站点使用 API, 全局预算需要配置为按站点预算的一个显著倍数。这意味着 它提供的 DP 保证虽然不依赖任何假设,但单独而言无法提供有意义的 DP 保护。因此,按站点预算提供主要 DP 保证。全局预算可被视为 在恶意站点协同攻击时的后备。
全局 DP 预算还可以防护能够跨多个站点关联用户身份 以合并按站点预算的站点。按站点模型没有考虑这种可能性,尽管某些 站点通常具有这种能力。值得注意的是,这包括身份提供者、接收用户 标识符(如电子邮件地址或电话号码)的站点、成功使用导航跟踪 [NAV-TRACKING-MITIGATIONS] 的站点,以及因任何原因能够使用 跨站点 cookie 的站点 [WEB-WITHOUT-3P-COOKIES]。跨 多个站点使用 Attribution 可能给这些站点带来协调挑战,但站点可能具有 将活动关联到单个人的能力,这一点在对系统隐私进行整体分析时 不能忽视。
7.1.2. 浏览器实例
每个浏览器实例管理单独的隐私预算。
浏览器实例之间的协调可能是可行的, 但并不预期如此。 这种协调可能通过减少释放的信息总量 来改进隐私。 它也可能通过允许一个浏览器实例上的展示 在另一个浏览器实例上转化 来改进归因的效用。
跨不同实现的协调 目前超出此工作的范围。 实现可以在已知属于同一个人的实例之间 执行一些协调, 但这不是强制性的。
7.1.3. 按站点限制
释放给网站的信息是基于站点进行的。 这与其他隐私相关功能中使用的同一边界一致。
更细的隐私单元,例如源, 会使获取额外信息变得微不足道。 可以从多个源收集 关于同一个人的信息。 然后可以利用站点内信息的自由流动 将这些信息合并, 例如使用 cookie [COOKIES] 或类似机制。
§ 7.2.2 安全限制讨论了利用此限制的攻击, 以及用户代理可能实现的一些额外安全 限制 来防止这些攻击。
7.1.4. 隐私预算周期
站点接收单独的差分隐私预算, 用于查询在每个隐私 预算周期 (或周期)中 记录的展示。
此预算适用于向用户代理 注册并随后被查询的展示, 而不是转化。
从分析 [PPA-DP] 的角度来看, 每个周期的 展示形成单独的 数据库。 有限的隐私预算 会在对每个数据库进行的所有查询中强制执行。
从跨多个周期的展示 生成转化 报告具有隐私后果。 对网站的一次访问可以向该站点提供 跨许多周期的活动信息。 这只要求 在整个期间转化站点 被标识为 展示的目标。 可查询的周期数量由用户代理限制。
目标是设置一个尽可能大的周期。 更长的时间段允许更好的隐私/效用平衡, 因为站点可以在任何时间点 被分配更大的总体预算, 同时保持总体隐私损失率较低。 但是,更长的间隔意味着 更容易完全耗尽隐私预算, 从而在下一次刷新前得不到任何信息。
将周期时长设置为一周的决定在很大程度上是任意的。 预计一周足以让站点 在决定如何花费隐私预算时 具有一定灵活性, 而不需要仔细规划以考虑 未来几天或几周内可能发生的变化。
§ 7.2 隐私预算更详细地描述了预算过程。
7.2. 隐私预算
浏览器维护隐私 预算, 这是一种限制隐私损失量的手段。
本规范使用一种个体形式的 (ε, δ)-差分隐私作为其基础。 在此模型中,隐私损失使用值 ε 来度量。 δ 值由聚合服务 在向聚合结果添加噪声时处理。
每个用户代理实例负责 管理隐私预算。
每个被请求的转化报告 都指定一个 ε 值, 表示该报告消耗的隐私预算量, 以及转化报告中可返回值的最大值。
7.2.1. 隐私预算扣除
在为转化报告搜索展示时, 用户代理会从保存这些展示所在的隐私预算周期的预算中 扣除指定的 ε 值。 如果该周期的隐私预算 不足, 则不会使用该周期中的展示。
每当转化 站点调用 measureConversion() 时, 会对归因 逻辑所选择的展示 所来自的周期 扣除隐私预算。
可能会在标记为“现在”的时间请求一个转化 报告。 该转化报告选择用黑色圆圈标记的展示, 对应于来自站点 B、C 和 E 的展示。
因此,转化站点的隐私 预算 会从周期 1、3、4 和 5 中被扣除。 在周期 2 中没有记录展示, 因此不会从该周期扣除任何预算。
用户 代理如何管理隐私预算的耗尽, 取决于所选择的归因 逻辑。
7.2.2. 安全限制
基本隐私单元 容易受到能够在多个站点之间 关联同一个人活动的攻击者攻击。
站点组有时可以协调其活动, 例如当它们具有共同所有权或强协议时。 能够确定某个特定访问者是同一个人的站点组——使用任何手段,包括 类似 FedCM [FEDCM] 的机制——可以合并从此 API 获得的信息。
这可用于提高站点从归因中 获得信息的速率, 其比例取决于 发生协调的站点数量。 默认隐私单元对此方式释放的信息 不设置任何限制。
为抵消这种影响,用户代理可以实现安全限制, 即不考虑站点的额外隐私预算。 安全限制可能显著高于按站点预算, 因此在大多数正常浏览活动中不会达到。 目标是确保它们只对 高强度活动或遭受攻击时有效。
与按站点隐私预算一样, 至关重要的是,站点无法确定 其对转化报告的请求 是否导致安全限制被超过。
7.3. 差分隐私机制
差分隐私机制——即添加噪声的具体方法——可以由 聚合 服务选择。
预计添加拉普拉斯噪声会产生良好结果, 在噪声的总体幅度 与实现和分析的简单性之间取得平衡。 当前设计使用基于 L1 范数的 DP 敏感度, 它支持在聚合中添加拉普拉斯噪声。 支持其他噪声机制可能需要对 敏感度的计算和信号传递方式进行额外更改。
在中心位置添加噪声, 如这些聚合服务中任一项所定义, 确保噪声总量不会随着 报告总数的增加而增加。 与在报告生成点应用噪声的差分隐私设计 (即本地差分隐私模型) 相比,这提供了效用优势, 后者的噪声会按报告总数成比例增加。
8. 安全性考量
8.1. 展示存储
Attribution API 使用的展示存储 保存与浏览活动相关的信息, 并跨浏览会话持久存在。 尽管通过展示存储的信息流 受到严格控制, 它仍会跨源携带一定量的信息。
以下措施限制了 有害信息通过展示存储流动的可能性:
-
网站不能从展示存储中读取。 来自展示存储的信息 仅通过加密的转化报告释放。 由用户代理中的功能 和聚合服务中的功能组合提供的差分隐私 对聚合服务输出的聚合信息 与在没有任何用户贡献时的值相比 可区分的概率 提供严格界限。
-
用户可以明确地 清除已存储的展示。
-
建议用户代理限制数据 可在展示存储中持久存在的时间, 即使没有明确的用户操作, 也应通过施加 lifetimeDays 的最大值来实现。
8.2. 实现中的侧信道风险
Attribution API 必须谨慎实现, 以维护所需的安全和隐私属性。 调用这些 API 的站点不能了解:
请注意,显式返回值或抛出的异常 并不是站点可以从 Attribution API 中了解信息的唯一方式。 可能可以从如下侧信道 推断敏感信息:
-
API 完成所需时间的变化。
-
API 对共享资源的消耗, 例如内存、存储、网络和 CPU。 这包括对该消耗的任何限制执行, 如果站点能够观察到的话。
API 中函数执行时间的变化 是维护保证时的主要考量。 对执行时间而言,有两个特别令人担忧的因素:
-
measureConversion() 处理的展示数量。 因为站点控制保存多少展示 以及选择它们的逻辑, 这会造成站点创建跨站点计时侧信道的 显著暴露面。
-
对共享全局状态的访问。 对 API 的并发访问由单个归因预算锁治理, 以防止正确性错误。 该锁形成了在并发访问 API 的站点之间 泄露信息的手段。
全局隐私预算存储、 展示站点配额存储 和周期开始时间中的 共享全局状态 风险较小, 因为这些值从不直接影响算法运行时间。 实现仍需要确保任何全局状态 不会导致指纹识别 或其他信息泄露。
虽然完全消除所有侧信道并不现实, 实现必须作出合理努力以防止 Attribution API 泄露敏感信息。 防止泄露的策略包括:
-
完全验证所有 API 输入,即使 API 已禁用。
-
避免条件逻辑。例如, measureConversion() 应始终完成构造 转化报告的完整过程,即使要报告的转化值 为零。
-
为某些操作设置固定运行时间。
8.3. 聚合服务
虽然聚合服务不是 Web 平台的一部分, 但其安全性对于 Attribution 机制的总体安全性 非常重要。 由 measureConversion() 生成的转化报告 使用聚合服务的密码密钥进行加密。 因此,披露这些报告中所含信息的 很大一部分潜在可能性 取决于聚合服务的细节。
用户 代理开发者在将聚合服务添加为 Attribution API 支持的服务之前, 应仔细考虑聚合服务的设计 以及聚合服务操作者的可信度。 关于这些问题的其他讨论 可见于 § 6 聚合 和 § 9 隐私 考量。
8.4. 合并来自多个站点的报告
Attribution API 中的隐私机制 主要以站点粒度运行。 恶意操作者 可能尝试为多个站点 注册展示, 从而超过本应通过归因 释放的信息量。 § 7.2.2 安全限制讨论了建立额外跨站点 隐私预算以缓解这种可能性。
8.5. 控制跨站点参与
为了生成聚合直方图, 多个站点需要协作。 每个展示站点 都需要为其保存的展示 生成一致的值。 转化站点需要 信任展示站点会记录正确的值。
API 提供了多个过滤选项, 以帮助站点管理不需要的展示 污染聚合结果的风险。
-
展示站点 可以使用
conversionSites定向特定转化站点。 -
展示可以使用
conversionCallers限制为在转化站点上运行的 特定中介方。 -
转化站点 可以使用
impressionSites限制它作为归因一部分 所查询的展示站点。 -
转化还可以使用
impressionCallers将展示查询限制为 由特定中介方保存的展示。
过滤选项有助于 限制哪些站点能够参与归因, 从而减少能够污染聚合结果的实体集合。 有效使用这些选项对于防止 意外包含某些不需要的展示尤其有用。
这些过滤选项在抵御恶意污染结果的尝试方面 效力有限。 信任很少像这些控制所预期的那样严格二元。 被列入的展示站点可能会将 从转化站点角度看是真实的展示 与伪造或错误的展示混合。 错误展示表示所谓的无效流量(IVT), 其中一些可能被认为是欺诈性的。
8.5.1. 广告欺诈
Web 上的广告 一直是各种欺诈的对象。 站点可能会试图使用此 API 进行展示欺诈, 制造价值被错误归因到 其投放广告上的印象。
欺诈性注册展示 是此 API 的一个特别关注点, 因为展示只存储在设备上。 无法应用服务器端智能 来识别欺诈性展示并将其 排除在归因之外。
针对恶意展示的唯一直接缓解措施 是站点级过滤选项。 这防止完全不受信任站点上的展示 干扰对预期候选展示集合的归因。
相反,尽管转化报告是加密的, 因为这些报告被发送到转化站点, 转化站点可以作出判断, 认为该转化很可能是欺诈性的, 并将其排除在聚合之外。
9. 隐私考量
此 API 的主要隐私目标是 确保为站点提供执行归因的能力 不会增强它们执行跨站点识别的能力。
本节提供更多信息, 说明实现此目标所需的保护措施。 其他讨论涉及次要隐私目标, 例如防止同站点识别。
9.1. Attribution API 暴露的信息
展示存储和 隐私预算 存储 包含关于浏览活动横截面的信息。 随着 API 使用增加, 此信息的范围也随之增加。 但是,写入这些存储的大多数信息 永远不会被披露。 因为归因是在设备上执行的 (设备上归因), Attribution API 只暴露关于已归因转化的信息。 这与其他方案形成对比,在那些方案中, 关于展示和转化的信息都会被发送到 聚合服务进行设备外归因。 在后一类方案中, 聚合服务被攻破 (或与聚合服务的通信被攻破)时 可能揭示的信息量 要大得多。
当 Attribution API 进行归因时, 关于该归因的信息只会在差分隐私限制允许的范围内 从设备释放。
虽然 Attribution API 旨在衡量 相对不频繁的转化事件 与有限一组相关展示候选项之间的关联, 但必须考虑 API 可能如何被误用 于更大规模的数据收集。 展示枚举可能的转化 站点(反之亦然)的要求 在防止 API 被误用进行大规模数据收集 以及使此类误用尝试更可见方面 具有重要作用。
9.2. 禁用 Attribution API
用户代理必须提供控件, 供用户禁用 Attribution API。
Attribution API 被设计为只揭示聚合信息。 使用差分隐私 限制了确定任何特定用户 是否对聚合输出作出贡献的可能性。 但是,一些用户仍可能更愿意 不参与归因测量。
实现可以向用户提供选择退出的选项, 使用 Attribution API 的专用控件, 或通过适用于多个功能的统一隐私控件。
用户代理开发者应考虑 其他隐私模式与 Attribution API 的交互。 例如,归因可能在私密浏览模式中被禁用, 或者如果用户选择退出诊断数据收集, 归因也可能被禁用。
按设计,网站无法检测用户是否已选择退出。
为了最大限度降低指纹识别风险, 并防止对选择禁用 Attribution API 的用户 进行歧视, 站点不得检测 API 是否被禁用。 具体而言,对 Attribution API 的所有调用 只要在其他方面有效, 即使 API 被禁用也会成功完成。 行为上的唯一差异是, API 被禁用时返回的转化 报告 永远不会报告任何转化值。 因为报告是加密的, 接收转化报告的站点无法检测到 这种差异。
9.3. 可见性
实现应为用户提供一种方式, 以查看展示存储的状态 并审查过去的报告提交。
这些界面可能仅限于显示 站点对 Attribution API 聚合使用情况的摘要信息。 用于检查展示和已提交报告详情的界面 可以帮助用户和 Web 开发者 诊断 API 的运行。
9.4. 未配置的浏览器
此 API 假定用户代理实例 具有响应 measureConversion() 请求所需的 所有配置。
如果调用 measureConversion() 所需的聚合 服务配置 不存在或已过期, 站点可能会观察到这一点。
如果检索配置 可能延迟对 measureConversion() 调用的解析, 这会产生计时侧信道。 如果改为生成假响应, 来自正确配置的用户代理的响应 与假响应之间的差异 可能可被观察到。 这可能是密钥标识符的使用 或其他未加密元数据。 密文长度的差异也可能揭示被加密内容的变化 或算法选择的变化。
因此,用户 代理应 以站点不可观察的方式 优先获取聚合服务配置。 这可以通过在启动时 在开始加载任何内容之前获取配置来实现。
如果无法获得必要配置, 或配置明显陈旧, 实现可以选择在调用 measureConversion() 时 立即拒绝。 这会泄露信息, 但可能比尝试生成假值泄露得更少。
9.5. 在保存的展示中包含识别信息
站点能够在展示中
编码一定量的数据,
使用 matchValue
或其他字段。
API 不会阻止站点
在这些字段中编码用户标识符。
归因过程在构造转化报告时
可以使用这些数据,
这意味着该识别信息
有可能被接收该报告的站点获得。
以下措施缓解了此风险:
9.6. 在第三方上下文中使用
Attribution API 即使在第三方上下文中也可用。 特别是,第三方 iframe 可以调用 saveImpression()。 但请注意,展示会以顶级导航上下文的站点 记录,而不是以 iframe 的源 记录。
虽然 API 在第三方上下文中可用 会带来一定的隐私风险增加, 但这种支持被认为是必要的, 因为 iframe 常用于展示广告。
9.7. 清除 API 状态
用户 代理可能会提供清除存储的选项。 这些选项存在有两个原因:
清除跟踪隐私预算支出的状态 会对面向站点的隐私产生不利影响。 站点随后将能够从归因中 获得更多信息。
当 API 被禁用时, 用户 代理可以清除 隐私 预算存储和周期开始时间中的数据。 在这种情况下,如果 API 重新启用, 就无法确定 API 被禁用之前 已支出了多少预算。 在这种情况下,用户代理可以更新 上次清除浏览历史的值, 以确保隐私 预算不会被无意中超出。
9.7.1. 清除站点数据
在应用户请求清除站点数据 但保留浏览历史时, 用户 代理会调用为归因清除浏览历史, 给定受影响站点的集合、 false(用于forgetVisits), 以及采取该操作的时间。 这会将该站点的隐私预算设置为零, 防止在该站点上使用转化测量。 这不会从展示存储中移除已保存的展示; 从逻辑上说,展示在保存时 就被转移给转化站点。
当应站点请求
通过使用
`Clear-Site-Data`
标头清除站点数据时,
用户
代理只会移除展示,
而不会改变隐私预算存储
或周期开始
时间。
9.7.2. 清除浏览历史
在清除浏览历史时, 更新隐私 预算存储是不够的。 保留为防止面向站点的隐私损失 所必需的按站点 信息 会留下关于站点访问的信息, 供计算机的其他用户发现。
清除浏览历史的用户代理 会调用为归因清除浏览历史, 给定受影响站点的集合、 true(用于forgetVisits), 以及启动该操作的时间。
在清除浏览历史时, 用户 代理需要 移除所有按站点的隐私预算信息 (也就是说,从隐私预算存储中移除条目)。 用户 代理还需要确保 任何后续隐私 预算支出 不会因丢失该信息而导致 超过配置限制的隐私损失。
这可以通过在丢弃浏览历史所在的周期 中禁用归因来实现。 否则,一个在清除历史前 立即花费其预算的站点 可能会通过 API 了解 比不清除状态时更多的信息。
这会在受影响站点的 周期剩余时间内禁用 API。 因为周期开始 时间没有被清除, 周期 时间线保持连续。
用户 代理会在上次清除浏览历史值中 记住上次清除历史的时间。 这用于防止预算支出, 直到可以保证站点不会超过 用户 代理选择的最大允许隐私预算。
获取归因起始周期 算法 确保转化 站点 不能查询在清除状态后一个周期持续时间内 开始的任何周期中的 展示。
9.7.3. 清除展示
必须提供一种机制来清除展示存储。 例如,可以在激活 禁用 Attribution API 的控件时 清除展示存储。
建议将用户代理提供的 任何清除已存储数据(历史、cookie 等)的机制 扩展为覆盖展示存储。 § 9.7 清除 API 状态提供了关于 清除已存储数据的更详细信息。
为站点清除状态的用户 代理 必须丢弃在受影响期间保存的所有已保存 展示, 这些展示具有匹配的展示站点 或转化站点。 对于展示站点, 这些展示与被清除的活动有关。 已清除状态的转化站点 将无法使用这些展示。
9.8. 时钟的选择
此 API 使用挂钟作为其时间基础。 这主要是因为 API 依赖持久的时间概念。 单调时钟只在用户 代理的单次执行期间定义, 因此如果用户代理重启, 它不能保证一致性。
挂钟可以被调整以考虑 可能因时钟漂移而累积的误差。 因此,挂钟不能保证始终以一致速率 前进, 包括它有时可能后退的可能性。
挂钟的后退不会影响 此 API 提供的隐私保证。 只有时钟的前进 可能具有不利的隐私影响。 超过正常时间进度的前进 可能导致隐私预算 比预期更快地更新。
对于在每个周期内 经历校正的时钟, 时钟调整不会产生隐私影响。 单次足够大的校正 可能导致隐私 预算 提前更新, 从而导致一次性的隐私损失增加。 连续的大幅校正对隐私影响最严重, 因为每次周期之间的过渡 都会释放额外的隐私预算。
时间的大幅增加 如果跳过整个周期, 不会导致额外的隐私损失。 除非展示能够被保存, 否则不可能发生隐私损失。
当然,任何需要对其时钟进行大幅 或连续 校正的用户代理 都很可能因其报告的时间而具有高度可识别性。 仅这一点就可能足以实现不希望的跨站点识别。
10. 致谢
本规范是许多人大量工作的成果。 此级别 API 的总体形态基于 Luke Winstrom 的一个想法。 隐私架构由 [PPA-DP] 的作者提供。