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

gdpr consentManagement module docs #645

Merged
merged 10 commits into from
Apr 16, 2018
1 change: 1 addition & 0 deletions dev-docs/bidders/appnexus.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ biddercode: appnexus
biddercode_longer_than_12: false
hide: true
prebid_1_0_supported : true
gdpr_supported: true
---

**Table of Contents**
Expand Down
1 change: 1 addition & 0 deletions dev-docs/bidders/prebidServer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ biddercode: prebidServer
biddercode_longer_than_12: true
hide: true
prebid_1_0_supported : true
gdpr_supported: true
---

### Sign up
Expand Down
178 changes: 178 additions & 0 deletions dev-docs/modules/consentManagement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
---
layout: page
title: Module - GDPR ConsentManagement
Copy link
Member

Choose a reason for hiding this comment

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

@mjacobsonny
What do you want to call the module? GDPR Consent Management or just "Consent Management"

description: User ID persisted in first party domain
Copy link
Member

Choose a reason for hiding this comment

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

Not sure this is accurate. Maybe change to something like "Add on module to consume and distribute consent information to bidder adapters"

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 was a hold-over from a page I copied from to start things off that I missed. Will update it.

top_nav_section: dev_docs
nav_section: modules
module_code : consentManagement
display_name : GDPR ConsentManagement
---

<div class="bs-docs-section" markdown="1">

## PENDING RELEASE
This module is still considered under development, but the core logic and integration steps documented here will very likely remain as described.

# GDPR ConsentManagement Module
{:.no_toc}

