-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Description
Summary
Create client side granular consent into amp-consent by allowing publishers to add a new data-block-on-consent-purposes attribute onto AMP elements, whose value is a list of publisher defined purposes. This attribute will block AMP elements from being built until all purpose consents have been accepted. Purpose consents will be collected (and stored) by amp-consent, and can also be synced via checkConsentHrefs request and response.
Design document
Original issues and discussion: #26735
Design Doc: https://docs.google.com/document/d/1RThWzCG7-LLzb13lmUNawLkBJCeGyUIi62GefTunIQg/edit
Motivation
A clear and concise description of any alternative solutions or features you've considered.
- Creating a new component or splitting up amp-consent somehow (future work)
- Creating multiple consent instances for each "purpose"
Additional context
Launch tracker
-
Create experiment flag (🧪✨ [amp-consent] Allow
purposeConsentRequiredinline and via endpoint response #32433) -
Expose purposeConsentRequired API through
checkConsentHref& inline (🧪✨ [amp-consent] AllowpurposeConsentRequiredinline and via endpoint response #32433) -
PromptUI changes - create
toggleConsent(), expandacceptandrejectactions, createpurposeConsentMapfrom decisions ✨ [amp-consent] Add purposes to user actions for inline PromptUI #32470 -
PromptUiSrc changes - send and receive
purposeConsentMap(✨ [amp-consent] AcceptpurposeConsentMapfrom external consent UI flow #32638) -
Store the the
purposeConsentMapandpurposeConsentRequiredin local storage through the ConsentManager (✨ [amp-consent] Sync and storepurposeConsentsin localStorage #32721) -
Create Internal API to get purposeConsentMap from ConsentPolicyManager (for syncing) (✨[amp-consent] block buildcallback through granular consent #32990)
-
Runtime and ConsentPolicyManager changes to block building until all purposes are accepted (✨[amp-consent] block buildcallback through granular consent #32990)
-
E2E tests
-
Lauch 100%
-
Cleanup
/cc @ampproject/wg-approvers
Usage
- Add
data-block-on-consent-purposesattributes to elements you want to block based upon consent purposes, and add a list of purposes that you want to be accepted before allowing the component to unblock.
// blocked by AMP runtime
<amp-foo data-block-on-consent-purposes=”purpose-analytics,purpose-foo,purpose-bar”>
// blocked by AMP runtime
<amp-bar data-block-on-consent=”purpose-bar”>
- To signal to
amp-consentwhat consent purposes need to be collected (by comparing against what's stored in local storage) either addpurposeConsentRequired: [‘analytics’, ‘advertising’, ‘vendorA’]to your inline config orcheckConsentHrefresponse ifconsentRequired: remote. If the consent purposes are not found in localStorage then the consent prompt UI will be shown. amp-consentstores the consent information (including this consent purposes) in local storage, to save the decision for next user visit. To opt out of storing, use theexpireCachefeature
// From checkConsentHref endpoint or via inline <amp-consent> config
purposeConsentRequired: [‘purpose-analytics’, ‘purpose-foo’, ‘purpose-bar’]
- Collect purpose consents via
promptUI: Add elements that have a newsetPurposeaction, that takes a list of key value pairs represneting the consent purpose name and if it's been acceptedsetPurpose(consentPurposeName=boolean). You can useevent.checkedfor the boolean value if using a toggle input. Additionally, it is suggested that you add a parameterpurposeConsentDefault=booleanto existingacceptandrejectactions, in the case that the user clicks the accept or reject button without setting all the individual consent purposes
<amp-consent>
<script>
{
consentInstanceId: 'myConsent',
promptUI: 'ui',
...
}
</script>
<div id=’ui’>
<label for="consent-purpose-analytics">
<input
type="checkbox"
on="change: ABC.toggleConsent(purpose-analytics=event.checked)"
id="consent-purpose-analytics"
>
Accept Analytics Consent
</label>
<label for="consent-purpose-foo">
<input
type="checkbox"
on="change: ABC.toggleConsent(purpose-foo=event.checked)"
id="consent-purpose-foo"
>
Accept Foo Consent
</label>
<label for="consent-purpose-bar">
<input
type="checkbox"
on="change: ABC.toggleConsent(purpose-bar=event.checked)"
id="consent-purpose-bar"
>
Accept Bar Consent
</label>
<!--
Even if no elements are blocked with data-block-on-consent, still need to accept or reject.
-->
<button on="tap:ABC.accept(purposeConsentDefault=accepted)">
Save
</button>
<button on="tap:ABC.dismiss">
Close
</button>
</div>
</amp-consent>
- Send the the consent purpose's consent state via
promptUISrcaccept or reject post message to amp-consent . In the data object, add in apurposeConsentsobject that has a string to boolean mapping.
// checkConsentHref response
{
consentRequired: true
purposeConsentRequired: [‘purpose-analytics’, ‘purpose-foo’, ‘purpose-bar’],
consentState: unknown,
purposeConsentMap: undefined,
}
// promptUiSrc’s iframes postmessage response:
{
type: 'consent-response',
action: 'accept',
purposeConsentMap: {
“purpose-analytics”: accept,
“purpose-foo”: reject,
“purpose-bar”: accept
}
}
- Elements that are blocked with
data-block-on-consent-purposes, will be unblocked based off the promptUI - The UI will prompt if not all of the
purposeConsentRequiredpurposes are locally stored (and we have a global consent) - Amp consent will send the stored consent purpose consents via
checkConsentHref. The response can also containpurposeConsentsmapping (just like inpromptUISrc), so amp-consent can update its stored values to be reflected on next visit.