Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IntentIq ID & Analytics Modules: GDPR support and update documentation #12738

Conversation

dmytro-po
Copy link
Contributor

@dmytro-po dmytro-po commented Feb 6, 2025

  • Bugfix
  • Feature
  • Refactoring (no functional changes, no api changes)

Description of change

Updated CMP data processing. Added support for GDPR.

| params.allowGDPR | Optional | Boolean | This flag determines whether the use of GDPR (General Data Protection Regulation) data is allowed. If set to true, the use of GDPR data will be allowed. The GDPR string can either be provided by the partner or taken from the framework. If set to false, the use of GDPR data will be prohibited. By default, it is set to true. | `true`|
| params.allowGPP | Optional | Boolean | This flag determines whether the use of USP (US Privacy) data is allowed. If set to true, the use of USP data will be allowed. If set to false, the use of USP data will be prohibited. By default, it is set to true. | `true`|
| params.allowUSP | Optional | Boolean | This flag determines whether the use of GPP (Global Privacy Platform) data is allowed. If set to true, the use of GPP data will be allowed. If set to false, the use of GPP data will be prohibited. By default, it is set to true. | `true`|
| params.providedGDPR | Optional | String | This parameter is used to provide the GDPR consent string by the partner. If providedGDPR is empty, the consent string will be taken from the framework. | `"provided_gdpr_string"`|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not allowed; you must take the string you get from the framework. If you want publishers to be able to override that and you think that is not currently possible, you need to propose a pr the framework, which will be heavily scrutinized given the subject matter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, in many cases, our partners can obtain the TCF string before configuring the settings. To avoid making an additional framework call, we provide them with the option to directly input this string in the configuration, allowing us to use it. However, since rules are rules, we will remove this option. Thanks.

Copy link
Collaborator

@patmmccann patmmccann Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be clear, what you are describing is prohibited as of https://www.dataprotectionauthority.be/citizen/iab-europe-held-responsible-for-a-mechanism-that-infringes-the-gdpr?utm_source=chatgpt.com for the same reason no one can use getTCData any longer. You have to hit the tcf api at event time, you can't refer to some old string. Prebid is keeping track of the current string using the evnet listeners.

@@ -43,6 +43,12 @@ Please find below list of paramters that could be used in configuring Intent IQ
| params.browserBlackList | Optional |  String | This is the name of a browser that can be added to a blacklist. | `"chrome"` |
| params.manualWinReportEnabled | Optional | Boolean | This variable determines whether the bidWon event is triggered automatically. If set to false, the event will occur automatically, and manual reporting with reportExternalWin will be disabled. If set to true, the event will not occur automatically, allowing manual reporting through reportExternalWin. The default value is false. | `true`|
| params.domainName | Optional | String | Specifies the domain of the page in which the IntentIQ object is currently running and serving the impression. This domain will be used later in the revenue reporting breakdown by domain. For example, cnn.com. It identifies the primary source of requests to the IntentIQ servers, even within nested web pages. | `"currentDomain.com"` |
| params.allowGDPR | Optional | Boolean | This flag determines whether the use of GDPR (General Data Protection Regulation) data is allowed. If set to true, the use of GDPR data will be allowed. The GDPR string can either be provided by the partner or taken from the framework. If set to false, the use of GDPR data will be prohibited. By default, it is set to true. | `true`|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the use of GDPR data will be allowed

it is not clear to me what GDPR data might be, does this mean the contents of the tcf consent string? This is the very thing the Belgian DPA seemed concerned about the potential for misuse of.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This parameter instructs our submodule on whether to consider GDPR or not. In rare cases, when TCF API is present on a US page for US users, it can be ignored. We provide this option to our partners if they prefer to exclude it.

Copy link
Collaborator

@patmmccann patmmccann Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

. In rare cases, when TCF API is present on a US page for US users, it can be ignored.

No you cannot, what gave you that idea? You must follow the publishers instructions as expressed by the TCF API. This is not optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We wanted to eliminate unnecessary delays and give our partners the option to support or not support GDPR when it is not relevant. Regardless, we have made the changes mentioned above. We kindly ask you to review our pull request again.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If gdpr isn't relevant, the CMP will respond that gdpr does not apply. Your partners should fix their CMP if it isn't doing so quickly, not ignore its result in prebid

@bretg
Copy link
Collaborator

bretg commented Feb 11, 2025

This parameter instructs our submodule on whether to consider GDPR or not

Prebid is not going to allow modules that bypass TCF and GPP protections.

Please provide justification for what you're trying to do with this. If we believe there's merit, we will review it with Prebid legal counsel.

@dmytro-po dmytro-po requested a review from patmmccann February 19, 2025 16:50
@patmmccann
Copy link
Collaborator

@dmytro-po i hate to do this to you, but it seems you're a bit out of date since #12783 merged in. Tagging the author @dgirardi in case he has any quick pointers

