diff --git a/extensions/amp-consent/amp-consent.md b/extensions/amp-consent/amp-consent.md index 228e37c16d70..148dc216f6ab 100644 --- a/extensions/amp-consent/amp-consent.md +++ b/extensions/amp-consent/amp-consent.md @@ -41,6 +41,14 @@ Only a single `` element is allowed on the page, and that element m If you also include an `` element on the page, the UI associated with the `` and `` will not be deterministic. Avoid using `` with `` if this would be problematic. +## Granular and global consent + +`` supports **global consent**, in which users can make a single consent choice for a website. It also supports **granular consent**, allowing users to make a set of choices. + +To implement granular consent, define a set of **consent purposes**. Choose a name for each purpose. Create a UI that allows the user to make choices for each, and use the `setPurpose()` action to save each choice. + +The other actions that `` supports apply to both granular and global consent. Thus, a webpage can implement both types simultaneously. + ## Consent configuration The `` element requires a JSON configuration object that specifies the extension's behavior. @@ -118,6 +126,8 @@ AMP expects the response to be a JSON object like the following: } ``` +For granular consent, this response can also contain a map of `purposeConsent` choices. + **Note: The legacy `promptIfUnknown` is migrating to `consentRequired` as prompt is no longer strictly required to manage consents.** The `consentStateValue` can be thought of as a signal for the runtime to block and unblock components. The value `accepted` instructs AMP that the user has given consent (or doesn't revoke consent in the opt-out case). This can be used to serve personalized ads in some scenarios. The value `rejected` means the user doesn't give consent (or has revoked consent in the opt-out case) and vendors may decide to not serve personalized ads. @@ -152,6 +162,16 @@ useful when publishers want to use their own server to decide if consent is requ Note that this value will be ignored if there is previous consent state stored in client cache (see [Client caching](#client-caching) section for examples). +#### purposeConsentRequired + +For [granular consent](#granular-and-global-consent), `purposeConsentRequired` lets you specify an array of consent purposes. Until the user has made a choice for each, the [consent UI](#prompt-ui) will appear each time they visit your webpage. + +For example, if you want to make sure the user makes a choice for consent purposes you've called `purpose-analytics` and `purpose-marketing`, your JSON would include: + +```json +"purposeConsentRequired": ["purpose-analytics", "purpose-marketing"] +``` + #### onUpdateHref `onUpdateHref`: Instructs AMP to make a CORS HTTPS POST request with credentials to the specified URL whenever the stored consent state changes. @@ -345,7 +365,7 @@ _Example_: Displays a prompt user interface on an AMP Story #### Prompt Actions -There are three types of user actions that are associated with the consent prompt: `accept`, `reject` and `dismiss`. +Three user actions apply to both granular and global consent: `accept`, `reject` and `dismiss`. To enable the user to choose a consent state and hide the prompt UI, add an `on` attribute to a button with the following value scheme `on="event:idOfAmpConsentElement.accept/reject/dismiss"` @@ -356,6 +376,26 @@ following value scheme `on="event:idOfAmpConsentElement.accept/reject/dismiss"` - `dismiss`: instruct AMP to cancel `buildCallback` of components waiting for the consent, and hides the prompt UI. +The `setPurpose` action is used in [granular consent](#granular-and-global-consent). You can use it to temporarily store the user's choice for an individual consent purpose. This action takes the form `setPurpose({purpose name}={boolean value})`. Setting a purpose to `true` marks it as accepted; setting it to `false` marks it as rejected. + +For example, to mark a consent purpose called `performanceCookies` as `true`, you would use + +```js +myConsent.setPurpose(performanceCookies=true) +``` + +The `accept` and `reject` actions, which accept or deny global consent, both save granular consent choices as well. If you pass either of these the argument `(purposeConsentDefault={boolean value})`, any consent purposes for which the user has not made a choice will be assigned that boolean value. + +For example, the action + +```js +myConsent.accept(purposeConsentDefault=false) +``` + +will reject any consent purposes for which the user has not made a choice. + +If you don't use `purposeConsentDefault`, any purposes for which the user has not made a choice will remain unset. For this reason, especially when the prompt UI is a form with checkboxes, it's generally recommended that you include this argument. + ### Post-prompt UI (optional) You can provide a UI after collecting the initial consent. For example, you can provide a UI for the user to manage their consent (e.g., change their "reject" to "accept"). The post-prompt UI is defined with the `` JSON configuration object. The `postPromptUI` refers to an element by id. If the element is a child element of the ``, it will be fixed to the bottom of the page same as prompt UIs. You can also inline the `postPromptUI` in the document, but please be aware of the potential layout shift caused by toggling the display of this element. @@ -398,9 +438,11 @@ A couple of implications with this behavior: - When a user travels, `` will use the stored consent. It's up to the `checkConsentHref` response to erase stored value using `expireCache: true` and `consentRequired: false`. - If a promptUI is used to collect user consent. Using `expireCache: true` will prompt consent dialog and block users from content on their following visits. +`` stores consent choices in a key called `amp-store:{xxx}`, where `{xxx}` is your domain. The value is base64-encoded JSON. + ### Basic blocking behaviors -To block components, either add the `data-block-on-consent` attribute to the AMP component or add the `amp-consent-blocking` meta tag with the list of extensions to be blocked. Note, that if you're using the `type` attribute for CMP integration, you must also include the `amp-consent-blocking` meta tag. This ensures that `buildCallback` of the component isn't called until consent has been accepted, or if consent is not required for the user based on the `consentRequired` value. In effect, this means that all behaviors of the element (e.g. sending analytics pings for `` or the loading of an ``) are delayed until the relevant consent instance is accepted. +In global consent, to block components, either add the `data-block-on-consent` attribute to the AMP component or add the `amp-consent-blocking` meta tag with the list of extensions to be blocked. Note, that if you're using the `type` attribute for CMP integration, you must also include the `amp-consent-blocking` meta tag. This ensures that `buildCallback` of the component isn't called until consent has been accepted, or if consent is not required for the user based on the `consentRequired` value. In effect, this means that all behaviors of the element (e.g. sending analytics pings for `` or the loading of an ``) are delayed until the relevant consent instance is accepted. Individual components may override this behavior to provide more specialized handling. Please refer to each component's documentation for details. @@ -416,6 +458,12 @@ or ``` +For granular consent, use the `data-block-on-consent-purposes` attribute with a comma-separated list of consent purposes. For example, the following will block an `amp-pixel` component until the user accepts purposes named `performance` and `marketing`: + +```html + +``` + ### Advanced predefined consent blocking behaviors AMP provides a list of pre-defined [consent policy instances](#policy-instance-optional) for publishers to easily define consent blocking behaviors to individual components.