To #15653
Overview
The following sections will try to answer these questions:
- What to include in the prompt dialog and how to allow CMP to customize it?
- What is the blocking behavior with CMP?
- What the data flow looks like between different parties?
- What the CMP needs to do to integrate with AMP?
- What does a publisher need to do to include a CMP solution on their AMP page?
Background
<amp-consent>
provides a solution for publishers to collect user consent and block or unblock any AMP component in an AMP page. Currently, this solution only allows the publisher to collect a boolean consent for all vendors in the consent UI.
To support per purpose and per vendor based consents and allow for third party integration from Consent Management Platforms (CMP) with publisher AMP pages, AMP will enhance <amp-consent>
. It will allow for richer interaction between the publisher page, vendors, CMP and ad extensions on AMP pages that need to know about the consent status. AMP must make such an API for CMPs because AMP doesn’t allow custom JavaScript to run on the page and therefore a CMP must integrate with the AMP framework to integrate with a publishers page.
Data Flow Desing
The following section explains each step in terms of data structure and API.
Read data from localStorage (Step 1)
Data includes the stored consent string and CMP stored information.
Pass information to CMP endpoint (Step 2)
The following data with be passed through a POST request
{
'consentInstanceId': string,
'consentStr': string,
'pubConfig': object,
'cmpStoredData': string,
}
CMP endpoint response (Step 3)
Endpoint returns a JSON object
{
'promptIfUnknown': boolean,
'sharedData': object,
'forcePrompt': boolean, //optional
}
Initiate the UI iframe (Step 4)
Data will be stringified and passed via the iframe name attribute
JSON.stringify({
'publicConfig': object,
'cmpStoredData': string,
'consentStr': string,
})
Iframe returns user decision (Step 5)
UI iframe will pass the consent information back to <amp-consent>
via postMessage
window.parent.postMessage({
type: 'consent-response',
cmpStoredData: '',
consentStr: '',
action: 'accept/reject/dismiss'
}, '*');
consentStr
is required to pass the value to vendors.
action
is optional. When specified, it instructs components that don’t understand consent string to load or not based on the publisher’s configurations.
cmpStoredData
value will be stored per the CMP request
Store consent information (Step 6)
Store the consentStr
and the cmpStoredData
to localStorage
Pass consent information (Step 7)
AMP components on the AMP page (vendors in the format <amp-ad type=${vendorName})>
can access consent information with function call
getConsentPolicySharedData(ampdoc, policyId)
Where the function returns an object that merge the value of consentStr
and sharedData
{
'consentStr': string,
'sharedData': object
}
Blocking Behaviors
Default Blocking Behaviors
When a CMP is present on the page, AMP runtime behavior will default to:
- Block all
<amp-ad>
components on the page from rendering
- Send request to the CMP endpoint to ask whether consent is required
- Check if there’s a response stored in the AMP runtime, or the CMP endpoint returned with a response
- If yes -> Unblock
<amp-ad>
and pass the response to them
- If no -> Prompt the consent collect dialog in a foreign iframe
- Get the response from the prompted iframe
Store the response as instructed.
- Unblock all
<amp-ad>
components (unless the publisher specifies not to by adding the data-block-on-consent
attribute) and passesthe response to them.
Special Cases
Publishers can override the default behavior and customize the blocking behaviors by tagging the components manually.
- If a publisher wants to avoid ad blocking with a CMP,: Use
<amp-ad data-block-on-consent=”_never”>
- If the publisher wishes to block a component other than
<amp-ad>
: Use the existing data-block-on-consent
attribute. However, the value of the returned action (accept/reject/dismiss), depends on the agreement between the publisher and the CMP.
Prompt Window
External Iframe
AMP consent will load and render the CMP’s prompt UI in a cross domain iframe, where the CMP will have full control. However, AMP runtime will control the life cycle of the iframe, dictating when to load or unload it.
- The iframe will be loaded if a user consent is required but missing, or if a user wants to manage their consent at any point.
- The iframe will be unloaded once a user decision has been made and the prompt UI needs to be hidden.
Default placeholder
AMP will apply a placeholder before the CMP iframe loads to improve user experience.
The placeholder will not block the user from interacting with the rest of the page.
UX design will be added once ready.
Iframe Size and Placement
AMP will make the prompt UI interstitial by default. CMP and publishers will NOT be able to customize the size and the placement of the iframe. AMP will create a modal layer and place the iframe with default aspect width and height ratio in the center.
Consent String
Consent string contains the user decision and will be stored and passed to vendors. Vendors will interpret the consent string and respond accordingly.
Format
Because different CMPs want to store different consent strings for customized vendors in addition to the IAB consent string, AMP will not enforce format on the consent string, or attempt to interpret the consent string before passing the information to vendors. AMP would require CMP to indicate their string as IAB so that vendors can understand. Please note in MVP, not API will be provided to vendors, and vendors need to interpret consent string themselves.
Storage Limit
When the cached AMP page is served from the google.com. All information will be stored under the google.com domain. Because of it, AMP consent has to be very cautious of the storage usage.
In order to be space efficient, AMP restricts the size of total stored value to an upper limit of 300 bytes. That includes the consent string and the CMP private stored string, if one exists. CMPs should work with their partner vendors to compress their consent string.
In the case that a CMP asks AMP to store information that exceeds the size limit, AMP will:
- Erase the current stored value
- Log an error
- Unblock
<amp-ad>
components and make the consent string information globally accessible to all AMP components the consent string information but w/o storing the value for next visit.
Access
The consent string is made available to all AMP components on the page and to the CMP.
-
To AMP components and vendors
AMP components can call where the policyId can be interpreted from the data attribute.
getConsentPolicySharedData(ampdoc, policyId)
3P ad that integrate with AMP can find the string at (similar to supported sharedData)
window.context.consentString
-
To CMP
-
CMP will have access to the consent string. Per their request a CMP will also have access to the CMP stored data. Note that passing CMP stored data is not in scope with the initial implementation.
-
The stored value will be divided into two parts.
- Standard Consent string
- Private CMP stored string
Where consent string can be shared to all components, stored string will only be shared with the CMP.
CMP Integration
A CMP named foo_bar
will integrate with AMP in the following way.
Check in configuration
Add the configuration as part of the <amp-consent>
codebase. This will allow AMP to recognize the CMP, perform steps to check if consent is necessary, handle storage and UI.
'foo_bar': {
‘storageKey’: ‘cmp_foo_bar’,
'checkConsentHref': 'https://foo-bar.com/amp/endpoint',
'promptUISrc': 'https://foo-bar.com/cmp.html',
}
storageKey
instructs AMP runtime to store the consent information under this unique key name. Note: AMP will append prefix to the key. If not specified, AMP will assume CMP does not require consent string to be stored client side.
Unlike the current DIY approach with <amp-consent>
, CMP will be able to specify the storage key value instead of publishers. This is easier for CMP to bump up versions because they have control of the storageKey.
checkConsentHref
is a field AMP consent already supports. It allows the AMP consent component to ask the CMP if consent is required for a user. This field is required, as it is the key to instruct AMP runtime to ask for consent and block other components on the page. For more details, please refer to the section here
Note:the existing promptIfUnknowForGeoGroup
for CMP integration won’t be provided as AMP expects CMP to host their own endpoint instead of depending on publishers configuration on the <amp-geo>
component.
src
is the source for the foreign iframe. It is also a required field. Once AMP consent decides to prompt, it will create a foreign iframe with the src given.
Host endpoint
AMP consent will rely on the host endpoint to determine if the prompt is required with the checkConsentHref
request.
Consent Dialog
The CMP will need to modify their prompt logic to function in a cross domain iframe. And communicate with the parent host AMP page through the proposed communication APIs.
Publisher’s Configuration
To work with a CMP, publisher’s configuration will need to stay minimal.
<amp-consent id="ABC" type="foo-bar" layout="nodisplay">
<script type="application/json">{
“cmp”: {
“token”: xxx
}
}</script>
</amp-consent>
Type Attribute
A type attribute with a valid CMP name value instructs the <amp-consent>
component to load the CMP config.
CMP Object
All configuration within the cmp
object will be passed to the CMP, both with checkConsentHref
and iframe (added to the name attribute).
PostPromptUI
CMP’s support to postPromptUI has not been discussed yet. Right now publishers can still put their own postPromptUI element on the page and reference the element.
<amp-consent id="ABC" type="foo-bar" layout="nodisplay">
<script type="application/json">{
"postPromptUI": "postPromptUI"
}</script>
<div id="postPromptUI">
Post Prompt UI
<button on="tap:ABC.prompt" role="button">Manage</button>
</div>
</amp-consent>
Other topics
Below is a list of topics we have talked about but not covered in the current design. We may look into supporting it in the future.
Allow publishers to still use the <amp-geo>
component to reduce one roundtrip of latency
Provide support for CMP to store consent server side but not client side
INTENT TO IMPLEMENT WG: analytics P1: High Priority Component: amp-consent Stale