generated from privacycg/template
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathapi.bs
1667 lines (1312 loc) · 61.7 KB
/
api.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class=metadata>
Title: Privacy-Preserving Attribution: Level 1
Shortname: Attribution
Repository: private-attribution/api
URL: https://private-attribution.github.io/api/
Editor: Martin Thomson, w3cid 68503, Mozilla https://mozilla.org/, mt@mozilla.com
Editor: Andy Leiserson, w3cid 147715, Mozilla https://mozilla.org/, aleiserson@mozilla.com
Editor: Benjamin Savage, w3cid 114877, Meta https://www.meta.com/, btsavage@meta.com
Abstract: This specifies a browser API for the measurement of advertising performance. The goal is to produce aggregate statistics about how advertising leads to conversions, without creating a risk to the privacy of individual web users. This API collates information about people from multiple web origins, which could be a significant risk to their privacy. To manage this risk, the information that is gathered is aggregated using an aggregation service that is trusted by the user-agent to perform aggregation within strict limits. Noise is added to the aggregates produced by this service to provide differential privacy. Websites may select an aggregation service from the list of approved aggregation services provided by the user-agent.
Status Text: This specification is a proposal that is intended to be migrated to the W3C standards track. It is not a standard.
Text Macro: LICENSE <a href=http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document>W3C Software and Document License</a>
Complain About: accidental-2119 yes, missing-example-ids yes
Markup Shorthands: markdown yes, css no, dfn yes
Assume Explicit For: yes
Group: patcg
Status: CG-DRAFT
Level: None
</pre>
<style>
@media (prefers-color-scheme: dark) {
figure svg { background: white }
}
</style>
# Introduction # {#intro}
This document defines a simple API for browsers
that enables the collection of aggregated, differentially-private metrics.
The primary goal of this API is to enable attribution for advertising.
## Attribution ## {#s-attribution}
In advertising, <dfn lt=attribution|attributed>attribution</dfn> is the process of identifying [=actions=]
that precede an [=outcome=] of interest,
and allocating value to those [=actions=].
<dfn lt=actions>Actions</dfn> that are of interest to advertisers
are primarily the showing of advertisements
(also referred to as <dfn lt=impression>impressions</dfn>).
Other actions include ad clicks (or other interactions)
and opportunities to show ads that were not taken.
Desired <dfn>outcomes</dfn> for advertising are more diverse,
as they include any result that an advertiser seeks to improve
through the showing of ads.
A desirable outcome might also be referred to as a <dfn>conversion</dfn>,
which refers to "converting" a potential customer
into a customer.
What counts as a conversion could include
sales, subscriptions, page visits, and enquiries.
For this API, [=actions=] and [=outcomes=] are both
events: things that happen once.
What is unique about attribution for advertising
is that these events might not occur on the same [=site=].
Advertisements are most often shown on sites
other than the advertiser's site.
The primary challenge with attribution is in maintaining privacy.
Attribution involves connecting activity on different sites.
The goal of attribution is to find an impression
that was shown to the same person before the conversion occurred.
If attribution information were directly revealed,
it would enable unwanted
[[PRIVACY-PRINCIPLES#dfn-cross-context-recognition|cross-context recognition]],
thereby enabling [[UNSANCTIONED-TRACKING|tracking]].
This document avoids cross context recognition by ensuring that
attribution information is aggregated using an [=aggregation service=].
The aggregation service is trusted to compute an aggregate
without revealing the values that each person contributes to that aggregate.
Strict limits are placed on the amount of information that each browser instance
contributes to the aggregates for a given site.
Differential privacy is used to provide additional privacy protection for each contribution.
Details of aggregation service operation is included in [[#aggregation]].
The differential privacy design used is outlined in [[#dp]].
## Background ## {#background}
From the early days of the Web,
advertising has been widely used to financially support the creation of sites.
One characteristic that distinguished the Web from other venues for advertising
was the ability to obtain information about the effectiveness of advertising campaigns.
Web advertisers were able to measure key metrics like reach (how many people saw an ad),
frequency (how often each person saw an ad),
and [=conversions=] (how many people saw the ad then later took the action that the ad was supposed to motivate).
In comparison, these measurements were far more timely and accurate than for any other medium.
The cost of measurement performance was privacy.
In order to produce accurate and comprehensive information,
advertising businesses performed extensive tracking of the activity of all Web users.
Each browser was given a tracking identifier,
often using cookies that were lodged by cross-site content.
Every action of interest was logged against this identifier,
forming a comprehensive record of a person's online activities.
Having a detailed record of a person's actions allowed advertisers to infer characteristics about people.
Those characteristics made it easier to choose the right audience for advertising,
greatly improving its effectiveness.
This created a strong incentive to gather more information.
Online advertising is intensely competitive.
Sites that show advertising seek to obtain the most money for each ad placement.
Advertisers seek to place advertising where it will have the most effect relative to its cost.
Any competitive edge gained by these entities--
and the intermediaries that operate on their behalf--
depends on having more comprehensive information about a potential audience.
Over time, actions of interest expanded to include nearly every aspects of online activity.
Methods were devised to correlate that information with activity outside of the Web.
An energetic trade has formed,
with multiple purveyors of personal information that is traded for various purposes.
## Goals ## {#goals}
The goal of this document is to define a means of performing [=attribution=]
for advertising
that does not enable tracking.
## End-User Benefit ## {#user-benefit}
The measurement of advertising performance creates new cross-site flows of information.
That information flow creates a privacy risk or cost--
of [[PRIVACY-PRINCIPLES#dfn-cross-context-recognition|cross-context recognition]]--
that needs to be justified in terms of benefits to end users.
Any benefits realized by end users through the use of [=attribution=] is indirect.
End users that visit a website
pay for "free" content or services
primarily through their attention
to any advertisements the site shows them.
This "value" accrues to the advertiser,
who in turn pays the site.
The site is expected to use this money to
support the provision of their content or services.
<figure>
<pre class=include-raw>
path:images/value.svg
</pre>
<figcaption>Value exchange for advertising-supported content and services</figcaption>
</figure>
Participation in an [=attribution=] measurement system
would comprise a secondary cost to Web users.
Support for attribution enables more effective advertising,
largely by informing advertisers about what ads perform best,
and in what circumstances.
Those circumstances might include
the time and place that the ad is shown,
the person to whom the ad is presented, and
the details of the ad itself.
Connecting that information to outcomes
allows an advertiser to learn what circumstances most often lead
to the outcomes they most value.
That allows advertisers to spend more on effective advertising
and less on ineffective advertising.
This lowers the overall cost of advertising
relative to the value obtained. [[ONLINE-ADVERTISING]]
Sites that provide advertising inventory,
such as content publishers and service providers,
indirectly benefit from more efficient advertising.
Venues for advertising that are better able to
show ads that result in
the outcomes that advertisers seek
can charge more for ad placements.
Sites that obtain support through the placement of advertisements
are better able to provide quality content or services.
Importantly, that support is derived unevenly from their audience.
This can be more equitable than other forms of financial support.
Those with a lower tendency or ability to spend on advertised goods
obtain the same ad-supported content and services
as those who can afford to pay. [[EU-AD]][[COPPACALYPSE]]
The ability to supply "free" services
supported by advertising
has measurable economic benefit
that derives from the value of those services. [[FREE-GDP]]
## Collective Privacy Effect ## {#collective}
The use of aggregation--
if properly implemented--
ensures that information provided to sites is about groups and not individuals.
The introduction of this mechanism therefore represents collective decision-making,
as described in [[PRIVACY-PRINCIPLES#collective-privacy]].
Participation in attribution measurement carries a lower privacy cost
when the group that participates is larger.
This is due to the effect of aggregation on
the ability of sites to
extract information about individuals from aggregates.
This is especially true for central [[#dp|differential privacy]],
which is the mathematical basis for the privacy design used
in this specification.
Larger cohorts of participants also produce more representative--
and therefore more useful--
statistics about the advertising that is being measured.
If attribution is justified,
both these factors motivate the enablement of attribution for all users.
Acting to enable attribution measurement by user agents
will not be positively received by some people.
Different people perceive the costs and benefits
that come from engaging with advertising differently.
The proposed design allows people the option of appearing to participate in attribution
without revealing that choice to sites; see [[#opt-out]].
## Attribution Using Histograms ## {#histograms}
[=Attribution=] attempts to measure correlation
between one or more ad placements ([=impressions=])
and the [=outcomes=] that an advertiser desires.
When considered in the aggregate,
information about individuals is not useful.
Actions and outcomes need to be grouped.
The simplest form of attribution splits impressions into a number of groupings
according to the attributes of the advertisement
and counts the number of conversions.
Groupings might be formed from attributes such as
where the ad is shown,
what was shown (the "creative"),
when the ad was shown,
or to whom.
These groupings
and the tallies of conversions attributed to each
form a histogram.
Each bucket of the histogram counts the conversions
for a group of ads.
<figure>
<pre class=include-raw>
path:images/histogram.svg
</pre>
<figcaption>Sample histogram for conversion counts,
grouped by the site where the impressions were shown</figcaption>
</figure>
Different groupings might be used for different purposes.
For instance, grouping by creative (the content of an ad)
might be used to learn which creative works best.
Adding a value greater than one at each conversion
enables more than simple counts.
Histograms can also aggregate values,
which might be used to differentiate between different outcomes.
The value that is allocated to impressions
is called a <dfn>conversion value</dfn>.
A higher conversion value might be used for larger purchases
or any outcome that is more highly-valued.
A conversion value might also be split between multiple impressions
to split credit,
though this capability is not presently supported in the API.
* Compatibility with privacy-preserving aggregation services
* Flexibility to assign buckets
* As histogram size increases, noise becomes a problem
# Overview of Operation # {#overview}
The private attribution API provides aggregate information about the
association between two classes of events: [=impressions=] and [=conversions=].
An [=impression=] is any action that an advertiser takes on any website.
The API does not constrain what can be recorded as an impression.
Typical actions that an advertiser might seek to measure include:
* Displaying an advertisement.
* Having a user interact with an advertisement in some way.
* Not displaying an advertisement (especially for controlled experiments that seek to confirm whether an advertising campaign is effective).
For the API, a [=conversion=] is an [=outcome=] that is being measured.
The API does not constrain what might be considered to be an outcome.
Typical outcomes that advertisers might seek to measure include:
* Making a purchase.
* Signing up for an account.
* Visiting a webpage.
The remainder of this section describes
how the Private Attribution API operates
in conjunction with an [=aggregation service=]
to produce an aggregate attribution measurement.
That operation is illustrated in the following figure.
<figure>
<pre class=include-raw>
path:images/overview.svg
</pre>
<figcaption>Overview of Private Attribution Operation</figcaption>
</figure>
When an [=impression=] occurs,
the <a method for=PrivateAttribution>saveImpression()</a> method can be used
to request that the browser save information.
This includes an identifier for the impression
and some additional information about the impression.
For instance, advertisers might use additional information
to record whether the impression was an ad view or an ad click.
At [=conversion=] time, a [=conversion report=] is created.
A <dfn>conversion report</dfn> is an encrypted histogram contribution
that includes information from any [=impressions=] that the browser previously stored.
The <a method for=PrivateAttribution>measureConversion()</a> method accepts a simple query that is used
to tell the browser how to construct a [=conversion report=].
That includes a simple query that selects from the [=impressions=]
that the browser has stored,
a [=conversion value=] that is allocated to the selected impression(s),
and other information needed to construct the [=conversion report=].
The histogram created by the [=conversion report=] is constructed as follows:
* If the query found no impressions,
or the [=privacy budget=] for the site is exhausted,
a histogram consisting entirely of zeros (0) is constructed.
* If one or more matching impressions is found, the browser runs the attribution
logic (default last-touch) to select the most recent impression. The provided conversion
value is added to a histogram at the bucket that was specified at the time of the
attributed impression. All other buckets are set to zero.
The browser updates the privacy budget store to reflect the reported conversion.
The resulting histogram is prepared for aggregation according to the requirements
of the chosen [=aggregation service=] and returned to the site.
This minimally involves encryption of the histogram.
<p class=note>A site that invokes this API will always receive a valid conversion report.
As a result, sites learn nothing about what happened on other sites from this interaction.
The site can collect the encrypted histograms it receives from calls to this API
and submit them to the aggregation service.
Upon receiving a set of encrypted histograms from a site, the aggregation service:
1. confirms that it has not
previously computed an aggregate
from the provided inputs
and that there are enough conversion reports,
2. adds the histograms including sufficient [[#dp|noise]]
to produce a differentially-private aggregate histogram, and
3. returns the aggregate to the site.
# API Details # {#api}
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
<a method for=PrivateAttribution>saveImpression()</a>. No preparation is
required to use this API beyond collecting parameter values, although
it may be useful to examine the supported
<a attribute for=PrivateAttribution>aggregationServices</a> in deciding
whether to use the Private Attribution API.
To request a conversion report, a site calls
<a method for=PrivateAttribution>measureConversion()</a>.
Before calling this API, a site must
select a supported [=aggregation service=].
The page may select any of the supported services found in
<a attribute for=PrivateAttribution>aggregationServices</a>.
The name of the selected service must be supplied as
the {{PrivateAttributionConversionOptions/aggregator}} member of the
{{PrivateAttributionConversionOptions}} dictionary when calling the
<a method for=PrivateAttribution>measureConversion()</a> method.
## Finding a Supported Aggregation Service ## {#find-aggregation-service}
The <dfn attribute for=PrivateAttribution>aggregationServices</dfn> 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
<a method for=PrivateAttribution>measureConversion()</a> 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.
<xmp class=idl>
enum PrivateAttributionProtocol { "dap-12-histogram", "tee-00" };
dictionary PrivateAttributionAggregationService {
required DOMString url;
required DOMString protocol;
};
[SecureContext, Exposed=Window]
interface PrivateAttributionAggregationServices {
readonly setlike<PrivateAttributionAggregationService>;
};
[SecureContext, Exposed=Window]
interface PrivateAttribution {
readonly attribute PrivateAttributionAggregationServices aggregators;
};
</xmp>
The <a attribute for=PrivateAttribution>aggregationServices</a> attribute
contains the following information about each supported aggregation service:
<dl dfn-for=PrivateAttributionAggregationService dfn-type=dict-member>
<dt><dfn>url</dfn></dt>
<dd>
A URL that identifies an [=aggregation service=].
This value is passed as the {{PrivateAttributionConversionOptions/aggregator}} parameter
to <a method for=PrivateAttribution>measureConversion()</a> to select the identified aggregation service.
</dd>
<dt><dfn>protocol</dfn></dt>
<dd>
The {{PrivateAttributionProtocol|protocol}} that the [=aggregation service=] uses.
Different versions of the same protocol use different values.
Even if a single service provider supports multiple protocols,
each needs to use a different URL.
This ensures that each can be uniquely identified by URL
without also specifying the choice of protocol.
</dd>
</dl>
The <dfn enum>PrivateAttributionProtocol</dfn> describes the submission protocol
used by different [=aggregation services=]. This document defines two protocols:
<dl dfn-for=PrivateAttributionProtocol dfn-type=enum-value>
<dt><dfn>dap-12-histogram</dfn></dt>
<dd>A DAP-based protocol [[DAP]] that uses [=MPC=]; see [[#s-mpc]].</dd>
<dt><dfn>tee-00</dfn></dt>
<dd>A protocol for submission to a [=TEE=]; see [[#s-tee]].</dd>
</dl>
## Saving Impressions ## {#save-impression-api}
The <dfn method for=PrivateAttribution>saveImpression()</dfn> method requests
that the [=user agent=] record an [=impression=] in the [=impression store=].
<pre>
navigator.privateAttribution.saveImpression({
histogramIndex: 3,
filterData: 2,
conversionSite: "advertiser.example",
lifetimeDays: 7,
});
</pre>
<xmp class=idl>
dictionary PrivateAttributionImpressionOptions {
required unsigned long histogramIndex;
required unsigned long filterData;
required DOMString conversionSite;
unsigned long lifetimeDays = 30;
};
[SecureContext, Exposed=Window]
partial interface PrivateAttribution {
[Throws] undefined saveImpression(PrivateAttributionImpressionOptions options);
};
</xmp>
The arguments to <a method for=PrivateAttribution>saveImpression()</a> are as follows:
<dl dfn-for=PrivateAttributionImpressionOptions dfn-type=dict-member>
<dt><dfn>histogramIndex</dfn></dt>
<dd>
If <a method for=PrivateAttribution>measureConversion()</a> matches this
[=impression=] with a subsequent [=conversion=], the [=conversion value=]
will be added to the histogram bucket identified by this index.
</dd>
<dt><dfn>filterData</dfn></dt>
<dd>
An optional piece of metadata associated with the impression. The filterData
can be used to identify which impressions may receive attribution
from a [=conversion=].
</dd>
<dt><dfn>conversionSite</dfn></dt>
<dd>
The site where [=conversions=] for this impression may occur, identified by
its domain name. The <a method for=PrivateAttribution>measureConversion()</a>
method will only attribute to this impression when called by the indicated
site.
<dt><dfn>lifetimeDays</dfn></dt>
<dd>
A "time to live" (in days) after which the [=impression=] can no longer
receive attribution.
If not specified, the default is 30 days.
The [=user agent=] should impose an upper limit on the lifetime,
and silently reduce the value specified here if it exceeds that limit.
</dd>
</dl>
### Operation ### {#save-impression-api-operation}
1. Collect the implicit API inputs:
1. The current timestamp
2. The impression site domain
3. The iframe site domain
1. Validate the page-supplied API inputs
1. If the private attribution API is enabled, save the impression to the
[=impression store=].
<p class=advisement><a method for=PrivateAttribution>saveImpression()</a>
does not return a status indicating whether the impression was recorded.
This minimizes the ability to detect when the Private Attribution
API is [[#opt-out|disabled].
## Requesting Attribution for a Conversion ## {#measure-conversion}
The <dfn method for=PrivateAttribution>measureConversion()</dfn> method
requests that the [=user agent=] perform [=attribution=] for a [=conversion=],
and return a [=conversion report=].
The <a method for=PrivateAttribution>measureConversion()</a> method
always returns a conversion report,
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.
<pre>
navigator.privateAttribution.measureConversion({
// name of the aggregation service
aggregator: "aggregator.example",
// the number of buckets in the histogram
histogramSize: 20,
// the amount of privacy budget to use
epsilon: 1,
// the attribution logic to use
logic: "last-touch",
// the value to assign to the histogram index of the impression
value: 3,
// the maximum value which can be generated across all reports included in the aggregation
// used together with epsilon to calibrate the differential privacy budget to use
maxValue: 5,
// only consider impressions within the last N days
lookbackDays: 30,
// an optional filter to restrict the set of ads that can be attributed
filterData: 2,
// an optional list of sites where impressions might have been registered
impressionSites: ["publisher.example"],
// an optional list of sites which called the saveImpression API
intermediarySites: ["ad-tech.example"],
});
</pre>
<xmp class=idl>
dictionary PrivateAttributionConversionOptions {
required DOMString aggregator;
double epsilon = 1.0;
required unsigned long histogramSize;
PrivateAttributionLogic logic = "last-touch";
unsigned long value = 1;
unsigned long maxValue = 1;
unsigned long lookbackDays;
unsigned long filterData;
sequence<DOMString> impressionSites = [];
sequence<DOMString> intermediarySites = [];
};
[SecureContext, Exposed=Window]
partial interface PrivateAttribution {
[Throws] Promise<Uint8Array> measureConversion(PrivateAttributionConversionOptions options);
};
</xmp>
The arguments to <a method for=PrivateAttribution>measureConversion()</a> are as follows:
<dl dfn-for=PrivateAttributionConversionOptions dfn-type=dict-member>
<dt><dfn>aggregator</dfn></dt>
<dd>
A selection from the [=aggregation services=] that can be found in <a
attribute for=PrivateAttribution>aggregators</a>.
</dd>
<dt><dfn>epsilon</dfn></dt>
<dd>The amount of [=privacy budget=] to expend on this [=conversion report=].</dd>
<dt><dfn>histogramSize</dfn></dt>
<dd>The number of histogram buckets to use in the [=conversion report=].</dd>
<dt><dfn>logic</dfn></dt>
<dd>
A selection from <a enum>PrivateAttributionLogic</a> indicating the
[=attribution logic=] to use.
</dd>
<dt><dfn>value</dfn></dt>
<dd>
The [=conversion value=]. If an attribution is made and [[#dp|privacy]]
restrictions are satisfied, this value will be encoded into the [=conversion
report=].
</dd>
<dt><dfn>maxValue</dfn></dt>
<dd>
The maximum [=conversion value=] across all contributions included in the aggregation.
Together with epsilon, this is used to calibrate the distribution of random noise that
will be added to the outcome. It is also used to determine the amount of [=privacy budget=]
to expend on this [=conversion report=].
</dd>
<dt><dfn>lookbackDays</dfn></dt>
<dd>An integer number of days. Only impressions occurring within the past `lookbackDays` may match this [=conversion=].</dd>
<dt><dfn>filterData</dfn></dt>
<dd>Only [=impressions=] having a filterData value matching this value will be eligible to match this [=conversion=].</dd>
<dt><dfn>impressionSites</dfn></dt>
<dd>A list of impression sites. Only [=impressions=] recorded where the top-level site is on this list are eligible to match this [=conversion=].</dd>
<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=].
</dd>
</dl>
### Operation ### {#measure-conversion-api-operation}
1. Collect the implicit API inputs
1. The current timestamp
2. The conversion site domain
3. The iframe site domain
1. Validate the page-supplied API inputs
1. If <a dict-member for=PrivateAttributionConversionOptions>logic</a>
is specified, and the value is anything other than
<a enum-value for=PrivateAttributionLogic>"last-touch"</a>,
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}
The <dfn>impression store</dfn> is used by the <a method
for=PrivateAttribution>measureConversion()</a> method to find matching
[=impressions=].
### Contents ### {#impression-store-contents}
The [=impression store=] must store the following information:
<div link-for=PrivateAttribution>
<pre class=simpledef>
Filter Data: The {{PrivateAttributionConversionOptions/filterData}} value passed to <a>saveImpression()</a>.
Impression Site: The site that called <a>saveImpression()</a>.
Intermediary Site: The site corresponding to the script that called <a>saveImpression()</a>.
Conversion Sites: The conversion site(s) that were passed to <a>saveImpression()</a>.
Timestamp: The time at which <a>saveImpression()</a> was called.
Lifetime: The number of days an [=/impression=] remains eligible for attribution,
Lifetime: either from the call to <a>saveImpression()</a>, or a [=/user agent=]-defined limit.
Histogram Index: The histogram index passed to <a>saveImpression()</a>.
</pre>
</div>
### Maintenance ### {#impression-store-maintenance}
The [=user agent=] should periodically use
the timestamp and lifetime values
to identify and delete any [=impressions=] in the [=impression store=]
that have expired.
It is not necessary to remove [=impressions=] immediately upon expiry,
as long as <a method for=PrivateAttribution>measureConversion()</a>
excludes expired [=impressions=] from [=attribution=]. However, the
[=user agent=] should not retain expired [=impressions=] indefinitely.
### Clearing ### {#impression-store-clearing}
A mechanism must be provided to clear the impression store.
For example, the impression store could be cleared
upon activation of the control that
[[#opt-out|disables]] the Private Attribution API.
It is recommended that any mechanism a user agent provides
to clear stored browsing data (history, cookies, etc.)
be extended to cover the impression store.
## Privacy Budget Store ## {#s-privacy-budget-store}
<!--
Added this here for symmetry with the impression store and with the philosophy
that "just tell me how to implement" goes in the API section. But I'd also be
fine with putting this in the DP section.
-->
The <dfn>privacy budget store</dfn> records the state
of the per-[=site=] [=privacy budgets=], and of any
[=safety limits=]. It is updated by [=deduct privacy budget=].
<p class=issue>
The [=privacy budget store=] needs to be described in more detail.
Some references to clearing the impression store may need to be
updated to refer to the privacy budget store as well.
## Attribution Logic ## {#s-logic}
A site that measures conversions can specify <dfn>attribution logic</dfn>,
which determines how the [=conversion value=] is allocated to histogram buckets.
The <a method for=PrivateAttribution>measureConversion()</a> function
accepts a <a dict-member for=PrivateAttributionConversionOptions>logic</a> parameter
that specifies the [=attribution logic=].
<xmp class=idl>
enum PrivateAttributionLogic {
"last-touch",
};
</xmp>
Each attribution logic specifies a process for allocating values to histogram buckets.
This logic includes how to select impressions,
how to handle weeks in which the [=privacy budget=] is insufficient,
and (optionally) how to process any additional parameters that might be used.
### Last Touch Attribution ### {#logic-last-touch}
The <dfn enum-value for=PrivateAttributionLogic>"last-touch"</dfn> [=attribution logic=]
indicates that the browser should select
the last (most recent) impression that matches the [[#logic-matching|common matching logic]].
The entire [=conversion value=] (up to the maximum imposed by the [[#dp-budget|privacy budget]])
is allocated to the histogram bucket that was saved with the impression.
Last touch attribution does not select any impression
that was saved during a week
that does not have sufficient [=privacy budget=].
If impressions match from a week
that does not have enough [=privacy budget=],
impressions are not matched for any preceding weeks.
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 <dfn>fill a histogram using last-touch attribution</dfn>,
given <a dictionary lt=PrivateAttributionConversionOptions>|options|</a>:
1. Initialize |impression| to a null value.
1. Initialize |value| to |options|.{{PrivateAttributionConversionOptions/value}}.
1. Let |now| be the current time.<!-- TODO: cite HRTIME spec -->
1. For each |week| starting from the current week
to the oldest week supported by the [=user agent=]:
1. Let |impressions| be the result of invoking [=common matching logic=]
with |options|, |week|, and |now|.
1. If |impressions| is not empty:
1. Retain the value of |week|.
1. Set |impression| to the value in |impressions|
with the most recent |impression|.timestamp.
<!-- TODO define a type for stored impressions -->
1. Exit the loop.
1. If |impression| is null, let |budgetOk| be false.
1. Otherwise, let |budgetOk| be the result of [=deduct privacy budget=]
with |week| and |options|.{{PrivateAttributionConversionOptions/epsilon}}.
1. If |budgetOk| is false, set |value| to 0.
1. If |impression|.<var ignore=''>histogramIndex</var>
is |options|.{{PrivateAttributionConversionOptions/histogramSize}} or greater,
set |value| to 0.
1. If |value| is not 0, set |index|
to |impression|.{{PrivateAttributionImpressionOptions/histogramIndex}}.
1. Otherwise, set |index| to 0.
1. Return a histogram containing |options|.{{PrivateAttributionConversionOptions/histogramSize}} values,
with a value of |value| at an index of |index|
and a value of zero at all other indices.
### Common Impression Matching Logic ### {#logic-matching}
TODO specify how to match using "lookbackDays", "filterData" and "impressionSites".
Discuss "infinite" lookbackDays. Clarify when it apples. When field is missing? Zero?
To perform <dfn>common matching logic</dfn>,
given |options|, |week|, and [=moment=] |now|:
1. If number of days since the end of |week| exceeds |lookbackDays|,
return an empty set.
1. Initialize |matching| to an empty set.
1. For each |impression| in the saved impressions for the |week|:
1. If |now| - |lookbackDays| is after |impression|.timestamp,
continue the loop.
1. If |options|.{{PrivateAttributionConversionOptions/filterData}}
does not match |impression|.filterData,
continue the loop.
1. If |options|.{{PrivateAttributionConversionOptions/impressionSites}}
does not contain |impression|.impressionSite,
continue the loop.
1. Add |impression| to |matching|.
1. Return |matching|.
## User Control and Visibility ## {#user-control}
### Optional Participation ### {#opt-out}
* Users should be able to opt out. Opt out should be undetectable.
Text fragment moved from privacy section:
This mechanism may be a dedicated control
for the Private Attribution API,
or it may be a consolidated privacy control
that applies to multiple features,
including private attribution.
Further, user agent developers should consider interaction
of other privacy modes with the Private Attribution API.
For example, attribution might be disabled in a private browsing mode,
or it might be disabled
if the user has opted out of collection of diagnostic data.
### Visibility ### {#visibility}
* User ability to view the impression store and past report submissions.
# Permissions Policy Integration # {#permission-policy}
This specification defines two [=policy-controlled features=]:
* Invocation of the <a method for=PrivateAttribution>saveImpression()</a> API,
identified by the string "<code><dfn export for="PermissionPolicy"
enum-value>save-impression</dfn></code>".
* Invocation of the <a method for=PrivateAttribution>measureConversion()</a> API,
identified by the string "<code><dfn export for="PermissionPolicy"
enum-value>measure-conversion</dfn></code>".
The [=policy-controlled feature/default allowlist=] for both of these features is
<code><a dfn for="default allowlist">*</a></code>.
<p class=note>Having separate permissions for
<a method for=PrivateAttribution>saveImpression()</a> and
<a method for=PrivateAttribution>measureConversion()</a>
allows pages that do both to limit subresources
to the expected kind of activity.
<p class=note>Enabling permissions by default
simplifies the task of integrating external services.
<p class=note>Permissions policy provides only all-or-nothing control,
it does not enable delegation of a portion of privacy budget.
# Implementation Considerations # {#implementation-considerations}
* Management and distribution of values for the following:
* Histogram size
* Conversion site for impressions
* Impression site for conversions
* Ad IDs
# Aggregation # {#aggregation}
An <dfn>aggregation service</dfn> takes multiple pieces of attribution information
and produces an aggregate metric.
User agent implementations will have different requirements for aggregation.
However, the aggregation process has some common elements.
Firstly, user agents will need to be configured with,
or otherwise obtain,
information about the aggregation service.
This includes the aggregation methods that are supported
and any configuration that is required.
Each aggregation method needs to define
how a histogram is:
* prepared for aggregation,
* encrypted,
* annotated with any necessary metadata, and
* submitted to the aggregation service for aggregation.
The aggregation method also needs to define
how the aggregated result is obtained by a site.
## Multi-Party Computation Aggregation ## {#s-mpc}
A <dfn lt=MPC>Multi-Party Computation (MPC)</dfn> system is one that
involves multiple independent entities
that cooperatively compute an agreed function.
This specification uses an MPC system based on Prio [[PRIO]]
and the <dfn lt=DAP ignore>Distributed Aggregation Protocol (DAP)</dfn> [[DAP]].
This is a two-party MPC system that is characterized by
its reliance on client-provided proofs of correctness for inputs.
This allows for very efficient MPC operation
at a modest cost in the size of submissions to the system.
An aggregator that uses Multi-Party Computation (MPC)
comprises two or more independent services
that cooperate to compute a predefined function.
The basic guarantee provided by MPC
is that only the defined outputs of a function,
plus well-defined leakage,
is revealed to any entity.
The MPC guarantees hold only to the extent that
a subset of the entities that participate are honest.
For the two-party MPC used in Prio,
privacy--
that is, the confidentiality of inputs--
is maintained
as long as either MPC operator remains honest.
This MPC configuration does not protect
against the corruption of the outputs
by either MPC operator.
### Prio and DAP ### {#prio}
The "dap-12-histogram" aggregation method
uses Prio [[PRIO]]
and the Distributed Aggregation Protocol (DAP) [[DAP]].
Specifically, this aggregation method uses
the Prio3L1BoundSum instantiation [[PRIO-L1]]
of the Prio3 Verifiable Distributed Aggregation Function (VDAF) [[VDAF]].
DAP and the Prio3L1BoundSum instantiation define how a report is prepared,
encrypted, and submitted for aggregation.
DAP also defines how an aggregate is obtained
and what configuration is necessary
for a user agent to obtain about the aggregation service.
Several extensions to DAP [[DAP-EXT]] are necessary for this application:
* [[DAP-EXT#name-late-task-binding|Late task binding]]
improves the ability of a site to collect reports
and aggregate them as needed.
* [[DAP-EXT#name-requester-website-identity|Website identity]]
is critical to ensure
that differential privacy protections are effective.
This prevents a malicious actor
that is able to correlate user identity across multiple sites
from exceeding the sensitivity bounds for that user
by aggregating reports from multiple sites together.
* [[DAP-EXT#name-privacy-budget-consumption|Privacy budget consumption]]
ensures that the aggregator does not aggregate reports
that received less privacy budget
than the aggregation task was configured with.
User agents need to include all of these extensions in reports
that they generate.