Cookie Consent Support for AMP Websites
This document provides a step-by-step guide to implementing Cookie Consent on Accelerated Mobile Pages (AMP) websites.
While this solution will work for the General Data Protection Regulation (GDPR), Accelerated Mobile Publishing (AMP) does not currently support granular consent for different cookie categories. However, this solution does support granular consent via IAB TCF 2.2 Purposes or the Google Additional Consent String.
Additionally, the California Consumer Privacy Act (CCPA) will be supported with this AMP component framework and can be used for CCPA compliance. The updates allow you to include multiple consent prompts and trigger the correct response based upon the site visitor's location.
To implement a Cookie Consent solution for an AMP site, you will need the following:
- A valid AMP site.
- A plain HTML page on the same root domain as the AMP site, but a different sub-domain. For example, if the AMP site is under amp.example.com the plain HTML page could be under iframe.example.com.
- The OneTrust Cookie Consent solution.
To Implement Cookie Consent Support for AMP
In the <head>
section of your website, add the elements below:
- Add the
<amp-consent>
tag to your AMP Site by inserting the<amp-consent>
script.
For more information, see amp-consent.
<script async custom-element="amp-consent" src="https://cdn.ampproject.org/v0/amp-consent-0.1.js"></script>
- You will also need the
<amp-geo>
tag if it is not already present. Add the<amp-geo>
tag to your AMP Site by inserting the<amp-geo>
script.
For more information, see amp-geo.
<script async custom-element="amp-geo" src="https://cdn.ampproject.org/v0/amp-geo-0.1.js"></script>
- Add the
<amp-iframe>
tag to your AMP Site by inserting the<amp-iframe>
.
For more information, see amp-iframe.
<script async custom-element="amp-iframe" src="https://cdn.ampproject.org/v0/amp-iframe-0.1.js"></script>
- Add the OneTrust Cookie Banner script to the section of your plain HTML page.
For details on how to configure this script, see Publishing and Implementing Cookie Consent Scripts.
- Example: OneTrust Cookie Banner Script.
<!-- OneTrust Cookies Consent Notice start -->
<script src="https://cdn.cookielaw.org/scripttemplates/otSDKStub.js" type="text/javascript" charset="UTF-8" data-domain-script="xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx">
</script>
<!-- OneTrust Cookies Consent Notice end -->
- Add the following code segment to your plain HTML page. Replace [COOKIE-ID] with a specific cookie category ID you have selected. To locate this ID, navigate to Cookie Consent > Categorizations > Categories. This setup relies on the [COOKIE-ID] which is used as control to allow the AMP website to determine whether ads or other elements can be shown based on the state of the [COOKIE-ID] (category). The plain HTML page is used as an iFrame on your AMP page and this script on the plain HTML page allows consent choices to be communicated back to the AMP page. This enables the AMP website to utilize user consent to load content and ad management while complying with legal requirements.
Here's a brief breakdown of what the code does: The script initiates a request to retrieve consent data from the AMP page. It checks whether CCPA/GDPR or IAB TCF frameworks are in use and initializes event handlers to track consent through button interactions like accepting or rejecting. After detection of the framework and user's choice, the script responds back to the AMP page accepting or rejecting cookies based on the [COOKIE-ID].
<script>
var consentState, consentString, has_amp_key = false, isTCF2 = false, isFirst = true;
window.parent.postMessage(
{
sentinel: 'amp',
type: 'send-consent-data'
},
'*'
);
window.addEventListener('message', function (event) {
// will fetch only if AMP key is present
if (!isAmpMessage(event, 'consent-data')) {
return
}
has_amp_key = true;
});
function OptanonWrapper() {
// Check if it's CMP or TCF
if (typeof __cmp === "function") {
__cmp("getConsentData", Array, function (e) {
consentString = e.consentData;
});
isTCF2 = false;
}
if (typeof __tcfapi === "function") {
__tcfapi("getTCData", 2, (tcData, success) => {
if (success) {
consentString = tcData.tcString;
} else {
}
isTCF2 = true;
});
}
initialiseBtnHandlers();
window.addEventListener('OneTrustPCLoaded', function () {
initialiseBtnHandlers();
});
if (!getCookie("OptanonAlertBoxClosed") && isFirst && !has_amp_key) {
isFirst = false;
if (Optanon.GetDomainData().ShowAlertNotice == false) {
send2Amp(consentString);
}
} else if (isFirst && has_amp_key) {
isFirst = false;
Optanon.ToggleInfoDisplay();
} else {
send2Amp(consentString);
}
}
function isAmpMessage(event, type) {
return (
event.source == window.parent &&
event.origin != window.location.origin &&
event.data &&
event.data.sentinel == 'amp' &&
event.data.type == type
);
}
function initialiseBtnHandlers() {
var PCCloseButton = document.getElementById("close-pc-btn-handler");
var PCbutton = document.getElementById("onetrust-pc-btn-handler");
var PClink = document.getElementsByClassName("ot-sdk-show-settings");
var listButton = document.getElementsByClassName(
"onetrust-vendors-list-handler"
);
PCbutton &&
PCbutton.addEventListener("click", function () {
iFrameState("consent-ui", "enter-fullscreen");
});
PCCloseButton &&
PCCloseButton.addEventListener("click", function () {
iFrameState("consent-response", "dismiss");
});
for (var i = 0; i < listButton.length; i++) {
listButton[i] &&
listButton[i].addEventListener("click", function () {
iFrameState("consent-ui", "enter-fullscreen");
});
}
for (var i = 0; i < PClink.length; i++) {
PClink[i] &&
PClink[i].addEventListener("click", function () {
iFrameState("consent-ui", "enter-fullscreen");
});
}
}
function iFrameState(type, action) {
window.parent.postMessage({
type: type,
action: action,
initialHeight: "60vh"
}, '*');
}
function send2Amp(consentString) {
var payload = {
type: 'consent-response',
info: consentString,
};
if (OptanonActiveGroups.indexOf('[COOKI-ID]') === -1) {
payload.action = 'reject';
}
if(OptanonActiveGroups.indexOf('[COOKIE-ID]') !== -1) {
payload.action = 'accept';
}
if (isTCF2) {
payload.consentMetadata = {
"consentStringType": 2,
"gdprApplies": true,
"additionalConsent": getCookie("OTAdditionalConsentString"),
}
}
window.parent.postMessage(payload, "*");
}
</script>
<script>
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length == 2)
return parts.pop().split(";").shift();
}
</script>
- Add the following code segment to you AMP Site. Replace [PATH TO THE PLAIN HTML PAGE] with the path to the plain HTML page configured in the previous step. This step involves setting up the AMP page to display a template based on the user’s location. The banner appears as an iFrame that displays content from the plain HTML page, enabling the AMP page to comply with regional privacy laws like GDPR and CCPA.
Here's a brief breakdown of what the code does: It displays a cookie banner (via an iFrame) based on the user’s geographic location and loads the consent management functionality from the plain HTML page as an iFrame, allowing users to manage their consent settings by interacting with the cookie banner on the AMP page.
<style amp-custom>
body {
margin: 0px;
}
amp-consent {
background-color: transparent;
}
amp-consent #post-consent-ui,
.amp-geo-group-eea amp-consent #consentDialog {
padding-bottom: 45px;
}
.consentPopup {
padding: var(--space-3);
margin: 0 auto;
position: relative;
background-color: transparent;
width: 100%;
height: 100vh;
}
.consentPopup amp-iframe {
background-color: transparent;
}
.manage-settings-link {
color: blue;
text-decoration: underline;
cursor: pointer;
}
</style>
<amp-geo layout="nodisplay">
<script type="application/json">
{
"ISOCountryGroups": {
"us": ["us"]
}
}
</script>
</amp-geo>
<amp-consent layout="nodisplay" id="consent-element">
<script type="application/json">
{
"consents": {
"eu": {
"promptIfUnknownForGeoGroup": "us",
"promptUI": "myConsentFlow"
}
},
"postPromptUI": "post-consent-ui"
}
</script>
<div id="myConsentFlow" class="popupOverlay">
<div class="consentPopup">
<amp-iframe id='idFrame' layout="fill" resizable sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" src="[PATH TO THE PLAIN HTML PAGE]">
<div placeholder></div>
<div overflow></div>
</amp-iframe>
</div>
</div>
<div id="post-consent-ui">
<a on="tap:consent-element.prompt;" role="button" class="manage-settings-link">Do Not Sell My Personal Information</a>
</div>
</amp-consent>
- In order for the
<amp-consent>
framework to work for AMP ads, you need to add an attribute called<amp-ad>
. To configure<amp-ad>
to block the ad until consent is given, add thedata-block-on-consent
element to<amp-ad>
. This ensures thatbuildCallback
of the component is not called until consent has been given or the consent prompt has been skipped bypromptIfUnknownForGeoGroup
. This will rely on consent being given to [COOKIE-ID] defined.
For more information, see amp-ad.
- Example: Blocking ads until the user gives consent.
<amp-ad
data-block-on-consent
type="a9"
data-amzn_assoc_ad_mode="auto"
data-divid="amzn-assoc-ad-fe746097-f142-4f8d-8dfb-45ec747632e5"
data-recomtype="async"
data-adinstanceid="fe746097-f142-4f8d-8dfb-45ec747632e5"
width="300"
height="250"
data-aax_size="300x250"
data-aax_pubname="test123"
data-aax_src="302">
</amp-ad>
Updated 6 days ago