Skip to content

Commit 32a1ac2

Browse files
authored
✨ Resolve ATTRIBUTION_REPORTING_STATUS in attributionsrc/src for generated pixels (#39132)
* Resolve ATTRIBUTION_REPORTING_STATUS in attributionsrc/src for generated pixels * Resolve ATTRIBUTION_REPORTING_STATUS in attributionsrc/src for generated pixels * Update attributionsrc to attributionSrc * Update attributionsrc to attributionSrc in tests * Update attributionsrc to attributionSrc in tests
1 parent b4b0153 commit 32a1ac2

File tree

5 files changed

+84
-23
lines changed

5 files changed

+84
-23
lines changed

extensions/amp-ad-exit/0.1/amp-ad-exit.js

+4-11
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ import {Services} from '#service';
1414

1515
import {getData} from '#utils/event-helper';
1616
import {dev, devAssert, user, userAssert} from '#utils/log';
17-
import {isAttributionReportingAllowed} from '#utils/privacy-sandbox-utils';
17+
import {
18+
AttributionReportingStatus,
19+
isAttributionReportingAllowed,
20+
} from '#utils/privacy-sandbox-utils';
1821

1922
import {TransportMode, assertConfig, assertVendor} from './config';
2023
import {makeClickDelaySpec} from './filters/click-delay';
@@ -40,16 +43,6 @@ const TAG = 'amp-ad-exit';
4043
*/
4144
let NavigationTargetDef;
4245

43-
/**
44-
* Indicates the status of the `attribution-reporting` API.
45-
* @enum
46-
*/
47-
const AttributionReportingStatus = {
48-
ATTRIBUTION_MACRO_PRESENT: 4,
49-
ATTRIBUTION_DATA_PRESENT: 5,
50-
ATTRIBUTION_DATA_PRESENT_AND_POLICY_ENABLED: 6,
51-
};
52-
5346
export class AmpAdExit extends AMP.BaseElement {
5447
/** @param {!AmpElement} element */
5548
constructor(element) {

src/pixel.js

+48-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import {createElementWithAttributes} from '#core/dom';
22
import {WindowInterface} from '#core/window/interface';
33

4+
import {Services} from '#service';
5+
46
import {user} from '#utils/log';
57

6-
import {isAttributionReportingAllowed} from './utils/privacy-sandbox-utils';
8+
import {
9+
AttributionReportingStatus,
10+
isAttributionReportingAllowed,
11+
} from './utils/privacy-sandbox-utils';
712

813
/** @const {string} */
914
const TAG = 'pixel';
@@ -67,10 +72,31 @@ function createImagePixel(win, src, noReferrer = false, attributionSrc) {
6772
if (noReferrer) {
6873
image.referrerPolicy = 'no-referrer';
6974
}
70-
image.src = src;
71-
if (isAttributionReportingAllowed(win.document)) {
72-
image.attributionsrc = attributionSrc;
75+
76+
let attributionReportingStatus =
77+
AttributionReportingStatus.ATTRIBUTION_DATA_UNSPECIFIED;
78+
if (attributionSrc != null) {
79+
if (isAttributionReportingAllowed(win.document)) {
80+
attributionReportingStatus =
81+
AttributionReportingStatus.ATTRIBUTION_DATA_PRESENT_AND_POLICY_ENABLED;
82+
const substituteVariables =
83+
getAttributionReportingStatusUrlVariableRewriter(
84+
win,
85+
attributionReportingStatus
86+
);
87+
attributionSrc = substituteVariables(attributionSrc);
88+
image.attributionSrc = attributionSrc;
89+
} else {
90+
attributionReportingStatus =
91+
AttributionReportingStatus.ATTRIBUTION_DATA_PRESENT;
92+
}
7393
}
94+
const substituteVariables = getAttributionReportingStatusUrlVariableRewriter(
95+
win,
96+
attributionReportingStatus
97+
);
98+
src = substituteVariables(src);
99+
image.src = src;
74100
return image;
75101
}
76102

@@ -83,3 +109,21 @@ function createImagePixel(win, src, noReferrer = false, attributionSrc) {
83109
function isReferrerPolicySupported() {
84110
return 'referrerPolicy' in Image.prototype;
85111
}
112+
113+
/**
114+
* @param {!Window} win
115+
* @param {string=} status
116+
* @return {function(string): string}
117+
*/
118+
function getAttributionReportingStatusUrlVariableRewriter(win, status) {
119+
const substitutionFunctions = {
120+
'ATTRIBUTION_REPORTING_STATUS': () => status,
121+
};
122+
const replacements = Services.urlReplacementsForDoc(win.document);
123+
const allowlist = {
124+
'ATTRIBUTION_REPORTING_STATUS': true,
125+
};
126+
127+
return (url) =>
128+
replacements.expandUrlSync(url, substitutionFunctions, allowlist);
129+
}

src/utils/privacy-sandbox-utils.js

+11
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,14 @@ export function isAttributionReportingAvailable(doc) {
1515
export function isAttributionReportingAllowed(doc) {
1616
return doc.featurePolicy?.allowedFeatures().includes('attribution-reporting');
1717
}
18+
19+
/**
20+
* Indicates the status of the `attribution-reporting` API.
21+
* @enum
22+
*/
23+
export const AttributionReportingStatus = {
24+
ATTRIBUTION_DATA_UNSPECIFIED: 0,
25+
ATTRIBUTION_MACRO_PRESENT: 4,
26+
ATTRIBUTION_DATA_PRESENT: 5,
27+
ATTRIBUTION_DATA_PRESENT_AND_POLICY_ENABLED: 6,
28+
};

test/unit/builtins/test-amp-pixel.js

+20-7
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,16 @@ describes.realWin('amp-pixel', {amp: true}, (env) => {
142142
it('should not allow attribution reporting', () => {
143143
const attributionSrc =
144144
'//pubads.g.doubleclick.net/activity;dc_iu=1/abc;ord=2';
145+
pixel.setAttribute(
146+
'src',
147+
'https://pubads.g.doubleclick.net/activity;dc_iu=1/abc;ord=1?ars=ATTRIBUTION_REPORTING_STATUS'
148+
);
145149
return trigger(null, attributionSrc).then((img) => {
146150
// Protocol is resolved to `http:` relative to test server.
147151
expect(img.src).to.equal(
148-
'https://pubads.g.doubleclick.net/activity;dc_iu=1/abc;ord=1?'
152+
'https://pubads.g.doubleclick.net/activity;dc_iu=1/abc;ord=1?ars=5'
149153
);
150-
expect(img.attributionsrc).to.be.undefined;
154+
expect(img.attributionSrc).to.be.undefined;
151155
});
152156
});
153157

@@ -156,26 +160,35 @@ describes.realWin('amp-pixel', {amp: true}, (env) => {
156160
.stub(privacySandboxUtils, 'isAttributionReportingAllowed')
157161
.returns(true);
158162
const attributionSrc = '';
163+
pixel.setAttribute(
164+
'src',
165+
'https://pubads.g.doubleclick.net/activity;dc_iu=1/abc;ord=1?ars=ATTRIBUTION_REPORTING_STATUS'
166+
);
159167
return trigger(null, attributionSrc).then((img) => {
160168
// Protocol is resolved to `http:` relative to test server.
161169
expect(img.src).to.equal(
162-
'https://pubads.g.doubleclick.net/activity;dc_iu=1/abc;ord=1?'
170+
'https://pubads.g.doubleclick.net/activity;dc_iu=1/abc;ord=1?ars=6'
163171
);
164-
expect(img.attributionsrc).to.equal('');
172+
expect(img.attributionSrc).to.equal('');
165173
});
166174
});
167175

168176
it('should allow attribution reporting with attributionsrc defined', () => {
169177
env.sandbox
170178
.stub(privacySandboxUtils, 'isAttributionReportingAllowed')
171179
.returns(true);
172-
const attributionSrc = 'https://adtech.example';
180+
pixel.setAttribute(
181+
'src',
182+
'https://pubads.g.doubleclick.net/activity;dc_iu=1/abc;ord=1?ars=ATTRIBUTION_REPORTING_STATUS'
183+
);
184+
const attributionSrc =
185+
'https://adtech.example?ars=ATTRIBUTION_REPORTING_STATUS';
173186
return trigger(null, attributionSrc).then((img) => {
174187
// Protocol is resolved to `http:` relative to test server.
175188
expect(img.src).to.equal(
176-
'https://pubads.g.doubleclick.net/activity;dc_iu=1/abc;ord=1?'
189+
'https://pubads.g.doubleclick.net/activity;dc_iu=1/abc;ord=1?ars=6'
177190
);
178-
expect(img.attributionsrc).to.equal('https://adtech.example');
191+
expect(img.attributionSrc).to.equal('https://adtech.example?ars=6');
179192
});
180193
});
181194
});

testing/helpers/service.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ export class ImagePixelVerifier {
369369
const pixel = this.imagePixels_.shift();
370370
expect(pixel.src).to.equal(url);
371371
expect(pixel.referrerPolicy).to.equal(referrerPolicy);
372-
expect(pixel.attributionsrc).to.equal(attributionSrc);
372+
expect(pixel.attributionSrc).to.equal(attributionSrc);
373373
}
374374

375375
verifyRequestMatch(regex) {

0 commit comments

Comments
 (0)