ampproject / ampproject/amphtml
I2I: Client Side Granular Consent
- Dominant language
- JavaScript
- Stars
- 14.9k
- Forks
- 4.1k
- PR merge metrics
- No merged PRs in 30d
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 `checkConsentHref`s request and response.
## Design document
Original issues and discussion: https://github.com/ampproject/amphtml/issues/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
- [x] Create experiment flag (#32433)
- [x] Expose purposeConsentRequired API through `checkConsentHref` & inline (#32433)
- [x] PromptUI changes - create `toggleConsent()`, expand `accept` and `reject` actions, create `purposeConsentMap` from decisions #32470
- [x] PromptUiSrc changes - send and receive `purposeConsentMap` (#32638)
- [x] Store the the `purposeConsentMap` and `purposeConsentRequired` in local storage through the ConsentManager (#32721)
- [x] Create Internal API to get purposeConsentMap from ConsentPolicyManager (for syncing) (#32990)
- [x] Runtime and ConsentPolicyManager changes to block building until all purposes are accepted (#32990)
- [ ] E2E tests
- [x] Lauch 100%
- [x] Cleanup
/cc @ampproject/wg-approvers
## Usage
- Add `data-block-on-consent-purposes` attributes 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
// blocked by AMP runtime
```
- To signal to `amp-consent` what consent purposes need to be collected (by comparing against what's stored in local storage) either add `purposeConsentRequired: [‘analytics’, ‘advertising’, ‘vendorA’]` to your inline config or `checkConsentHref` response if `consentRequired: remote`. If the consent purposes are not found in localStorage then the consent prompt UI will be shown.
- `amp-consent` stores the consent information (including this consent purposes) in local storage, to save the decision for next user visit. To opt out of storing, use the [`expireCache`](https://github.com/ampproject/amphtml/blob/master/extensions/amp-consent/amp-consent.md#client-caching) feature
```
// From checkConsentHref endpoint or via inline config
purposeConsentRequired: [‘purpose-analytics’, ‘purpose-foo’, ‘purpose-bar’]
```
- Collect purpose consents via `promptUI`: Add elements that have a new `setPurpose` action, that takes a list of key value pairs represneting the consent purpose name and if it's been accepted `setPurpose(consentPurposeName=boolean)`. You can use `event.checked` for the boolean value if using a toggle input. Additionally, it is suggested that you add a parameter `purposeConsentDefault=boolean` to existing `accept` and `reject` actions, in the case that the user clicks the accept or reject button without setting all the individual consent purposes
```
{
consentInstanceId: 'myConsent',
promptUI: 'ui',
...
}
Accept Analytics Consent
Accept Foo Consent
Accept Bar Consent
Save
Close
```
- Send the the consent purpose's consent state via `promptUISrc` accept or reject post message to amp-consent . In the data object, add in a `purposeConsents` object 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 `purposeConsentRequired` purposes are locally stored (and we have a global consent)
- Amp consent will send the stored consent purpose consents via `checkConsentHref`. The response can also contain `purposeConsents` mapping (just like in `promptUISrc`), so amp-consent can update its stored values to be reflected on next visit.
Contributor guide
Assessment
This issue has not been assessed yet.