Designed to support the EU General Data Protection Regulation ([GDPR](https://www.eugdpr.org/)), this module works with supported Consent Management Platforms (CMPs) to fetch an encoded string representing the user's consent choices and make it available for adapters to consume and process.

This module will perform its tasks with the CMP prior to the auction starting. A rough synopsis of this interaction process would be:

1. Fetch the user's encoded consent string from the CMP.
2. If this request doesn't return a string, we assume this is a new-user and is undergoing the consent process. We will wait for a signal from the CMP that the consent has finished and perform the lookup again.
3. With a valid consent string, we will incorporate this data into the auction objects (for adapters to collect) and then allow the auction to proceed.

There are timeout settings in place in the module to permit this interaction with the CMP a specified length of time to operate before it's unacceptable or assumed an issue has occurred.

When either this timeout occurs or if an error from the CMP is thrown, one of two options are taken; either:

1. The auction is canceled outright.
2. The auction proceeds without the user's consent information.

Though these options are mutually exclusive, they are configurable by the publisher via the site's implementation of the prebid code (see further below for details) so that they can be used in the proper scenarios for that site/audience.


## Page integration

To utilize this module, a separate CMP needs to be implemented onto the site to interact with the user and obtain their consent choices.

The actual implementation details of this CMP are not covered by this page; any questions on that implemenation should be referred to the CMP in question. However, we would recommend to have the CMP's code located before the prebid code in the head of the page, in order to ensure their framework is implemented before the prebid code starts to execute.

The module currently supports the following CMPs:
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we discussed that this should be worded to include any CMP that conforms to the IAB standard at https://info.quantcast.com/rs/516-DGM-318/images/Framework%20CMP%20JS%20API%20Specification.pdf

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will make this update; would that be the ideal link to reference? I was looking around and thinking this may be better to use for a long-term reference:
https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good.


* AppNexus (appnexus)

Once the CMP is implemented, simply include the module in your build and add a consentManagement object in the setConfig() call. Adapters that support this feature will be able to retrieve the consent information and incorporate it in their requests.

{: .table .table-bordered .table-striped }
| Param | Type | Description | Example |
| --- | --- | --- | --- |
| cmp | `string` | The ID for the CMP in use on the page. Default is `'appnexus'` | `'appnexus'` |
Copy link
Contributor

Choose a reason for hiding this comment

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

Related to the previous comment, believe this would be more like cmpApi, with the value being 'iab'.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll make this change (note - there will be subsequent updates in the main PR as a result).

| consentRequired | `boolean` | An override type setting to indicate if GDPR consent is required or not. See note in regards to default. | `true` or `false` |
| timeout | `integer` | Length of time (in milliseconds) to allow the CMP to perform its tasks before aborting the process. Default is `10000` | `10000` |
| allowAuctionWithoutConsent | `boolean` | A setting to determine what will happen when obtaining consent information from the CMP fails; either allow the auction to proceed (**true**) or cancel the auction (**false**). Default is `true` | `true` or `false` |

* Note - There are some technologies to determine if a given request is in scope of GDPR or not. While this technology is not part of the consentManagement module (nor prebid), some adapters may have this technology available. If they do, they have the opportunity to set their own default value for the `consentRequired` field. If you are using a GDPR supported adapter that has this capability, simply do **not** include this field in your config to let the corresponding adapter(s) set their value.
Copy link
Contributor

Choose a reason for hiding this comment

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

It's not the adapter that has the ability to determine GDPR scope... probably the SSP/exchange/bidder. Would suggest wording more like this:

Note - Some SSPs can determine whether a given request is in GDPR scope or not. If the page specifies consentRequired, it will override any dynamic determination and force the bidders to use this override value -- i.e. tell the SSP whether the consent string must be enforced for this user. Each bidder adapter supporting GDPR will default to the proper setting for the backend SSP, so it's not recommended to set this value unless override is what's desired.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the feedback, I'll make the changes as recommended.


Example: AppNexus CMP using the custom timeout and cancel auction options with the consentRequired field not defined.

{% highlight js %}
var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];
pbjs.que.push(function() {
pbjs.setConfig({
consentManagement: {
cmp: 'appnexus',
timeout: 8000,
allowAuctionWithoutConsent: false
}
});
pbjs.addAdUnits(adUnits);
});
{% endhighlight %}

## Build the package

#### Step 1: Bundle the module code

Follow the basic build instructions on the Github repo's main README. To include the module, an additional option must be added to the the gulp build command:

{% highlight bash %}
gulp build --modules=consentManagement,bidAdapter1,bidAdapter2
{% endhighlight %}

#### Step 2: Publish the package(s) to the CDN

After testing, get your javascript file(s) out to your Content Delivery Network (CDN) as normal.

Note that there are more dynamic ways of combining these components for publishers or integrators ready to build a more advanced infrastructure.

## Adapter integration

To find the GDPR consent information to pass along to your system, adapters should look for the `bidderRequest.gdprConsent` field in their buildRequests() method.
Below is a sample of how the data is structured in the `bidderRequest` object:

{% highlight js %}
{
"bidderCode": "appnexus",
"auctionId": "e3a336ad-2761-4a1c-b421-ecc7c5294a34",
"bidderRequestId": "14c4ede8c693f",
"bids": [
{
"bidder": "appnexus",
"params": {
"placementId": "10433394"
},
"adUnitCode": "ad-unit-code",
"transactionId": "0e8c6732-0999-4ca8-b44f-8fe514f53cc3",
"sizes": [[300, 250], [300, 600]],
"bidId": "2e6fe30b22b4fc",
"bidderRequestId": "14c4ede8c693f",
"auctionId": "e3a336ad-2761-4a1c-b421-ecc7c5294a34"
}
],
"auctionStart": 1520001292880,
"timeout": 3000,
"gdprConsent": {
"consentString": "BOJ/P2HOJ/P2HABABMAAAAAZ+A==",
"consentRequired": true
},
"start": 1520001292884,
"doneCbCallCount": 0
}
{% endhighlight %}

### Notes about data fields

#### *consentString*
This field contains the user's choices on consent, represented as an encoded string value. In certain scenarios, this field may come to you with an `undefined` value; normally this happens when there was an error during the CMP interaction and the publisher had the config option `allowAuctionWithoutConsent` set to `true`. If you wish to set your own value for this scenario rather than pass along `undefined` to your system, you can check for the `undefined` value in the field and replace it accordingly. The code sample provided in the *consentRequried* section below provides a possible approach to perform this type of check/replacement.

#### *consentRequired*
As described earlier in this page - if the publisher didn't set their own value for `consentRequired` in the prebid `setConfig` code, each adapter has the opportunity to set their own value for this field.
There are two general approaches that can be taken by the adapter to populate this field:

- Set a hardcoded default value.
- Using their own system, derive if consent is required for the end-user and set the value accordingly.

Using the former option, below is an example of how the integration could look:

{% highlight js %}
...
buildRequests: function (bidRequests, bidderRequest) {
...
if (bidderRequest && bidderRequest.gdprConsent) {
adapterRequest.gdpr_consent = {
consent_string: bidderRequest.gdprConsent.consentString,
consent_required: (typeof bidderRequest.gdprConsent.consentRequired === 'boolean') ? bidderRequest.gdprConsent.consentRequired : true
Copy link
Member

Choose a reason for hiding this comment

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

can you add a comment on this line describing the logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added a comment in the code

}
}
...
}
...
{% endhighlight %}

The implementation of the latter option is up to the adapter, but the general premise should be the same. You would check to see if the `bidderRequest.gdprConsent.consentRequired` field is undefined and if so, set the derived value from your independent system. Otherwise, you would use the publisher's value that was set in the `bidderRequest.gdprConsent.consentRequired` field.

If neither option are taken, then there is a chance this field's value will be undefined on certain requests. As long as that acceptable, this could be a potential third option.

{% assign bidder_pages = site.pages | where: "layout", "bidder" %}

<script>
$(function(){
$('.adapters .col-md-4').hide();
$('.gdpr_supported').show();
});
</script>

Below is a list of Adapters that support GDPR:
<div class="adapters">
{% for page in bidder_pages %}
<div class="col-md-4{% if page.gdpr_supported %} gdpr_supported{% endif %}">
{{ page.title }}
</div>
{% endfor %}
</div>

</div>
1 change: 1 addition & 0 deletions dev-docs/modules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ If you are looking for bidder adapter parameters, see [Bidders' Params]({{site.b
| [**Server-to-Server Testing**]({{site.baseurl}}/dev-docs/modules/s2sTesting.html) | Adds A/B test support for easing into server-side header bidding. |
| [**DFP Video**]({{site.baseurl}}/dev-docs/modules/dfp_video.html) | Required for serving instream video through DFP. |
| [**Publisher Common ID**]({{site.baseurl}}/dev-docs/modules/pubCommonId.html) | Adds a persisted user ID in the publisher's domain. |
| [**GDPR ConsentManagement**]({{site.baseurl}}/dev-docs/modules/consentManagement.html) | Facilitates collecting/passing consent information in support of the EU GDPR. |

## Further Reading

Expand Down