✨ Consent: Pass consent string and metadata to amp-iframe#29636
✨ Consent: Pass consent string and metadata to amp-iframe#29636zhouyx merged 15 commits intoampproject:masterfrom
Conversation
|
👀 |
|
Thanks @nerdbeere for the Pull Request and my apology for the delay. I agree with you that an API similar to I can think of a few approaches to address this Option 2. Go ahead with your current design. In future we can post all consent changes via the API. Let me know if you think caveat we have today is fine with you, and we can proceed with option 2. Thanks. |
|
thanks for your feedback @zhouyx!
If the implementation in general is fine then can you maybe tell me what we should add/do in order to get this PR merged? Thanks in advance! |
| this.subscriptionApiConsent_.send( | ||
| 'consent-data', | ||
| dict({ | ||
| 'consentMetadata': consents[0], |
There was a problem hiding this comment.
Do you also want to pass the consentState. Asking because it's possible that no consentString or consentMetadata will be set (when there's <amp-consent> but no CMP)
Good thing about the object is that we can always add more field in the future : )
|
|
||
| ## Iframe & Consent Data | ||
|
|
||
| Iframes can send a `send-consent-data` message to receive consent data if a CMP is present on their parents page. |
There was a problem hiding this comment.
Based on the code, value will set only when data-block-on-consent attribute is added to the <amp-iframe> element. Is that expected?
There was a problem hiding this comment.
Good point, that was a mistake on my end.
- adjusted the test page to test with and without
data-block-on-consent - use now
policyId: defaultifdata-block-on-consentnot set - added some information on when to expect a consent response
|
|
||
| this.subscriptionApiConsent_ = new SubscriptionApi( | ||
| iframe, | ||
| 'send-consent-data', |
There was a problem hiding this comment.
nit: please declare the message type to MessageType within 3p-frame-messaging.js
There was a problem hiding this comment.
Thanks for adding the messageType. Could you please also add consent-data there, and use the imported the message string.
|
|
||
| <!-- This should be in alphabetical order. _ping_ should be the first --> | ||
|
|
||
| <!-- _ping_ example --> |
There was a problem hiding this comment.
I think adding the fake CMP _ping_ would be sufficient to test the feature. There's no need to add following <amp-consent> elements.
In this case, you don't need to change to app.js either.
| listenFor(iframe, 'embed-ready', this.activateIframe_.bind(this)); | ||
| } | ||
|
|
||
| this.subscriptionApiConsent_ = new SubscriptionApi( |
There was a problem hiding this comment.
Can we add a unit test to cover the send-consent-data msg? Thanks
|
thank you for your in-depth review @zhouyx! |
| }, | ||
| /*opt_is3P*/ undefined, | ||
| /*opt_includingNestedWindows*/ undefined, | ||
| /*opt_allowOpaqueOrigin*/ true |
There was a problem hiding this comment.
opt_is3P=false because we don't expect sentinel to match here.
opt_includingNestedWindows=false and opt_allowOpaqueOrigin=false because nested window and opaque origin are not supported with sentinel=amp.
Feel free to not include those three optional undefined variables.
|
|
||
| this.subscriptionApiConsent_ = new SubscriptionApi( | ||
| iframe, | ||
| 'send-consent-data', |
There was a problem hiding this comment.
Thanks for adding the messageType. Could you please also add consent-data there, and use the imported the message string.
extensions/amp-iframe/amp-iframe.md
Outdated
| **Please note:** | ||
|
|
||
| - The `consent-data` response will only be sent once and won't update the iframe when the consent state changes (for example when the user decides to reject consent by using the post prompt ui) | ||
| - The response is delayed until the user interacts with the amp-consent ui in case iframe loading is not blocked by using `data-block-on-consent` |
There was a problem hiding this comment.
The response is not delayed until the user interact. It is delayed based on the data-block-on-consent value, and it's corresponding setting.
For example one can customize the consent service to resolve after a 2 seconds timeout. In this case, the response will resolve after 2 seconds, not wait for the user interaction.
| * @param {string} origin | ||
| * @param {JsonObject} data | ||
| * @private | ||
| * @return {Promise} |
There was a problem hiding this comment.
nit: doesn't return a promise. can be removed
|
@zhouyx Thanks again for your help! Would be great if you could re-check again, ideally this would be in the next release as this is very critical for us because of the european privacy laws. |
zhouyx
left a comment
There was a problem hiding this comment.
LGTM. Thanks for contributing!
|
to @alanorozco for owner's approval. |
|
Hi @alanorozco is something blocking this PR? Let me know if you need anything from us in order to get this merged. |
| const consentPolicyId = super.getConsentPolicy() || 'default'; | ||
| const consentStringPromise = this.getConsentString_(consentPolicyId); | ||
| const metadataPromise = this.getConsentMetadata_(consentPolicyId); | ||
| const consentPolicyStatePromise = this.getConsentPolicyState_( |
There was a problem hiding this comment.
nit: You can get rid of these intermediate methods, just call getConsentPolicyInfo, etc. directly.
There was a problem hiding this comment.
Answering for my colleague who is on vacation at the moment. These intermediate methods were introduced so that it is possible to write tests for this functionality (see mocking those functions here: https://github.com/ampproject/amphtml/pull/29636/files#diff-fd3e080d7fded1a7e2423b5ba744238bR945-R951). We've found similar ways to mock the unit-under-test within AMP within the test for send-intersections and embed-size. If we would call getConsentPolicyInfo directly the test would fail.
| window.addEventListener('message', function (event) { | ||
| if ( | ||
| event.source != window.parent || | ||
| event.origin == window.location.origin || | ||
| !event.data || | ||
| event.data.sentinel != 'amp' || | ||
| event.data.type != 'consent-data' | ||
| ) { | ||
| return; | ||
| } | ||
| console.log(event.data.consentMetadata); | ||
| console.log(event.data.consentString); | ||
| }); |
There was a problem hiding this comment.
For sanity I would suggest naming the short-circuit clause.
| window.addEventListener('message', function (event) { | |
| if ( | |
| event.source != window.parent || | |
| event.origin == window.location.origin || | |
| !event.data || | |
| event.data.sentinel != 'amp' || | |
| event.data.type != 'consent-data' | |
| ) { | |
| return; | |
| } | |
| console.log(event.data.consentMetadata); | |
| console.log(event.data.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; | |
| } | |
| window.addEventListener('message', function (event) { | |
| if (!isAmpMessage(event, 'consent-data')) { | |
| return; | |
| } | |
| console.log(event.data.consentMetadata); | |
| console.log(event.data.consentString); | |
| }); |
There was a problem hiding this comment.
Adjusted the docs and also placed the same isAmpMessage function into the send-intersections documentation block. While adjusting the docs and doing a manual test with this isAmpMessage I've found that the sentinel = amp was not send along the consent-data message and I've fixed it with this change: f6110f9
| dict({ | ||
| 'type': MessageType.CONSENT_DATA, | ||
| 'consentMetadata': consents[0], | ||
| 'consentString': consents[1], |
There was a problem hiding this comment.
How do we usually define data types for inbound messages? I wonder if it would make sense to have an intermediate consent object with these values.
There was a problem hiding this comment.
What I've found: for embed-size the properties height and width are next to type (see https://github.com/ampproject/amphtml/blob/master/extensions/amp-iframe/0.1/amp-iframe.js#L467-L476). intersection event sends changes next to type (see https://github.com/ampproject/amphtml/blob/master/src/utils/intersection-observer-3p-host.js#L117-L120).
|
All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the ℹ️ Googlers: Go here for more info. |
|
@googlebot I consent |
|
@alanorozco Hi Alan, in your opinion is this ready to go now? We'd really appreciate if this gets merged soon. Thanks! |
|
I'm going to make the ads/ui team own the 3p iframe messaging related code. |
|
Hi @zhouyx @jridgewell any chance this can be merged now? Thanks! |
|
PR Merged! |
|
Awesome! Thank you. |
|
Hi guys |
|
Just checked, the feature should be available in nightly and beta build already. |
…#29636) * Implement consent reading for 3p iframe * Add documentation for send-consent-data * Fix types * Use only _ping_ cmp on test page and revert changes in app.js * Add MessageType to 3p-frame-messaging.js * Allow retrieving consent without using data-block-on-consent * Add test and some refactoring * Fix linting in documentation * Adjust docs * Introduce and use MessageType and adjust jsdoc comment * Use fixture iframe instead of srcdoc * docs: extract isAmpMessage for receiving intersection and consent-data * Fix for missing sentinel="amp" Co-authored-by: Tobias von Klipstein <tobias@klpstn.com>
As discussed in #28719 it is necessary for us to retrieve the consent data within
amp-iframe.amp-iframeamp-iframewith multiple CMPsamp-video-iframebecause the implementation would probably look differentresolves #28719
related: #26938