import AES from 'crypto-js/aes.js';
import Utf8 from 'crypto-js/enc-utf8.js';
import {detectBrowser} from '../libraries/intentIqUtils/detectBrowserUtils.js';
import {appendVrrefAndFui} from '../libraries/intentIqUtils/getRefferer.js';
import {getGppValue} from '../libraries/intentIqUtils/getGppValue.js';
import { getCmpData } from '../libraries/intentIqUtils/getCmpData.js';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with #12783 you should have all this passed to this module without needing to import this, although, your analytics may still need it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We tried passing consentData as the second parameter, but when simulating USP, GPP, and GDPR data, we only received an object with the tcString value inside consentString (There were no USP or GPP values).

That's why we decided to keep the logic in a separate utility using multiHandler().
If you don’t mind.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay no problem, but did you pull in master? because that just merged a couple days ago

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Master pulled

Copy link
Collaborator

@patmmccann patmmccann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

various compliance changes; stop trying to implement string conflict logic. The only string available to you is the one you'll receive as an argument to getId.

firstPartyData.gpp_string_value = cmpData.gpp;
firstPartyData.isOptedOut = false
firstPartyData.cttl = 0
if (!firstPartyData.cttl || Date.now() - firstPartyData.date > firstPartyData.cttl || !isCMPStringTheSame(firstPartyData, cmpData)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why wouldnt they be the same? Stop trying to get two strings and compare them. You must use the string the module gives you.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We compare the values to avoid unnecessarily overwriting localStorage.
And we are using the strings that the module provided to us.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are you writing or accessing a string in local storage?

Stop trying to use / write / read any other consent string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We store the consent string to check if the user's agreements have changed.
Opt-in or opt-out is determined by our server.
If even one character in the consent string is changed, we can no longer be certain whether the user is opted in or opted out, so we make a request to the server to determine it. The server then decides whether to provide the ID or not.
This is the reason why we store the consent string on the device – to know in the next session whether we need to make a request to the server or not.
We are also aware that you store the consent string value as _cmpRepromptHash, but it doesn't work for us because it is not the same as the value returned by multiHandler() (Attached below is a screenshot comparing the strings)
347A5567-A1CF-4BE2-8BB1-3B9E9F4193EC_1_105_c

In other words, we read the consent string every time.

If nothing has changed, we do not make a request to the server and follow the opt-in or opt-out status that the server returned last time.
If anything in the current string value has changed, we update the new value in localStorage and make a request to the server.
This approach helps us avoid unnecessary server requests if the consent string hasn't changed.

@patmmccann
Copy link
Collaborator

Hi, I see your requst for review but you have merge conflicts to sort out

(cmpData.gppString ? '&gpp=' + encodeURIComponent(cmpData.gppString) : '') +
(cmpData.gdprString
? '&gdpr_consent=' + encodeURIComponent(cmpData.gdprString) + '&gdpr=1'
: '&gdpr=0');
Copy link
Collaborator

@patmmccann patmmccann Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a mistake; you cannot assume gdpr does not apply because the string does not exist; you have to look at gdprApplies independently

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see #7775 for more details

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now using gdprApplies. Thank you

Copy link
Collaborator

@patmmccann patmmccann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your module creates large compliance risk and seems to indicate a lack of understanding of the tcf spec. This is rather dangerous. Instead of taking our advice you seem to keep watering down your behavior slightly at each iteration.

firstPartyData.gpp_string_value = cmpData.gpp;
firstPartyData.isOptedOut = false
firstPartyData.cttl = 0
if (!firstPartyData.cttl || Date.now() - firstPartyData.date > firstPartyData.cttl || !isCMPStringTheSame(firstPartyData, cmpData)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are you writing or accessing a string in local storage?

Stop trying to use / write / read any other consent string.

@patmmccann
Copy link
Collaborator

I think the issue here might be confusion around the responsiblities of the submodule and the parent module. The parent module is responsible for detecting consent changes and refreshing the ids if necessary #10286 . If you don't like how that is done, it should be changes to the parent module that you propose, not your own.

@dmytro-po dmytro-po requested a review from patmmccann February 25, 2025 13:38
@patmmccann patmmccann self-assigned this Mar 2, 2025
@patmmccann
Copy link
Collaborator

Thanks for the bearing with us here, merging

@patmmccann patmmccann merged commit 2ad1d23 into prebid:master Mar 2, 2025
4 of 5 checks passed
kiho-shige pushed a commit to DAConsortium/Prebid.js that referenced this pull request Mar 6, 2025
prebid#12738)

* AGT-389: CMP data to module

* AGT-389: Analytics refactoring and changes after PR review

* AGT-389: Parameters description, some edits

* AGT-389: CMP data tests

* AGT-389: Tests fix, export fpd

* AGT-389: Fix uh parameter encoding

* AGT-389: Refactoring, test for new user

* fix linter

* AGT-389: Minor fixes

* AGT-389: Fix getIntentIqConfig method

* AGT-389: Gdpr detected tests, fix gdpr requests addresses

* AGT-389: Removed functionality partner to provide cmp data

* AGT-389: Clear extra comments, fix test

* AGT-389: Removed allow optons for cmpData

* AFT-399: Change getCmpData

* AFT-399: Change comment

* AFT-399: Delete comment

* gdprApplies, refactoring, fix tests

* AGT-389: Refactoring storageUtils

* AGT-389: Change version

---------

Co-authored-by: DimaIntentIQ <dmytro.piskun@intentiq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants