user-consent v1.1.0
User-Consent
A brand agnostic approach to CCPA and GDPR user consent using OneTrust.
Usage
Include code in your application (as the first script in the <head>
block).
Adding the Library
<head>
<!-- place this at or near the top -->
<script src="path/to/this-script.js" type="text/javascript"></script>
<script>
(function initalizeUserConsent(win) {
win.WM.UserConsent.init({
cookieDomain: '.your-brand.com',
domId: 'ONETRUST-GUID-HERE',
src: '//domain.com/path/to/one-trust-script.js'
});
})(window);
</script>
<!-- other head tags -->
</head>
Or by pre-defining the config, which will allow the code to self-initialize.
<head>
<!-- place this at or near the top -->
<script>
window.WM = window.WM || {};
window.WM.UserConsentConfig = {
cookieDomain: '.your-brand.com',
domId: 'ONETRUST-GUID-HERE',
src: '//domain.com/path/to/one-trust-script.js'
};
</script>
<script src="path/to/this-script.js" type="text/javascript"></script>
<!-- other head tags -->
</head>
Both methods are equavalent to the code, so just use whichever works best for your situation.
The required configuration values are:
- cookieDomain: The domain of the Optanon cookies you are using. For example:
".cnn.com"
(note the leading.
). - domId: The GUID provided by OneTrust for your domain.
- src: The URL for the OneTrust script to use.
Some other important configuration values are:
- ccCookie: The name of the session cookie that will contain the country-code set via Geo-IP from the CDN. As several sites--including CNN--use
countryCode
, this is the default. Note that either passing in the GeoIP-derived current country code directly (via thecountryCode
option below) or getting it from a session cookie on the response is required for User-Consent to work properly. The session cookie method is easily added to both Akamai and Fastly CDN configurations. - countryCode: The 2-letter GeoIP-derived country code to use. Only use this if you are acquiring this value directly through your own means and don't wish to use the "session cookie" method via the
ccCookie
option (above). - confirmCookie: The name of the "confirmation" cookie used by OneTrust. This defaults to "OptanonAlertBoxClosed".
- consentCookie: The name of the "consent" cookie used by OneTrust. This defaults to "OptanonConsent".
- controlCookie: The name of the "control" cookie used by User-Consent to help manage OneTrust cookies. This defaults to "OptanonControl".
Wrap Scripts
The addScript
Method
Replace scripts implemented like this:
<script src="//domain.com/path/to/script.js" onload="myLoadEventHandler()"></script>
With something like this:
<script>
window.WM.addScript({
async: true,
onload: function (e) {
myLoadEventHandler();
},
src: '//domain.com/path/to/script.js'
}, ['perf-general']);
})(window, document);
</script>
Any script tag properties can be passed in the object for the first parameter,
just as you would use with a script tag created via.
document.createElement('script')
.
The second parameter should be an array of strings specifying the list of the consent categories required for this script to be invoked. If more than one are included, all must have consent.
There is an optional third parameter, which (if specified) is the DOM node on the page to append the script to. This is not normally needed.
Note that the function returns boolean true
if consent exists and the script
tag was added or boolean false
if consent was not granted.
The addScriptElement
Method
Very similar to addScript
above, the addScriptElement
call will conditionally
add a script tag based on consent. The difference is instead of the first parameter
being an object consisting of script properties, it is a script element created by
your code but not yet added to the DOM.
For example, if you have something like this in your code:
var scpt = doc.getElementsByTagName('script')[0],
elem = doc.createElement('script');
elem.id = 'quantScript';
elem.async = true;
elem.type = 'text/javascript';
elem.src = doc.location.protocol === 'https:' ? config.runtime.quantcast.sslSrc : config.runtime.quantcast.src;
scpt.parentNode.appendChild(elem);
You would replace that with this:
var scpt = doc.getElementsByTagName('script')[0],
elem = doc.createElement('script');
elem.id = 'quantScript';
elem.async = true;
elem.type = 'text/javascript';
elem.src = doc.location.protocol === 'https:' ? config.runtime.quantcast.sslSrc : config.runtime.quantcast.src;
window.WM.UserConsent.addScriptElement(elem, config.runtime.quantcast.ucStates, scpt.parentNode);
Here we see that the first parameter is simply the script element created within
the code, but the instead of adding it directly to the DOM, we use addScriptElement
.
Note that the second parameter and optional third parameter are identical to addScript
.
Also note that the function returns true
or false
, similar to addScript
.
Wrapping Inline Code with inUserConsentState
If you simple need to make code conditional on a consent state, you can also do
that by using inUserConsentState
with a conditional. For example, let's say you have
a block of code like the following:
doThingA();
doGeneralPerfThing();
doThingB();
if (doSocialMediaIdentityThing() === 'success') {
doThingC();
} else {
doThingD();
}
You could re-write that to use consent with logic like the following:
doThingA();
if (window.WM.UserConsent.inUserConsentState(['perf-general'])) {
doGeneralPerfThing();
}
doThingB();
if (window.WM.UserConsent.inUserConsentState(['social-vendor'])) {
if (doSocialMediaIdentityThing() === 'success') {
doThingC();
} else {
doThingD();
}
} else {
doThingD();
}
A Note About Consent
In all the examples above, consent is specified as an array of strings.
Consent must exist for ALL the consent types specified for consent to be
successful. If the consent array is empty ([]
), it will always be true.
Note that a special consent string exists called "iab"
. If this string
appears in the consent array, and IAB is used in the current region
(notably GDPR), then consent will be granted, as it is assumed that the
code being invoked will correctly be using CMP to manage consent internally
on it's own in an IAB-compliant way.
Managing Categorization and Scripts
Ideally, scripts should be managed via an upstream configuration file - similar to:
// global config for application
{
"someThirdParty": {
"src": "//domain.com/path/to/script.js",
"ucStates": ["perf-vendor"]
}
}
<script>
window.WM.UserConsent.addScript({ src: Config.someThirdParty.src }, Config.someThirdParty.ucStates);
</script>
ES6
If using ES6-style import
, replace something like this:
<script>
import 'usabilla';
// Do stuff with usabilla
</script>
With something like:
<script>
if (window.WM.UserConsent.inUserConsentState(['perf-general'])) {
import 'usabilla';
// Do stuff with usabilla
}
</script>
Legacy Approaches
While we don't recommend it, as it makes future category changes difficult to migrate and makes some script behavior a bit unpredictable, you can also continue to use the OneTrust method with text/plain and optanon category class:
<script type="text/plain" class="optanon-category-pf" src="//domain.com/path/to/script.js"></script>
If you previously implemented OneTrust within your application for GDPR compliance, you will need to remove that script as the bootstrap
script will include it for you.
Debugging
Passing a query parameter of wmuc_debug=1
in the query string of your page URL will
enable "debug" mode. This will output extra details to the Javascript console which may
assist you in determining exactly what was or wasn't loaded and why.
Reference
User-Consent makes the following functions available...
- addScript(options, consents, parent) - Creates and adds a script tag if consent has been granted. Specify the script tag details (src, async, onload, type, id, class, etc.) in the options object, specify the desired consent string(s) in the consents array, and use the optional parent value to specify an HTTP Element to use as the parent for the script tag.
- addScriptElement(element, consents, parent) - Identical to addScript (above), but used to add a script tag which you have already created and not yet added to the DOM.
- forceReconsent() - Use to remove the user's current consent choices and force them to reconsent. Note: Very dangerous, use sparingly and with caution. Should probably ONLY be used in a "regionChangeAction" function when moving from CCPA or Global to GDPR.
- getConsentState() - Returns the current consent state object.
- getConsentTime() - Returns a Date value reflecting the date/time the user last made a consent change.
- getConsentVersion() - Returns the current OneTrust consent version (probably 5.7.0 or higher).
- getLinkAction() - Returns a function suitable for calling in response to the user clicking on a link to request a consent change. By default, this function will open the OneTrust consent panel.
- getLinkTitle() - Returns the appropriate text string to use for a link to request consent changes in the current region.
- getRegion() - Returns the current region, one of "ccpa", "gdpr", or "global".
- getVersion() - Returns the current version of the User-Consent code.
- init(config) - Use to initialize UserConsent if not using
window.WM.UserConsentConfig
(see "Adding the library" above). - inUserConsentState(consents) - Returns a boolean reflecting whether or not the current consent state permits the consent(s) specified in the consents array. Extremely useful for determining consent programmatically.
- isInRegion(region) - Given region set to "ccpa", "gdpr", or "global", will return a boolean
true
if the current user's region is a match. - isOptanonLoaded() - Returns a boolean reflecting the current loaded state of OneTrust scripts.
- isReady() - Returns a boolean
true
once the User-Consent is ready to process consent. Note that this does NOT imply that OneTrust has been loaded! - usingIAB() - Returns a boolean
true
if the user is in a region with IAB enabled.
5 years ago