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|: