From 932a8fbc40a1ca2b44c9c697929b282f3b33e43f Mon Sep 17 00:00:00 2001 From: Andy Leiserson Date: Fri, 13 Dec 2024 15:03:16 -0800 Subject: [PATCH 1/3] Initial detail of HTTP API --- api.bs | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/api.bs b/api.bs index e57a2c9..8157f97 100644 --- a/api.bs +++ b/api.bs @@ -385,6 +385,10 @@ it may be useful to examine the supported aggregationServices in deciding whether to use the Private Attribution API. +It is also possible to register an impression by including the +[:Save-Impression:] +header in the HTTP response when serving a resource to the user agent. + To request a conversion report, a site calls measureConversion(). Before calling this API, a site must @@ -463,7 +467,7 @@ navigator.privateAttribution.saveImpression({ dictionary PrivateAttributionImpressionOptions { required unsigned long histogramIndex; - required unsigned long filterData; + unsigned long filterData; required DOMString conversionSite; unsigned long lifetimeDays; }; @@ -624,8 +628,13 @@ The arguments to <a method for=PrivateAttribution>measureConversion()</a> are as <dt><dfn>intermediarySites</dfn></dt> <dd> A list of sites which called the <a method for=PrivateAttribution>saveImpression()</a> API. - Only [=impressions=] recorded by scripts originating from one of the intermediary sites - are eligible to match this [=conversion=]. + [=Impressions=] are only eligible to match this [=conversion=] if either: + 1. they were registered by a call to <a method for=PrivateAttribution>saveImpression()</a> + in a script originating from one of the intermediary sites, or + 2. they were registered by a [:Save-Impression:] header associated with a resource + from one of the intermediary sites. + <!-- TODO: HTTP registration should also apply to impression sites. + -- Interaction between impression and intermediary sites needs to be clarified (#55). --> </dd> </dl> @@ -855,6 +864,21 @@ if the user has opted out of collection of diagnostic data. * User ability to view the impression store and past report submissions. +# HTTP API # {#http-api} + +\`<dfn http-header><code>Save-Impression</code></dfn>\` is a +[=structured header/dictionary|Dictionary Structured Header=] +set on a response requesting that the user agent invoke the +<a method for=PrivateAttribution>saveImpression()</a> API. + +<pre class=example id=ex-save-impression-header> +Save-Impression: conversionSite=advertiser.example;histogramIndex=2;\ + filterData=12;lifetimeDays=7 +</pre> + +TODO need to specify in more detail when and how this header is interpreted + + # Implementation Considerations # {#implementation-considerations} * Management and distribution of values for the following: @@ -1475,6 +1499,12 @@ The privacy architecture is courtesy of the authors of [[PPA-DP]]. spec:html; type:dfn; text:site spec:infra; type:dfn; text:user agent </pre> +<pre class=anchors> +spec:structured header; type:dfn; urlPrefix: https://httpwg.org/specs/rfc9651; + text: structured header; url: #name-introduction + for: structured header + text: dictionary; url: #dictionary +</pre> <pre class=biblio> { "coppacalypse": { From bab0f956dea36eb29f741bfec62fa3498b1e9269 Mon Sep 17 00:00:00 2001 From: Andy Leiserson <aleiserson@mozilla.com> Date: Mon, 16 Dec 2024 15:45:10 -0800 Subject: [PATCH 2/3] Revert optional filterData --- api.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.bs b/api.bs index 8157f97..d9946ee 100644 --- a/api.bs +++ b/api.bs @@ -467,7 +467,7 @@ navigator.privateAttribution.saveImpression({ <xmp class=idl> dictionary PrivateAttributionImpressionOptions { required unsigned long histogramIndex; - unsigned long filterData; + required unsigned long filterData; required DOMString conversionSite; unsigned long lifetimeDays; }; From 5a342e17a378043a49796a8d8556d9eb8f93980e Mon Sep 17 00:00:00 2001 From: Andy Leiserson <aleiserson@mozilla.com> Date: Mon, 16 Dec 2024 16:51:37 -0800 Subject: [PATCH 3/3] Correct syntax of Save-Impression header; add detail --- api.bs | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/api.bs b/api.bs index d9946ee..84016ed 100644 --- a/api.bs +++ b/api.bs @@ -872,10 +872,41 @@ set on a response requesting that the user agent invoke the <a method for=PrivateAttribution>saveImpression()</a> API. <pre class=example id=ex-save-impression-header> -Save-Impression: conversionSite=advertiser.example;histogramIndex=2;\ - filterData=12;lifetimeDays=7 +Save-Impression: conversion-site=advertiser.example, histogram-index=2, \ + filter-data=12, lifetime-days=7 </pre> +The following keys are defined, corresponding to the members of +the {{PrivateAttributionImpressionOptions}} dictionary passed to +<a method for=PrivateAttribution>saveImpression()</a>. + +<dl dfn-for=save-impression> + <dt><code>conversion-site</code></dt> + <dd> + Value of <a dict-member for=PrivateAttributionImpressionOptions>conversionSite</a>, + a [=structured header/string=]. This key is required, + and must be a valid domain name. + </dd> + <dt><code>histogram-index</code></dt> + <dd> + Value of <a dict-member for=PrivateAttributionImpressionOptions>histogramIndex</a>, + an [=structured header/integer=]. This key is required. + </dd> + <dt><code>filter-data</code></dt> + <dd> + Value of <a dict-member for=PrivateAttributionImpressionOptions>filterData</a>. + Implementations parsing the header must accept any valid + [=structured header/item=] or [=structured header/inner list=]. + If the filter data is not understood, no impression is saved. + This key is optional. + </dd> + <dt><code>lifetime-days</code></dt> + <dd> + Value of <a dict-member for=PrivateAttributionImpressionOptions>lifetimeDays</a>, + an [=structured header/integer=]. This key is optional. + </dd> +</dl> + TODO need to specify in more detail when and how this header is interpreted @@ -1504,6 +1535,10 @@ spec:structured header; type:dfn; urlPrefix: https://httpwg.org/specs/rfc9651; text: structured header; url: #name-introduction for: structured header text: dictionary; url: #dictionary + text: string; url: #string + text: integer; url: #integer + text: item; url: #item + text: inner list; url: #inner-list </pre> <pre class=biblio> {