-
- Note
- Purpose
- Example
- Usage Example
- Consent Classes: Mapping consent to Cxense products
- Requiring The Consent Feature To Be Used
- What does the consent feature affect?
- Setting Consent
- Checking For Consent
- Not Covered in the Consent API
- Anonymous Page Views
- Behaviour of getUserSegmentIds()
- Clearing Cookies/Local Storage/IDs
- API Changelog
-
- Note
- Purpose
- Example
- Usage Example
- Consent Classes: Mapping consent to Cxense products
- Requiring The Consent Feature To Be Used
- What does the consent feature affect?
- Setting Consent
- Checking For Consent
- Not Covered in the Consent API
- Anonymous Page Views
- Behaviour of getUserSegmentIds()
- Clearing Cookies/Local Storage/IDs
- API Changelog
Note
This document will evolve as new features and requirements come up. Updates will be noted in the "API Changelog" section.
Purpose
Cxense customers who provide services to EU/EEA users must abide by the GDPR regulations that will be in effect on May 25, 2018. For those customers, Cxense is providing functionality to ensure compliance.
Cxense provides an API for customers to tune the use of cx.js after collecting consent. The API is not a solution for collecting consent itself. Instead, it is a method to activate or deactivate Cxense features based on how consent is recorded.
Example
You can find an API usage example at http://dev1.cxpublic.com/cxjs/consent.html. The example demonstrates the behaviour of the consent API in various states.
Usage Example
<script type="text/javascript">
var cX = cX || { options: { consent: true } };
cX.callQueue = cX.callQueue || [];
cX.callQueue.push(['requireConsent']);
cX.callQueue.push(['setSiteId', '12345']);
cX.callQueue.push(['sendPageViewEvent']);
cX.callQueue.push(['invoke', displayConsent]);
function displayConsent() {
if (!cX.hasConsent('pv')) { // can also check consent on 'segment', 'recs' or 'ad'
// function to trigger UI function to ask for consent
showConsentUI();
}
}
function showConsentUI() {
if (confirm('Will you allow us to send analytics data?')) {
cX.callQueue.push(['setConsent', {pv: true}]); // or `cX.setConsent({ pv: true });` if done synchronously.
}
}
</script>
<script type="text/javascript">
(function (d, s, e, t) {
e = d.createElement(s);
e.type = 'text/java' + s;
e.async = 'async';
e.src = 'http' + ('https:' === location.protocol ? 's://s' : '://') + 'cdn.cxense.com/cx.js';
t = d.getElementsByTagName(s)[0];
t.parentNode.insertBefore(e, t);
})(document, 'script');
</script>
Consent Classes: Mapping consent to Cxense products
As a customer and data controller, the purpose of your data collection is specific to your needs. For example, you might collect page view events to analyze the performance of articles, or place end-users into segments to personalize advertising to them. The purposes for data use must be outlined to the end-user by the data controller and this information must be obtained and managed by each customer. However, what is consented to by the end-user must be translated for cx.js to act in an appropriate way.
When using the cx.js consent API, the script is told what to collect and what not to collect based on your purposes. For the API, we are describing certain data collection and data processing activities in the form of criteria called a "consent class".
There are currently four consent classes. You turn on and off these classes based on the context of what is specifically allowed.
-
pv: Stands for "page views". Specifically, this covers all event collection activities: page view events, DMP events and the delivery of personal data through them. If an end-user rejects having their usage data being collected for your specific purposes, then this should either not be set or this should be set tofalse. -
segment: Refers to activating segment membership on the data subject. If an end-user rejects being added to segments for your specific use-cases, then this should not be set or should be set tofalse. -
recs: Refers to content recommendations or anything that involves content widgets. If an end-user rejectsrecs, they are specifically opting out to personalized recommendations. It is still possible to insert content widgets on your pages, but they will only return non-personalized recommendations (for example, articles that are trending.) -
ad: Refers to personal data processing for advertising. Advertising is specifically allowed, however, if an end-user rejects having their personal data being processed for any reason, such as for personalized advertising or retargeting, then this should either not be set or should be set tofalse.
Be aware that if page view collection is rejected, the other consent classes will automatically be rejected, except for non-personalized content recommendations. This is because page view collection is a critical step before any other type of activity can be reasonably recorded and be useful.
The key point here is that when the consent feature is turned on, besides requesting content widgets, nothing else will occur until the features are explicitly turned on.
Device and geolocation data
Two extra consent classes are available to address what type of data can and can't be collected. While a user can still allow tracking and other features, they might wish to limit the use of data such as what device they are using or where they are located during tracking.
These two consent classes are a part of the second version of the consent API and should be activated on setup: g
var cX = cX || { options: { consent: true, consentVersion: 2 }}
// or
cX.callQueue.push(['requireConsent', 2]);
If you supply device or geo without first configuring cX that it should use the correct consent version, these new consent classes will be ignored.
These consent classes similar to other ones:
cX.callQueue.push(['setConsent', { pv: true, device: true, geo: true }]);
The two new consent classes are:
-
device: This covers any data, such as user-agent or browser information, that can be used to identify what device the user is using. If consent is not given, certain activities that require device information will be limited, since the data will not be present. -
geo: This covers looking up geolocation data on end-users. Practically, this covers geolocation via IP lookups to some precision. It also will reject the use of latitude and longitude parameters in page view requests.
If these consents are not set, the data will be scrubbed from the respective events and widget calls to comply with the end-user's request.
Practically, by removing this data, it could mean that certain segments, content and CCE widgets, etc. might decline in quality. For example, if a large amount of some site group audience declines on the device consent, segments that rely on device data will match fewer users.
Requiring The Consent Feature To Be Used
The consent feature in cx.js is opt-in; you must turn it on for it to function. To activate the consent feature, you must add an option when declaring the cX variable:
var cX = cX || { options: { consent: true } }
Turning on consent will affect the use of cx.js. With the functionality active, events will not be delivered and segment membership requests will be deactivated. It can still insert content widgets, but on a limited basis (no content widget personalization.)
There is another way for consent to be activated. The cX.requireConsent() function can be utilized:
-
Async:
cX.callQueue.push(['requireConsent']) -
Sync:
cX.requireConsent()
However, setting the consent option to true is preferable. Load order of JavaScript scripts in a browser can be non-deterministic. Also, if the asynchronous method is used, the order of the call queue cannot be necessarily determined. Thus, turning on consent might be too late, allowing events to be delivered before the consent feature is turned on. However, the option is available when the order of call queue is controlled and for purposes of clarity.
What does the consent feature affect?
The functions listed below will not execute by default when consent is required and the related consent class has not been turned on (both synchronous and asynchronous methods):
-
sendPageViewEvent()whenpvis not set or is set tofalse. -
sendEvent()whenpvis not set or is set tofalse. -
getUserSegmentIds()whensegmentis not set or is set tofalse. -
insertAdSpace()whenadis not set or is set tofalse. -
insertMultipleAdSpaces()whenadis not set or is set tofalse. -
sync()whenadis not set or is set tofalse. -
addExternalId()whenpvis not set or is set tofalse.
Consent must be explicitly given before these methods can execute.
When the functions are called asynchronously, you have the option to run them when a consent class is turned on, which will be discussed in the next section.
Setting Consent
Setting user consent is done through this method:
-
Async:
cX.callQueue.push(['setConsent', <consent object>]); -
Sync:
cX.setConsent(<consent object>);
Here are examples of setting consent (using the synchronous method in the examples):
-
cX.setConsent({ pv: true, segment: true });: This tells us that page views can be collected and the user can be part of segments. -
cX.setConsent({ pv: true });: This tells us that the user only consents to having page view and events to be collected. -
cX.setConsent({ pv: true, segment: true, ad: true, recs: true });: The user agrees to everything. -
cX.setConsent({ pv: false, segment: false, ad: false, recs: false });: The user does not consent to anything.
Below are similar examples using the asynchronous method:
-
cX.callQueue.push(['setConsent', { pv: true, segment: true }]);: This tells us that page views can be collected and the user can be part of segments. -
cX.callQueue.push(['setConsent', { pv: true }]);: This tells us that the user only consents to having page view and events to be collected. -
cX.callQueue.push(['setConsent', { pv: true, segment: true, ad: true, recs: true }]);: The user agrees to everything. -
cX.callQueue.push(['setConsent', { pv: false, segment: false, ad: false, recs: false }]);: The user does not consent to anything.
The information will be stored in a local storage key called cX_cons in the form of a query string. Using the above examples, they will be stored as:
-
pv=true&segment=true -
pv=true -
pv=true&segment=true&ad=true&recs=true -
pv=false&segment=false&ad=false&recs=false
This information will also be delivered in page view events. Using the above examples, the page view event (in the rep.gif call) will contain this URL parameter:
-
con=y,pv,segment -
con=y,pv -
con=y,pv,segment,ad,recs -
con=y
The consent information is stored to ensure that our services reject event data for non-consenting users and deliver correct content based on the consent given.
When con=y by itself is reserved for telling the event receiver that the page view is an anonymous page view if no other consents are added. con=y,pv means that the user has given consent to full page view tracking.
Re-running the call queue on consent
When setting consent asynchronously, you can re-run the queue of methods that were denied execution by setting the runCallQueue flag in the function:
cX.setConsent(<consent object>, { runCallQueue: true });
When consent is sent in this scenario, the functions denied execution will be executed.
Note that this is an option for simple scenarios and might not work well on pages. For example, pages relying on infinite scroll to show more articles might not work well with running the call queue automatically. In these cases, it is best to develop another strategy on executing the data delivery methods after consent is provided.
Checking For Consent
You are able to check for consent for a particular consent class (pv, segment, recs, ad) with hasConsent(<consent class>):
Sync: cX.hasConsent('pv'); cX.hasConsent('segment'); cX.hasConsent('recs'); cX.hasConsent('ad');
Note: There is currently no reliable method to check for consent asynchronously.
You can get all consents in an object with:
cX.allUserConsents()
If one or many consent classes are not set in the output of allUserConsents(), it can be assumed that that class is set to non-consenting. For example, if we get this result back:
{ pv: true }
We can assume that segment membership, personal recommendations and personal ad targeting is not consented to.
Not Covered in the Consent API
setCustomParameters() is executed even if consent is turned off. Currently, this only affects page views, but since custom parameters could either be or not be personal data, it is left up to the discretion of the developer to properly remove any custom parameters with personal data if it applies. For example, if there is ad-like personal data that you wish to send through a page view request, you can check like this:
Sync:
if (cX.hasConsent('ad')) {
cX.setCustomParameters({ userIdForAd: userId });
}
cX.sendPageViewEvent();
Async:
cX.callQueue.push(['invoke', function () {
if (cX.hasConsent('ad')) {
cX.setCustomParameters({ userIdForAd: userId });
}
}]);
cX.callQueue.push(['sendPageViewEvent]);
Anonymous Page Views
When the consent feature is turned on and pv is set to false, an anonymous page view is delivered. These requests do not send identifying information. If there are cookies set via cx.js, these cookies will be ignored by the backend. See more information about clearing up cookies and identifiers in the section "Clearing Cookies/Local Storage/IDs".
The page view request will send three data points, all of which are not personally identifying.
|
Query string parameter |
Purpose |
Default |
|---|---|---|
|
|
Say that consent was turned on. |
|
|
|
The URL ( |
- |
|
|
The site ID |
- |
Example Request URL:
https://comcluster.cxense.com/Repo/rep.gif?con=y&loc=https%3A%2F%2Fwww.cxense.com&sid=12345
Details on anonymous page view collection
Page view events are collected and stored anonymously. Since the events are anonymous, these events cannot be used for user-tracking features, like unique users counting and session tracking.
Behaviour of getUserSegmentIds()
For purposes of backwards compatibility, getUserSegmentIds() will return a blank array if the consent feature is turned on and the consent class segment is set to false.
It is recommended to consider that when a blank array returns from getUserSegmentIds() or is passed into a callback that it could either be that the segment class was not turned on or that the user did not match any segment.
When the consent mode is turned on and the segment value is set to true, then getUserSegmentIds() will function normally.
Clearing Cookies/Local Storage/IDs
It is advisable to remove anything that was created by cx.js, in the form of cookies and local storage, after "sessions" are finished (e.g. when a user logs out.) This is particularly important if data subjects are using public computers and wish to have their sessions completely cleared and unidentifiable to the next data subject.
It is possible to implement this with the cX.clearIds() function. In the below example, we will describe a hypothetical "log out" scenario in code and how it would be executed in synchronous and asynchronous fashions.
Sync:
if (user.isLoggedOut()) {
cX.clearIds();
}
Async:
if (user.isLoggedOut()) {
cX.callQueue.push(['clearIds']);
}
// Another example:
cX.callQueue.push(['invoke', function () {
if (user.isLoggedOut()) {
cX.clearIds();
}
}]);
API Changelog
-
2-5-2018: Exposed
getExternalId()andsync()to consent handling. -
7-5-2018:
clearIds()was added to the consent API. -
9-5-2018: Exclusions on
setCustomParameters(). -
19-6-2018:
getUserSegmentIds()should return a blank array if consent mode is on and segments are not consented to. -
12-20-2020: Adding information on
deviceandgeoflags.