Skip to content

Commit

Permalink
Add CONSENT_STATE macro support for amp-analytics (ampproject#20995)
Browse files Browse the repository at this point in the history
* consent_state macro

* address comment
  • Loading branch information
zhouyx authored and Noran Azmy committed Mar 22, 2019
1 parent ab9d633 commit 13db695
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 3 deletions.
25 changes: 25 additions & 0 deletions examples/amp-consent.amp.html
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
</style>
<script async custom-element="amp-ad" src="https://cdn.ampproject.org/v0/amp-ad-0.1.js"></script>
<script async custom-element="amp-consent" src="https://cdn.ampproject.org/v0/amp-consent-0.1.js"></script>
<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
Expand All @@ -156,6 +157,30 @@
</header>
<main role="main">
<h3>Image that is blocked by '_till_responded' consent</h3>

<amp-analytics type="_ping_">
<script type="application/json">
{
"requests": {
"old": "https://fake.com/analytics?consent=CONSENT_STATE"
},
"vars": {
"abc": "${timestamp}.${requestCount}"
},
"triggers": {
"onetime": {
"on": "visible",
"request": "old"
}
},
"transport": {
"beacon": "false",
"xhrpost": "false",
"image": "true"
}
}
</script>
</amp-analytics>
<amp-img
data-block-on-consent='_till_responded'
src="https://lh3.googleusercontent.com/pSECrJ82R7-AqeBCOEPGPM9iG9OEIQ_QXcbubWIOdkY=w300-h200-no-n" width=300 height=200></amp-img>
Expand Down
7 changes: 7 additions & 0 deletions extensions/amp-analytics/0.1/requests.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import {BatchSegmentDef, defaultSerializer} from './transport-serializer';
import {
ExpansionOptions,
getConsentStateStr,
variableServiceFor,
} from './variables';
import {SANDBOX_AVAILABLE_VARS} from './sandbox-vars-whitelist';
Expand All @@ -38,6 +39,9 @@ export class RequestHandler {
*/
constructor(element, request, preconnect, transport, isSandbox) {

/** @const {!Element} */
this.element_ = element;

/** @const {!../../../src/service/ampdoc-impl.AmpDoc} */
this.ampdoc_ = element.getAmpDoc();

Expand Down Expand Up @@ -121,6 +125,9 @@ export class RequestHandler {
const bindings = this.variableService_.getMacros();
bindings['RESOURCE_TIMING'] = getResourceTiming(
this.win, trigger['resourceTimingSpec'], this.startTime_);
// TODO: (@zhouyx) Move to variable service once that becomes
// a doc level services
bindings['CONSENT_STATE'] = getConsentStateStr(this.element_);

if (!this.baseUrlPromise_) {
expansionOption.freezeVar('extraUrlParams');
Expand Down
14 changes: 13 additions & 1 deletion extensions/amp-analytics/0.1/test/test-requests.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ describes.realWin('Requests', {amp: 1}, env => {
});
});

it('should replace dynamic bindings', function* () {
it('should replace dynamic bindings RESOURCE_TIMING', function* () {
const spy = sandbox.spy();
const r = {'baseUrl': 'r1&${resourceTiming}'};
const handler = createRequestHandler(r, spy);
Expand All @@ -382,6 +382,18 @@ describes.realWin('Requests', {amp: 1}, env => {
expect(spy).to.be.calledWith('r1&resource-timing');
});

it('should replace dynamic bindings CONSENT_STATE', function* () {
const spy = sandbox.spy();
const r = {'baseUrl': 'r1&$CONSENT_STATEtest&${consentState}test2'};
const handler = createRequestHandler(r, spy);
const expansionOptions = new ExpansionOptions({
'consentState': 'CONSENT_STATE',
});
handler.send({}, {}, expansionOptions);
yield macroTask();
expect(spy).to.be.calledWith('r1&test&test2');
});

describe('expandPostMessage', () => {
let expansionOptions;
let params;
Expand Down
22 changes: 22 additions & 0 deletions extensions/amp-analytics/0.1/variables.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import {Services} from '../../../src/services';
import {base64UrlEncodeFromString} from '../../../src/utils/base64';
import {devAssert, user, userAssert} from '../../../src/log';
import {getConsentPolicyState} from '../../../src/consent';
import {getService, registerServiceBuilder} from '../../../src/service';
import {isArray, isFiniteNumber} from '../../../src/types';
import {tryResolve} from '../../../src/utils/promise';
Expand All @@ -27,6 +28,13 @@ const TAG = 'amp-analytics/variables';
/** @const {RegExp} */
const VARIABLE_ARGS_REGEXP = /^(?:([^\s]*)(\([^)]*\))|[^]+)$/;

const EXTERNAL_CONSENT_POLICY_STATE_STRING = {
1: 'accepted',
2: 'rejected',
3: 'unknown_not_required',
4: 'dismissed',
};

/** @typedef {{name: string, argList: string}} */
let FunctionNameArgsDef;

Expand Down Expand Up @@ -293,3 +301,17 @@ export function variableServiceFor(win) {
export function getNameArgsForTesting(key) {
return getNameArgs(key);
}

/**
* Get the resolved consent state value to send with analytics request
* @param {!Element} element
* @return {!Promise<?string>}
*/
export function getConsentStateStr(element) {
return getConsentPolicyState(element).then(consent => {
if (!consent) {
return null;
}
return EXTERNAL_CONSENT_POLICY_STATE_STRING[consent];
});
}
1 change: 1 addition & 0 deletions extensions/amp-analytics/0.1/vendors.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export const ANALYTICS_CONFIG = /** @type {!JsonObject} */ ({
'canonicalPath': 'CANONICAL_PATH',
'canonicalUrl': 'CANONICAL_URL',
'clientId': 'CLIENT_ID',
'consentState': 'CONSENT_STATE',
'contentLoadTime': 'CONTENT_LOAD_TIME',
'counter': 'COUNTER',
'documentCharset': 'DOCUMENT_CHARSET',
Expand Down
4 changes: 2 additions & 2 deletions src/consent.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import {user} from './log';
* Returns a promise that resolve when all consent state the policy wait
* for resolve. Or if consent service is not available.
* @param {!Element|!ShadowRoot} element
* @param {string} policyId
* @param {string=} policyId
* @return {!Promise<?CONSENT_POLICY_STATE>}
*/
export function getConsentPolicyState(element, policyId) {
export function getConsentPolicyState(element, policyId = 'default') {
return Services.consentPolicyServiceForDocOrNull(element)
.then(consentPolicy => {
if (!consentPolicy) {
Expand Down

0 comments on commit 13db695

Please sign in to comment.