1.1.0 • Published 5 years ago

user-consent v1.1.0

Weekly downloads
1
License
Apache-2.0
Repository
-
Last release
5 years ago

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 the countryCode 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.