forked from WICG/attribution-reporting-api
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.bs
4409 lines (3640 loc) · 223 KB
/
index.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: Attribution Reporting
Shortname: attribution-reporting
Level: 1
Status: CG-DRAFT
Group: wicg
Repository: WICG/attribution-reporting-api
URL: https://wicg.github.io/attribution-reporting-api
Editor: Charlie Harrison, Google Inc. https://google.com, [email protected]
Editor: John Delaney, Google Inc. https://google.com, [email protected]
Editor: Andrew Paseltiner, Google Inc. https://google.com, [email protected]
Abstract: An API to report that an event may have been caused by another cross-site event. These reports are designed to transfer little enough data between sites that the sites can't use them to track individual users.
Markup Shorthands: markdown on
Complain About: accidental-2119 on, missing-example-ids on
Assume Explicit For: on
</pre>
<pre class=link-defaults>
spec:html; type:element; text:a
spec:html; type:element; text:script
spec:html; type:dfn; text:feature separators
spec:html; type:dfn; text:follow the hyperlink
spec:html; type:dfn; text:navigation params
spec:html; type:dfn; text:prepare the script element
spec:html; type:dfn; text:script fetch options
spec:html; type:dfn; text:set up the classic script request
spec:html; type:dfn; text:set up the module script request
spec:html; type:dfn; text:tokenize the features argument
spec:html; type:dfn; text:update the image data
spec:html; type:dfn; text:window open steps
spec:webdriver; type:dfn; text:error
</pre>
<pre class="anchors">
spec: clear-site-data; type: dfn; urlPrefix: https://w3c.github.io/webappsec-clear-site-data/
text: clear DOM-accessible storage for origin; url: #abstract-opdef-clear-dom-accessible-storage-for-origin
spec: hr-time; type: dfn; urlPrefix: https://w3c.github.io/hr-time/
text: current wall time; url: #dfn-current-wall-time
text: duration; url: #dfn-duration
text: moment; url: #dfn-moment
spec: idl; type: dfn; urlPrefix: https://webidl.spec.whatwg.org/
text: throw; url: #dfn-throw
spec: webdriver; urlPrefix: https://w3c.github.io/webdriver/
type: dfn
text: getting a property; url: dfn-getting-properties
text: error code; url: dfn-error-code
spec: uuid; type: dfn; urlPrefix: https://wicg.github.io/uuid/
text: generate a random UUID; url: #dfn-generate-a-random-uuid
spec: private-state-token-api; type: dfn; urlPrefix: https://wicg.github.io/trust-token-api/
text: look up the key commitments; url: #look-up-the-key-commitments
text: generate masked tokens; url: #generate-masked-tokens
text: unmask tokens; url: #unmask-tokens
text: sec-private-state-token-crypto-version; url: #sec-private-state-token-crypto-version
spec: structured header; type: dfn; urlPrefix: https://httpwg.org/specs/rfc8941;
text: structured header; url: #introduction
for: structured header
text: define new structured fields; url: #specify
text: dictionary; url: #dictionary
text: item; url: #item
text: list; url: #list
text: parameter; url: #param
text: parse a list; url: #parse-list
text: parse a string; url: #parse-string
text: parse structured fields; url: #text-parse
text: serialize a list; url: #ser-list
text: serialize a string; url: #ser-string
text: string; url: #string
text: token; url: #token
spec: infra; type: dfn; urlPrefix: https://infra.spec.whatwg.org/
text: starts with; url: #string-starts-with
spec: fenced-frame; type: dfn; urlPrefix: https://wicg.github.io/fenced-frame/;
for: navigable
text: top-level traversable; url: #navigable-top-level-traversable
spec: multipage; type: dfn; urlPrefix: https://html.spec.whatwg.org/multipage/;
for: scheme and host
text: host; url: #concept-scheme-and-host-host
</pre>
<pre class=biblio>
{
"chan": {
"title": "Channel capacity",
"href": "https://en.wikipedia.org/wiki/Channel_capacity"
},
"dp": {
"title": "Differential privacy",
"href": "https://en.wikipedia.org/wiki/Differential_privacy"
},
"rr": {
"title": "Randomized response",
"href": "https://en.wikipedia.org/wiki/Randomized_response"
},
"bin-ent": {
"title": "Binary entropy function",
"href": "https://en.wikipedia.org/wiki/Binary_entropy_function"
},
"q-sc": {
"authors": [
"Claudio Weidmann",
"Gottfried Lechner"
],
"title": "q-ary symmetric channel",
"href": "https://arxiv.org/pdf/0909.2009.pdf"
}
}
</pre>
Introduction {#intro}
=====================
<em>This section is non-normative</em>
This specification describes how web browsers can provide a mechanism to the
web that supports measuring and attributing conversions (e.g. purchases) to ads
a user interacted with on another site. This mechanism should remove one need
for cross-site identifiers like third-party cookies.
## Overview ## {#overview}
Pages/embedded sites are given the ability to register [=attribution sources=] and
[=attribution triggers=], which can be linked by the User Agent to generate and
send [=attribution reports=] containing information from both of those events.
A reporter `https://reporter.example` embedded on `https://source.example` is able to
measure whether an interaction on the page lead to an action on `https://destination.example`
by registering an [=attribution source=] with [=attribution source/attribution destinations=]
of « `https://destination.example` ». Reporters are able to register sources through a variety
of surfaces, but ultimately the reporter is required to provide the User Agent with an
HTTP-response header which allows the source to be eligible for attribution.
At a later point in time, the reporter, now embedded on `https://destination.example`,
may register an [=attribution trigger=]. Reporters can register triggers by sending an
HTTP-response header containing information about the action/event that occurred. Internally,
the User Agent attempts to match the trigger to previously registered source events based on
where the sources/triggers were registered and configurations provided by the reporter.
If the User Agent is able to attribute the trigger to a source, it will generate and
send an [=attribution report=] to the reporter via an HTTP POST request at a later point
in time.
# HTML monkeypatches # {#html-monkeypatches}
<h3 id="monkeypatch-attributionsrc">API for elements</h3>
<pre class="idl">
interface mixin HTMLAttributionSrcElementUtils {
[CEReactions, SecureContext] attribute USVString attributionSrc;
};
HTMLAnchorElement includes HTMLAttributionSrcElementUtils;
HTMLImageElement includes HTMLAttributionSrcElementUtils;
HTMLScriptElement includes HTMLAttributionSrcElementUtils;
</pre>
Add the following <a spec=html>content attributes</a>:
: <{a}>
:: <dfn for="a" element-attr>attributionsrc</dfn> - A [=string=] containing
zero or more [=URLs=] to which a background attributionsrc request will be
made when the <{a}> is navigated.
: <{img}>
:: <dfn for="img" element-attr>attributionsrc</dfn> - A [=string=] containing
zero or more [=URLs=] to which a background attributionsrc request will be
made when set.
: <{script}>
:: <dfn for="script" element-attr>attributionsrc</dfn> - A [=string=] containing
zero or more [=URLs=] to which a background attributionsrc request will be
made when set.
The IDL attribute {{HTMLAttributionSrcElementUtils/attributionSrc}}
must <a spec=html>reflect</a> the respective content attribute of the same
name.
Whenever an <{img}> or a <{script}> |element| is created or |element|'s
{{HTMLAttributionSrcElementUtils/attributionSrc}} attribute is set or changed,
run [=make background attributionsrc requests=] with |element| and
"<code>[=eligibility/event-source-or-trigger=]</code>".
Issue: More precisely specify which mutations are relevant for the
attributionsrc attribute.
Modify [=update the image data=] as follows:
After the step
> Set |request|'s [=request/priority=] to the current state...
add the step
1. If the element has an <{img/attributionsrc}> attribute, set
|request|'s [=request/Attribution Reporting Eligibility=] to
"<code>[=eligibility/event-source-or-trigger=]</code>".
A [=script fetch options=] has an associated <dfn for="script fetch options">
Attribution Reporting eligibility</dfn> (an [=eligibility=]). Unless otherwise
stated it is "<code>[=eligibility/unset=]</code>".
Modify [=prepare the script element=] as follows:
After the step
> Let <var ignore=''>fetch priority</var> be the current state of |el|'s <{script/fetchpriority}>
> content attribute.
add the step
1. Let |Attribution Reporting eligibility| be
"<code>[=eligibility/event-source-or-trigger=]</code>" if |el| has an
<{script/attributionsrc}> content attribute and
"<code>[=eligibility/unset=]</code>" otherwise.
Add "and [=script fetch options/Attribution Reporting eligibility=] is
|Attribution Reporting eligibility|." to the step
> Let <var ignore=''>options</var> be a [=script fetch options=] whose...
Modify [=set up the classic script request=] and
[=set up the module script request=] as follows:
Add "and its [=request/Attribution Reporting eligibility=] is |options|'s
[=script fetch options/Attribution Reporting eligibility=]."
Modify [=follow the hyperlink=] as follows:
After the step
> If |subject|'s link types includes...
add the steps
1. Let |navigationSourceEligible| be false.
1. If |subject| has an `attributionsrc` attribute:
1. Set |navigationSourceEligible| to true.
1. [=Make background attributionsrc requests=] with |subject| and
"<code>[=eligibility/navigation-source=]</code>".
Add "and [=navigate/navigationSourceEligible=] set to
|navigationSourceEligible|" to the step
> [=Navigate=] <var ignore=''>targetNavigable</var>...
<h3 id="monkeypatch-window-open">Window open steps</h4>
Modify the [=tokenize the features argument=] as follows:
Replace the step
> [=Collect a sequence of code points=] that are not [=feature separators=] code
> points from |features| given |position|. Set |value| to the collected code
> points, [=ASCII lowercase|converted to ASCII lowercase=].
with
[=Collect a sequence of code points=] that are not [=feature separators=] code
points from |features| given |position|. Set |value| to the collected code
points, [=ASCII lowercase|converted to ASCII lowercase=]. Set
|originalCaseValue| to the collected code points.
Replace the step
> If |name| is not the empty string, then set |tokenizedFeatures|[|name|] to
> |value|.
with the steps
1. If |name| is not the empty string:
1. Switch on |name|:
<dl class="switch">
: "`attributionsrc`"
:: Run the following steps:
1. If |tokenizedFeatures|[|name|] does not [=map/exists|exist=],
[=map/set=] |tokenizedFeatures|[|name|] to a new [=list=].
1. [=list/Append=] |originalCaseValue| to |tokenizedFeatures|[|name|].
: Anything else
:: [=map/Set=] |tokenizedFeatures|[|name|] to |value|.
</dl>
Modify the [=window open steps=] as follows:
After the step
> Let |tokenizedFeatures| be the result of
> [=tokenize the features argument|tokenizing=] |features|.
add the steps
1. Let |navigationSourceEligible| be false.
1. If |tokenizedFeatures|["`attributionsrc`"] [=map/exists=]:
1. [=Assert=]: |tokenizedFeatures|["`attributionsrc`"] is a [=list=].
1. Set |navigationSourceEligible| to true.
1. Set |attributionSrcUrls| to a new [=list=].
1. [=list/iterate|For each=] |value| of
|tokenizedFeatures|["`attributionsrc`"]:
1. If |value| is the empty string, [=iteration/continue=].
1. Let |decodedSrcBytes| be the result of
[=string/percent-decode|percent-decoding=] |value|.
1. Let |decodedSrc| be the [=UTF-8 decode without BOM=] of
|decodedSrcBytes|.
1. <a spec="HTML" lt="parse a URL">Parse</a> |decodedSrc| relative to
the <a spec="HTML" lt="entry settings object">entry settings object</a>,
and set |urlRecord| to the resulting [=URL record=], if any. If
parsing failed, [=iteration/continue=].
1. [=list/Append=] |urlRecord| to |attributionSrcUrls|.
Issue: Use |attributionSrcUrls| with [=make a background attributionsrc request=].
In each step that calls [=navigate=], set [=navigate/navigationSourceEligible=]
to |navigationSourceEligible|.
## Navigation monkeypatches ## {#navigation-monkeypatches}
Add the following item to [=navigation params=]:
: <dfn for="navigation params">navigationSourceEligible</dfn>
:: A boolean indicating whether the navigation can register a
[=source type/navigation=] [=attribution source|source=] in its response.
Defaults to false.
Modify [=navigate=] as follows:
Add an optional boolean parameter called <dfn for="navigate">
<var>navigationSourceEligible</var></dfn>, defaulting to false.
In the step
> Set <var ignore=''>navigationParams</var> to a new [=navigation params=]
> with...
add the property
: [=navigation params/navigationSourceEligible=]
:: |navigationSourceEligible|
Issue: Use/propagate [=navigation params/navigationSourceEligible=] to the
[=navigation request=]'s [=request/Attribution Reporting eligibility=].
# Network monkeypatches # {#network-monkeypatches}
<pre class="idl">
dictionary AttributionReportingRequestOptions {
required boolean eventSourceEligible;
required boolean triggerEligible;
};
partial dictionary RequestInit {
AttributionReportingRequestOptions attributionReporting;
};
partial interface XMLHttpRequest {
[SecureContext]
undefined setAttributionReporting(AttributionReportingRequestOptions options);
};
</pre>
A [=request=] has an associated
<dfn export for=request>Attribution Reporting eligibility</dfn> (an [=eligibility=]).
Unless otherwise stated it is "<code>[=eligibility/unset=]</code>".
A [=request=] has an associated
<dfn for=request>trigger verification metadata</dfn> which is null or a [=trigger verification metadata=].
To <dfn>get an eligibility from {{AttributionReportingRequestOptions}}</dfn>
given an optional {{AttributionReportingRequestOptions}} |options|:
1. If |options| is null, return "<code>[=eligibility/unset=]</code>".
1. Let |eventSourceEligible| be |options|'s
{{AttributionReportingRequestOptions/eventSourceEligible}}.
1. Let |triggerEligible| be |options|'s
{{AttributionReportingRequestOptions/triggerEligible}}.
1. If (|eventSourceEligible|, |triggerEligible|) is:
<dl class="switch">
: (false, false)
:: Return "<code>[=eligibility/empty=]</code>".
: (false, true)
:: Return "<code>[=eligibility/trigger=]</code>".
: (true, false)
:: Return "<code>[=eligibility/event-source=]</code>".
: (true, true)
:: Return "<code>[=eligibility/event-source-or-trigger=]</code>".
</dl>
Issue: Check permissions policy.
"<code><dfn>Attribution-Reporting-Eligible</dfn></code>" is a
[=structured header/dictionary|Dictionary Structured Header=]
set on a [=request=] that indicates which registrations, if
any, are allowed on the corresponding [=response=]. Its values are not specified
and its <dfn lt="eligible key">allowed keys</dfn> are:
<dl dfn-for="eligible key">
: "<dfn><code>event-source</code></dfn>"
:: An [=source type/event=] [=attribution source|source=] may be registered.
: "<dfn><code>navigation-source</code></dfn>"
:: A [=source type/navigation=] [=attribution source|source=] may be registered.
: "<dfn><code>trigger</code></dfn>"
:: A [=attribution trigger|trigger=] may be registered.
</dl>
To <dfn>obtain a dictionary structured header value</dfn> given a [=list=] of [=strings=] |keys| and
a [=set=] of [=strings=] |allowedKeys|:
1. [=set/iterate|For each=] |key| of |allowedKeys|, optionally [=list/append=] the
[=string/concatenation=] of « "`not-`", |key| » to |keys|.
1. Optionally, [=shuffle a list|shuffle=] |keys|.
1. Let |entries| be a new [=list=].
1. [=list/iterate|For each=] |key| of |keys|:
1. Let |value| be true.
1. Optionally, set |value| to a [=structured header/token=]
corresponding to one of [=strings=] in |allowedKeys|.
1. Let |params| be an [=map/is empty|empty=] [=map=].
1. [=set/iterate|For each=] |key| of |allowedKeys|, optionally [=map/set=] |params|[|key|] to an
arbitrary [=structured header/item|bare item=].
1. [=list/Append=] a structured dictionary member with the key |key|, the
value |value|, and the parameters |params| to |entries|.
1. Return a [=structured header/dictionary=] containing |entries|.
Note: The user agent MAY "[=structured header/define new structured fields|grease=]" the
dictionary structured headers according to the preceding algorithm to help ensure that recipients
use a proper structured header parser, rather than naive string equality or
`contains` operations, which makes it easier to introduce backwards-compatible
changes to the header definition in the future. Including the allowed keys
as dictionary *values* or *parameters* helps ensure that only the dictionary's
keys are interpreted by the recipient. Likewise, shuffling the dictionary
members helps ensure that, e.g., "`key1, key2`" is treated equivalently to "`key2, key1`".
In the following example, only the "`trigger`" key should be interpreted by the
recipient after the header has been parsed as a structured dictionary:
<pre class="example" heading="Greased Attribution-Reporting-Eligible header">
Attribution-Reporting-Eligible: not-event-source, trigger=event-source;navigation-source=3
</pre>
To <dfn>set Attribution Reporting headers</dfn> given a [=request=] |request|
and an [=origin=] |contextOrigin|:
1. Let |headers| be |request|'s [=request/header list=].
1. Let |eligibility| be |request|'s [=request/Attribution Reporting eligibility=].
1. [=header list/Delete=] "<code>[=Attribution-Reporting-Eligible=]</code>" from
|headers|.
1. [=header list/Delete=] "<code>[=Attribution-Reporting-Support=]</code>" from
|headers|.
1. If |eligibility| is "<code>[=eligibility/unset=]</code>", return.
1. Let |keys| be an [=list/is empty|empty=] [=list=].
1. If |eligibility| is:
<dl class="switch">
: "<code>[=eligibility/empty=]</code>"
:: Do nothing.
: "<code>[=eligibility/event-source=]</code>"
:: [=list/Append=] "<code>[=eligible key/event-source=]</code>" to |keys|.
: "<code>[=eligibility/navigation-source=]</code>"
:: [=list/Append=] "<code>[=eligible key/navigation-source=]</code>" to
|keys|.
: "<code>[=eligibility/trigger=]</code>"
:: 1. [=list/Append=] "<code>[=eligible key/trigger=]</code>" to |keys|.
:: 1. [=Set trigger verification request headers=] with |request| and |contextOrigin|.
: "<code>[=eligibility/event-source-or-trigger=]</code>"
:: [=list/Append=] "<code>[=eligible key/event-source=]</code>" and
"<code>[=eligible key/trigger=]</code>" to |keys|.
1. Let |dict| be the result of [=obtaining a dictionary structured header value=] with
|keys| and the [=set=] containing all the [=eligible keys=].
1. [=header list/Set a structured field value=] given
("<code>[=Attribution-Reporting-Eligible=]</code>", |dict|) in |headers|.
1. [=Set an OS-support header=] in |headers|.
<h3 id="monkeypatch-fetch">Fetch monkeypatches</h4>
Modify [=fetch=] as follows:
Add a [=Document=] parameter called |document|.
After the step
> If |request|'s [=request/header list=] does not contain `Accept`...
add the step
1. [=Set Attribution Reporting headers=] with |request| and |document|'s [=node/context origin=].
Modify {{Request/constructor(input, init)}} as follows:
In the step
> Set |request| to a new [=request=] with the following properties:
add the property
: [=request/Attribution Reporting eligibility=]
:: |request|'s [=request/Attribution Reporting eligibility=].
After the step
> If |init|["`priority`"] [=map/exists=], then:
add the step
1. If |init|["{{RequestInit/attributionReporting}}"] [=map/exists=], then set
|request|'s [=request/Attribution Reporting eligibility=] to the result of
[=get an eligibility from AttributionReportingRequestOptions=] with it.
<h3 id="monkeypatch-xmlhttprequest">XMLHttpRequest monkeypatches</h4>
An {{XMLHttpRequest}} object has an associated
<dfn id="xmlhttprequest-eligibility">Attribution Reporting eligibility</dfn> (an
[=eligibility=]). Unless otherwise stated it is
"<code>[=eligibility/unset=]</code>".
The {{XMLHttpRequest/setAttributionReporting(options)}} method must run these
steps:
1. If <a>this</a>'s
<a href="https://xhr.spec.whatwg.org/#concept-xmlhttprequest-state">state</a>
is not <i>opened</i>, then [=throw=] an
"{{InvalidStateError!!exception}}" {{DOMException}}.
1. If <a>this</a>'s
<a href="https://xhr.spec.whatwg.org/#send-flag">`send()` flag</a> is set,
then [=throw=] an "{{InvalidStateError!!exception}}" {{DOMException}}.
1. Set <a>this</a>'s <a href=#xmlhttprequest-eligibility>Attribution Reporting
eligibility</a> to the result of
[=get an eligibility from AttributionReportingRequestOptions=] with
|options|.
Modify {{XMLHttpRequest/send(body)}} as follows:
Add a [=Document=] parameter called |document|.
After the step:
> Let |req| be a new [=request=], initialized as follows...
Add the step:
1. Set |req|'s [=request/Attribution Reporting eligibility=] to <a>this</a>'s <a href=#xmlhttprequest-eligibility>Attribution Reporting
eligibility</a>.
1. [=Set Attribution Reporting headers=] with |req| and |document|'s [=node/context origin=].
# Permissions Policy integration # {#permission-policy-integration}
This specification defines a [=policy-controlled feature=] identified by the string "<code><dfn export for="PermissionPolicy" enum-value>attribution-reporting</dfn></code>".
Its [=policy-controlled feature/default allowlist=] is <a href="https://w3c.github.io/webappsec-permissions-policy/#default-allowlist">`*`</a>.
# Clear Site Data integration # {#clear-site-data-integration}
In [=clear DOM-accessible storage for origin=], add the following step:
> 7. Run [=clear site data=] with |origin|.
To <dfn>clear site data</dfn> given an [=origin=] |origin|:
1. [=set/iterate|For each=] [=attribution source=] |source| of the [=attribution source cache=]:
1. If |source|'s [=attribution source/reporting origin=] and |origin| are [=same origin=],
[=set/remove=] |source| from the [=attribution source cache=].
1. [=set/iterate|For each=] [=event-level report=] |report| of the [=event-level report cache=]:
1. If |report|'s [=event-level report/reporting origin=] and |origin| are [=same origin=],
[=set/remove=] |report| from the [=event-level report cache=].
1. [=set/iterate|For each=] [=aggregatable report=] |report| of the [=aggregatable report cache=]:
1. If |report|'s [=aggregatable report/reporting origin=] and |origin| are [=same origin=],
[=set/remove=] |report| from the [=aggregatable report cache=].
Note: We deliberately do *not* remove matching entries from the
[=attribution rate-limit cache=], as doing so would allow a site to reset and
therefore exceed the intended rate limits at will.
# Structures # {#structures}
<h3 dfn-type=dfn>Registration info</h3>
A registration info is a [=struct=] with the following items:
<dl dfn-for="registration info">
: <dfn>preferred platform</dfn>
:: Null or a [=registrar=].
: <dfn>report header errors</dfn>
:: A [=boolean=].
</dl>
<h3 dfn-type=dfn>Trigger state</h3>
A trigger state is a [=struct=] with the following items:
<dl dfn-for="trigger state">
: <dfn>trigger data</dfn>
:: A non-negative 64-bit integer.
: <dfn>report window</dfn>
:: A [=report window=].
</dl>
<h3 dfn-type=dfn>Randomized response output configuration</h3>
A randomized response output configuration is a [=struct=] with the following items:
<dl dfn-for="randomized response output configuration">
: <dfn>max attributions per source</dfn>
:: A positive integer.
: <dfn>trigger specs</dfn>
:: A [=trigger spec map=].
</dl>
<h3 dfn-type=dfn>Randomized source response</h3>
A randomized source response is null or a [=set=] of [=trigger states=].
<h3 id="attribution-filtering">Attribution filtering</h3>
A <dfn>filter value</dfn> is an [=ordered set=] of [=strings=].
A <dfn>filter map</dfn> is an [=ordered map=] whose [=map/key|keys=] are [=strings=] and whose
[=map/value|values=] are [=filter values=].
A <dfn>filter config</dfn> is a [=struct=] with the following items:
<dl dfn-for="filter config">
: <dfn>map</dfn>
:: A [=filter map=].
: <dfn>lookback window</dfn>
:: Null or a positive [=duration=].
</dl>
<h3 dfn-type=dfn>Suitable origin</h3>
A suitable origin is an [=origin=] that is [=check if an origin is suitable|suitable=].
<h3 id="source-type-header">Source type</h3>
A <dfn>source type</dfn> is one of the following:
<dl dfn-for="source type">
: "<dfn><code>navigation</code></dfn>"
:: The source was associated with a top-level navigation.
: "<dfn><code>event</code></dfn>"
:: The source was not associated with a top-level navigation.
</dl>
<h3 id="report-window-header">Report window</h3>
A <dfn>report window</dfn> is a [=struct=] with the following items:
<dl dfn-for="report window">
: <dfn>start</dfn>
:: A [=moment=].
: <dfn>end</dfn>
:: A [=moment=], strictly greater than [=report window/start=].
</dl>
A <dfn>report window list</dfn> is a [=list=] of [=report windows=].
It has the following constraints:
* Elements are in ascending order based on their [=report window/start=].
* Every element's [=report window/start=] is equal to the previous element's [=report window/end=], if it exists.
* There is at least one element in the list.
A [=report window list=] |list|'s <dfn for="report window list">total window</dfn> is
a [=report window=] [=struct=] with the following fields:
: [=report window/start=]
:: The [=report window/start=] of |list|[0].
: [=report window/end=]
:: The [=report window/end=] of |list|[|list|'s [=list/size=] - 1].
Note: The [=report window list/total window=] is conceptually a union of
[=report windows=], because there are no gaps in time between any of the
[=report windows|windows=].
<h3 id="summary-windows-operator-header">Summary window operator</h3>
A <dfn>summary window operator</dfn> summarizes the triggers within a
[=report window=]. Its value is one of the following:
<dl dfn-for="summary window operator">
: "<dfn><code>count</code></dfn>"
:: Number of triggers attributed.
: "<dfn><code>value_sum</code></dfn>"
:: Sum of the value of triggers.
</dl>
<h3 id="summary-bucket-header">Summary bucket</h3>
A <dfn>summary bucket</dfn> is a [=struct=] with the following items:
<dl dfn-for="summary bucket">
: <dfn>start</dfn>
:: An unsigned 32-bit integer.
: <dfn>end</dfn>
:: An unsigned 32-bit integer.
</dl>
A <dfn>summary bucket list</dfn> is a [=list=] of [=summary buckets=].
It has the following constraints:
* Elements are strictly in ascending order based on their [=summary bucket/start=].
* Every element's [=summary bucket/end=] is equal to the next element's [=summary bucket/start=] - 1, if it exists.
* There is at least one element in the list.
<h3 id="trigger-data-matching-mode-header">Trigger-data matching mode</h3>
A <dfn>trigger-data matching mode</dfn> is one of the following:
<dl dfn-for="trigger-data matching mode">
: "<dfn><code>exact</code></dfn>"
:: [=event-level trigger configuration/Trigger data=] must be less than the
[=default trigger data cardinality=]. Otherwise, no event-level attribution
takes place.
: "<dfn><code>modulus</code></dfn>"
:: [=event-level trigger configuration/Trigger data=] is taken modulo the
[=default trigger data cardinality=].
</dl>
<h3 id="trigger-specs-header">Trigger specs</h3>
A <dfn>trigger spec</dfn> is a [=struct=] with the following items:
<dl dfn-for="trigger spec">
: <dfn>event-level report windows</dfn>
:: A [=report window list=].
</dl>
A <dfn>trigger spec map</dfn> is a [=map=] whose keys are unsigned 32-bit
integers and values are [=trigger specs=].
To <dfn>find a matching trigger spec</dfn> given an [=attribution source=]
|source| and an unsigned 64-bit integer |triggerData|:
1. Let |specs| be |source|'s [=attribution source/trigger specs=].
1. If |source|'s [=attribution source/trigger-data matching mode=] is:
<dl class="switch">
: "<code>[=trigger-data matching mode/exact=]</code>"
:: Run the following steps:
1. If |specs|[|triggerData|] [=map/exists=], return its [=map/entry=].
1. Return null.
: "<code>[=trigger-data matching mode/modulus=]</code>"
:: Run the following steps:
1. If |specs| [=map/is empty=], return null.
1. Let |keys| be |specs|'s [=map/get the keys|keys=].
1. Let |index| be the remainder when dividing |triggerData| by |keys|'s
[=set/size=].
1. Return the [=map/entry=] for |specs|[|keys|[|index|]].
</dl>
<h3 dfn-type=dfn>Attribution source</h3>
An attribution source is a [=struct=] with the following items:
<dl dfn-for="attribution source">
: <dfn>source identifier</dfn>
:: A [=string=].
: <dfn>source origin</dfn>
:: A [=suitable origin=].
: <dfn>event ID</dfn>
:: A non-negative 64-bit integer.
: <dfn>attribution destinations</dfn>
:: An [=ordered set=] of [=sites=].
: <dfn>reporting origin</dfn>
:: A [=suitable origin=].
: <dfn>source type</dfn>
:: A [=source type=].
: <dfn>expiry</dfn>
:: A [=duration=].
: <dfn>trigger specs</dfn>
:: A [=trigger spec map=].
: <dfn>aggregatable report window</dfn>
:: A [=report window=].
: <dfn>priority</dfn>
:: A 64-bit integer.
: <dfn>source time</dfn>
:: A [=moment=].
: <dfn>number of event-level reports</dfn>
:: Number of [=event-level reports=] created for this [=attribution source=].
: <dfn>Max number of event-level reports</dfn>
:: The maximum number of [=event-level reports=] that can be created for this [=attribution source=].
: <dfn>event-level attributable</dfn> (default true)
:: A [=boolean=].
: <dfn>dedup keys</dfn>
:: [=ordered set=] of [=event-level trigger configuration/dedup keys=] associated with this [=attribution source=].
: <dfn>randomized response</dfn>
:: A [=randomized source response=].
: <dfn>randomized trigger rate</dfn>
:: A number between 0 and 1 (both inclusive).
: <dfn>filter data</dfn>
:: A [=filter map=].
: <dfn>debug key</dfn>
:: Null or a non-negative 64-bit integer.
: <dfn>aggregation keys</dfn>
:: An [=ordered map=] whose [=map/key|keys=] are [=strings=] and whose [=map/value|values=] are
non-negative 128-bit integers.
: <dfn>aggregatable budget consumed</dfn>
:: A non-negative integer, total [=aggregatable contribution/value=] of all [=aggregatable contributions=] created with this [=attribution source=].
: <dfn>aggregatable dedup keys</dfn>
:: [=ordered set=] of [=aggregatable dedup key/dedup key|aggregatable dedup key values=] associated with this [=attribution source=].
: <dfn>debug reporting enabled</dfn>
:: A [=boolean=].
: <dfn>number of aggregatable reports</dfn>
:: Number of [=aggregatable reports=] created for this [=attribution source=].
: <dfn>trigger-data matching mode</dfn>
:: A [=trigger-data matching mode=].
: <dfn>debug cookie set</dfn> (default false)
:: A [=boolean=].
</dl>
An [=attribution source=] |source|'s <dfn for="attribution source">expiry time</dfn> is |source|'s [=attribution source/source time=] + |source|'s [=attribution source/expiry=].
An [=attribution source=] |source|'s <dfn for="attribution source">source site</dfn> is the result
of [=obtain a site|obtaining a site=] from |source|'s [=attribution source/source origin=].
<h3 dfn-type=dfn>Aggregatable trigger data</h3>
An aggregatable trigger data is a [=struct=] with the following items:
<dl dfn-for="aggregatable trigger data">
: <dfn>key piece</dfn>
:: A non-negative 128-bit integer.
: <dfn>source keys</dfn>
:: An [=ordered set=] of [=strings=].
: <dfn>filters</dfn>
:: A [=list=] of [=filter configs=].
: <dfn>negated filters</dfn>
:: A [=list=] of [=filter configs=].
</dl>
<h3 dfn-type=dfn>Aggregatable values configuration</h3>
An aggregatable values configuration is a [=struct=] with the following items:
<dl dfn-for="aggregatable values configuration">
: <dfn>values</dfn>
:: A [=map=] whose [=map/key|keys=] are [=strings=] and whose [=map/value|values=] are non-negative 32-bit integers.
: <dfn>filters</dfn>
:: A [=list=] of [=filter configs=].
: <dfn>negated filters</dfn>
:: A [=list=] of [=filter configs=].
</dl>
<h3 dfn-type=dfn>Aggregatable dedup key</h3>
An aggregatable dedup key is a [=struct=] with the following items:
<dl dfn-for="aggregatable dedup key">
: <dfn>dedup key</dfn>
:: Null or a non-negative 64-bit integer.
: <dfn>filters</dfn>
:: A [=list=] of [=filter configs=].
: <dfn>negated filters</dfn>
:: A [=list=] of [=filter configs=].
</dl>
<h3 dfn-type=dfn>Event-level trigger configuration</h3>
An event-level trigger configuration is a [=struct=] with the following items:
<dl dfn-for="event-level trigger configuration">
: <dfn>trigger data</dfn>
:: A non-negative 64-bit integer.
: <dfn>dedup key</dfn>
:: Null or a non-negative 64-bit integer.
: <dfn>priority</dfn>
:: A 64-bit integer.
: <dfn>filters</dfn>
:: A [=list=] of [=filter configs=].
: <dfn>negated filters</dfn>
:: A [=list=] of [=filter configs=].
</dl>
<h3 id="aggregation-coordinator-header">Aggregation coordinator</h3>
An <dfn>aggregation coordinator</dfn> is one of a user-agent-determined [=set=]
of [=suitable origins=] that specifies which aggregation service deployment to use.
<h3 id="aggregatable-source-registration-time-configuration-header">Aggregatable source registration time configuration</h3>
An <dfn>aggregatable source registration time configuration</dfn> is one of the following:
<dl dfn-for="aggregatable source registration time configuration">
: "<dfn><code>exclude</code></dfn>"
:: "`source_registration_time`" is excluded from an [=aggregatable report=]'s [=aggregatable report/shared info=].
: "<dfn><code>include</code></dfn>"
:: "`source_registration_time`" is included in an [=aggregatable report=]'s [=aggregatable report/shared info=].
</dl>
<h3 dfn-type=dfn>Attribution trigger</h3>
An attribution trigger is a [=struct=] with the following items:
<dl dfn-for="attribution trigger">
: <dfn>attribution destination</dfn>
:: A [=site=].
: <dfn>trigger time</dfn>
:: A [=moment=].
: <dfn>reporting origin</dfn>
:: A [=suitable origin=].
: <dfn>filters</dfn>
:: A [=list=] of [=filter configs=].
: <dfn>negated filters</dfn>
:: A [=list=] of [=filter configs=].
: <dfn>debug key</dfn>
:: Null or a non-negative 64-bit integer.
: <dfn>event-level trigger configurations</dfn>
:: A [=set=] of [=event-level trigger configuration=].
: <dfn>aggregatable trigger data</dfn>
:: A [=list=] of [=aggregatable trigger data=].
: <dfn>aggregatable values configurations</dfn>
:: A [=list=] of [=aggregatable values configuration=].
: <dfn>aggregatable dedup keys</dfn>
:: A [=list=] of [=aggregatable dedup key=].
: <dfn>verifications</dfn>
:: A [=list=] of [=trigger verification=].
: <dfn>debug reporting enabled</dfn>
:: A [=boolean=].
: <dfn>aggregation coordinator</dfn>
:: An [=aggregation coordinator=].
: <dfn>aggregatable source registration time configuration</dfn>
:: An [=aggregatable source registration time configuration=].
: <dfn>trigger context ID</dfn>
:: Null or a [=string=].
</dl>
<h3 dfn-type=dfn>Attribution report</h3>
An attribution report is a [=struct=] with the following items:
<dl dfn-for="attribution report, aggregatable report, event-level report">
: <dfn>reporting origin</dfn>
:: A [=suitable origin=].
: <dfn>report time</dfn>
:: A [=moment=].
: <dfn>report ID</dfn>
:: A [=string=].
: <dfn>source debug key</dfn>
:: Null or a non-negative 64-bit integer.
: <dfn>trigger debug key</dfn>
:: Null or a non-negative 64-bit integer.
</dl>
<h3 dfn-type=dfn>Event-level report</h3>
An event-level report is an [=attribution report=] with the following additional items:
<dl dfn-for="event-level report">
: <dfn>event ID</dfn>
:: A non-negative 64-bit integer.
: <dfn>source type</dfn>
:: A [=source type=].
: <dfn>trigger data</dfn>
:: A non-negative 64-bit integer.
: <dfn>randomized trigger rate</dfn>
:: A number between 0 and 1 (both inclusive).
: <dfn>trigger priority</dfn>
:: A 64-bit integer.
: <dfn>trigger time</dfn>
:: A [=moment=].
: <dfn>source identifier</dfn>
:: A string.
: <dfn>attribution destinations</dfn>
:: An [=ordered set=] of [=sites=].
</dl>
<h3 dfn-type=dfn>Aggregatable contribution</h3>
An aggregatable contribution is a [=struct=] with the following items:
<dl dfn-for="aggregatable contribution">
: <dfn>key</dfn>
:: A non-negative 128-bit integer.
: <dfn>value</dfn>
:: A non-negative 32-bit integer.
</dl>
<h3 dfn-type=dfn>Aggregatable report</h3>
An aggregatable report is an [=attribution report=] with the following additional items:
<dl dfn-for="aggregatable report">
: <dfn>source time</dfn>
:: A [=moment=].
: <dfn>contributions</dfn>
:: A [=list=] of [=aggregatable contributions=].
: <dfn>effective attribution destination</dfn>
:: A [=site=].
: <dfn>serialized private state token</dfn>