From c8139ecf83855afa05e79fbf328209091e71f628 Mon Sep 17 00:00:00 2001 From: Andy Leiserson Date: Mon, 16 Sep 2024 17:50:01 -0700 Subject: [PATCH] More API updates --- api.bs | 114 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 37 deletions(-) diff --git a/api.bs b/api.bs index 5f6477a..ee02d7d 100644 --- a/api.bs +++ b/api.bs @@ -353,27 +353,43 @@ Upon receiving a set of encrypted histograms from a site, the aggregation servic # API Details # {#api} -Before using the other Private Attribution APIs, a site must -[[#list-aggregation-services-api|list aggregation services]] to discover the aggregation services -that are supported. -The page may select any of the supported services returned by -listAggregationServices(). +A site using the Private Attribution API will typically register either +[=impressions=] or [=conversions=], but in some cases the same site may +do both. + +To register an impression, a site calls +saveImpression(). No preparation is +required to use this API beyond collecting parameter values, although +it may be useful to examine the supported +aggregationServices in deciding +whether to use the Private Attribution API. + +To request a conversion report, a site calls +measureConversion(). +Before calling this API, a site must +select a supported [=aggregation service=]. +The page may select any of the supported services found in +aggregationServices. The name of the selected service must be supplied as the `aggregator` member of the {{PrivateAttributionConversionOptions}} dictionary when calling the measureConversion() method. -## Finding a Supported Aggregation Service ## {#list-aggregation-services-api} +## Finding a Supported Aggregation Service ## {#find-aggregation-service}

Is any additional information required in the {{PrivateAttributionAggregationService}} dictionary? Do we want to rename `apiVersion` to `protocol`? And we should definitely define an enum for it. -The listAggregationServices() method -returns a list of aggregation services supported by the [=user agent=]. The page +The aggregationServices attribute +contains a list of aggregation services supported by the [=user agent=]. The page must select and specify one of these services when calling the measureConversion() method. +It may also be useful to query the supported services +before registering an impression, +but that is not required, +and impressions are not scoped to a single aggregation service.

dictionary PrivateAttributionAggregationService { @@ -387,7 +403,8 @@ interface PrivateAttribution { }; -The arguments to listAggregationServices() are as follows: +The aggregationServices attribute +contains the following information about each supported aggregation service:
name
@@ -407,14 +424,14 @@ The arguments to listAggregationServices() ## Saving Impressions ## {#save-impression-api} -The saveImpression() method requests +The saveImpression() method requests that the [=user agent=] record an [=impression=] in the [=impression store=].
 navigator.privateAttribution.saveImpression({
   histogramIndex: 3,
-  ad: "sample-campaign-eijb",       // a unique identifier for the ad placement
-  conversionSite: "advertiser.example",     // the advertiser site where a conversion will occur
+  ad: "sample-campaign-eijb",
+  conversionSite: "advertiser.example",
 });
 
@@ -441,6 +458,20 @@ The arguments to saveImpression() are as fo [=impression=] with a subsequent [=conversion=], the [=conversion value=] will be added to the histogram bucket identified by this index. +
ad
+
+ A unique ad identifier for the impression. The + ad identifier is used to identify which impressions may receive attribution + from a [=conversion=]. The Private Attribution API does not impose a particular + format on ad identifiers. If an implementation imposes a maximum ad identifer + length, it must be at least 64 code points. +
+
conversionSite
+
+ The site where [=conversions=] for this impression may occur, identified by + its domain name. The measureConversion() + method will only attribute to this impression when called by the indicated + site.
lifetimeDays
A "time to live" (in days) after which the [=impression=] can no longer @@ -452,11 +483,12 @@ The arguments to saveImpression() are as fo ### Operation ### {#save-impression-api-operation} -1. Validate the page-supplied API inputs -2. Collect the implict API inputs: +1. Collect the implicit API inputs: 1. The current timestamp 2. The impression site domain -3. If the private attribution API is enabled, save the impression to the store. +1. Validate the page-supplied API inputs +1. If the private attribution API is enabled, save the impression to the + [=impression store=]. ## Requesting Attribution for a Conversion ## {#measure-conversion} @@ -467,7 +499,10 @@ and return a [=conversion report=]. The measureConversion() method always returns a conversion report, -regardless of whether matching [=impression|impression(s)=] were found. +regardless of whether matching [=impression|impression(s)=] are found. +If there is no match, or if [[#dp|differential privacy]] disallows +reporting the attribution, the returned conversion report will not +contribute to the histogram, i.e., will be uniformly zero.
 navigator.privateAttribution.measureConversion({
@@ -519,14 +554,24 @@ The arguments to measureConversion() are as
 
aggregator
- A selection from the [=aggregation services=] that can be listed using listAggregationServices(). + A selection from the [=aggregation services=] that can be found in aggregationServices.
-
histogramSize
epsilon
+
The amount of [=privacy budget=] to expend on this [=conversion report=].
+
histogramSize
+
The number of histogram buckets to use in the [=conversion report=].
logic
+
+ A selection from PrivateAttributionLogic indicating the + [=attribution logic=] to use. +
value
-
The [=conversion value=]
+
+ The [=conversion value=]. If an attribution is made and [[#dp|privacy]] + restrictions are satisfied, this value will be encoded into the [=conversion + report=]. +
lookbackDays
An integer number of days. Only impressions occurring within the past `lookbackDays` may match this [=conversion=].
ads
@@ -538,21 +583,18 @@ The arguments to measureConversion() are as ### Operation ### {#measure-conversion-api-operation} -1. Validate the page-supplied API inputs -2. Collect the implicit API inputs +1. Collect the implicit API inputs 1. The current timestamp 2. The conversion site domain -3. Set |reportedConversionValue| to 0. -4. If the private attribution API is enabled, search for a matching impression using the [[#logic-matching|common matching logic]]. -5. If a matching impression was found: - 1. Set |histogramIndex| to the value from the matching impression - 2. Set |reportedConversionValue| to the smaller of the following: - 1. The conversion value passed to the MeasureConversion API. - 2. The limit on conversion value determined by the remaining privacy budget. -6. Update the privacy budget store to reflect the reported conversion value. -7. Construct a report from |reportedConversionValue|, |histogramIndex|, and histogramSize. -8. Encrypt the report. -9. Return the encrypted report. +1. Validate the page-supplied API inputs + 1. If logic + is specified, and the value is anything other than + "last-touch", + return an error. +1. If the private attribution API is enabled, + invoke the routine to [=fill a histogram using last-touch attribution=]. +1. Encrypt the report. +1. Return the encrypted report. ## Impression store ## {#s-impression-store} @@ -627,7 +669,7 @@ That is, once a week has a matching impression and insufficient budget, the process will set a value of zero for all histogram buckets. -To fill a histogram using last-touch attribution, +To fill a histogram using last-touch attribution, given |options|: 1. Initialize |impression| to a null value. @@ -659,7 +701,7 @@ given |options|: 1. If |budgetOk| is false, set |value| to 0. -1. If |impression|.|histogramIndex| +1. If |impression|.histogramIndex is |options|.{{PrivateAttributionConversionOptions/histogramSize}} or greater, set |value| to 0. @@ -679,8 +721,6 @@ TODO specify how to match using "lookbackDays", "ads" and "impressionSites". Discuss "infinite" lookbackDays. Clarify when it apples. When field is missing? Zero? -ad identifier - To perform common matching logic, given |options|, |week|, and [=moment=] |now|: