BLOG

COOKIES, CONTROLLERS, AND GDPR: HOW TO BE LEGALLY COMPLIANT

 Gary,
 7 November 2019

In this article we explain the importance of ensuring any cookies and cookies controllers your website use are compliant with GDPR regulations and the latest guidance from the ICO.

Here at Verdant Spark we’ve recently gone through the process of setting up and testing our own cookie controller to ensure GDPR compliance. We thought it would be worth reflecting on and sharing our own experiences.

COOKIES AND CONTROLLERS: THE BASICS

Cookies are small bits of code that can be stored in your browser. They are used for a variety of reasons: so a website can remember you when you return, to track your visits to a website (e.g. Google Analytics) and they can also be used in advertising, if you’ve ever looked at a product online and then seen adverts for it for days afterwards, that’s because of cookies.

cookie controller simply is a piece of code, or functionality, which controls which cookies your browser will store from a website. Your browser will, unless you’ve elected to disable all cookies, simply store whichever cookies are presented to it. The controller can separate out essential from optional cookies and only allow those optional ones which the user has explicitly accepted to be stored instead. It should be noted that even a cookie controller will store a cookie in order to remember what your preferences were for the site.

COOKIES AND THE LAW

Verdant Spark are UK-based so we have to ensure we abide by the EU laws governing the use of cookies. The main legal regulations are the Privacy and Electronic Communications Regulations (PECR) but the use of cookies also falls under the General Data Protection Regulations (GDPR).

The Information Commissioner’s Office (ICO) uphold these regulations in the UK. They are able to take enforcement action and businesses who don’t comply can be fined. In July 2019 the ICO published updated guidance on the use of cookies which many businesses are not aware of.

SO WHAT’S NEW?

You will probably be familiar with the cookie banners that many websites have which say something like “by continuing to use this site you agree to the use of cookies” and you could click the close button to dismiss the banner. Well you should stop seeing them so often as they are now not compliant with the ICO’s interpretation of PECR and GDPR, the ICO have explicitly said that implied consent from a user continuing to use a site is not good enough.

The ICO is clear that for cookies to be used legally, the user must consent to the placing of cookies on their device, and by consent they specify:

the user must take a clear and positive action to give their consent to non-essential cookies – continuing to use your website does not constitute valid consent;

you must clearly inform users about what your cookies are and what they do before they consent to them being set;

if you use any third party cookies, you must clearly and specifically name who the third parties are and explain what they will do with the information;

you cannot use any pre-ticked boxes (or equivalents such as ‘on’ sliders) for non-essential cookies;

you must provide users with controls over any non-essential cookies, and still allow users access to your website if they don’t consent to these cookies; and

you must ensure that any non-essential cookies are not placed on your landing page (and similarly that any non-essential scripts or other technologies do not run until the user has given their consent).

Source: ico.org.uk

There are exemptions to the cookie rules: if the cookies are strictly necessary or if they are for the purpose of communication. There is more detail on the ICO website regarding the definitions of both exceptions but in simple terms to be considered exempt the cookies must be strictly necessary for you to provide the service the user requests (or to comply with other legal regulations) or for the communications exemption, the transmission of a communication must be impossible without the use of a cookie.

So why is this important?

COOKIE COMPLIANCE WILL BE AN INCREASING REGULATORY PRIORITY FOR THE ICO IN THE FUTURE.

Source: ico.org.uk

Yikes! No one would welcome an ICO investigation so what is the solution?

You may be thinking that a cookie wall is a simple solution i.e. prevent users from accessing your website unless they consent to non-essential cookies. Well the ICO have said you must allow users to access your site even if they do not consent to non-essential cookies so a cookie wall won’t be compliant under the guidance.

So what can you use?

A GDPR-COMPLIANT COOKIE CONTROLLER

After a couple of hours searching for current cookie controllers, their implementation, and their legal compliance with the ICO guidelines (as detailed above), we elected to use the Civic Cookie Control v8. If you needed any more persuasion as to its suitability, it is the controller used by the ICO on its own website!

This controller gives a huge amount of options for its use, and even has a WordPress plugin option. We elected not to use the plugin and have implemented the code directly in our child theme. Let’s go through how we did it.

COOKIE CONTROLLER INSTALLATION AND CONFIGURATION

To get started, all you need to add to the header.php of your child theme, just before the </head> tag is:

<!-- Cookie controller-->
<script type="text/javascript" src="https://cc.cdn.civiccomputing.com/8/cookieControl-8.2.1.min.js"></script>
<script type="text/javascript">
    var config = {};
    CookieControl.load(config);
</script>
<!-- End cookie controller-->

We’ll break down the actual config JSON (standard object notation) in the above snippet in the following code blocks. The first part of the config is for the basic appearance, behaviour, and content enabled in the controller itself. To sit in our site comfortably we’re using the LIGHT theme, and have left the default consentCookieExpiry of the controller’s own cookie at 90 days. The apiKey you get from Civic when you register your own site to use the controller.

        apiKey: '11111111111111111111111111111111',
        product: 'COMMUNITY',
        logConsent: false,
        notifyOnce: true,
        initialState: 'OPEN',
        position: 'LEFT',
        theme: 'LIGHT',
        layout: 'SLIDEOUT',
        toggleType: 'slider',
        iabCMP: false,
        closeStyle: 'button',
        consentCookieExpiry: 90,
        subDomains :  true,
        rejectButton: false,
        settingsStyle : 'button',
        encodeCookie : false,
        accessibility: {
            accessKey: 'C',
            highlightFocus: false
        },

Next is a set of properties to control the presentation of text inside the controller:

    text: {
        title: 'This site uses cookies',
        intro: 'Some of these cookies are essential, while others help us to improve your experience by providing insights into how the site is being used.',
        necessaryTitle: 'Necessary Cookies',
        necessaryDescription: 'Necessary cookies enable core functionality. The website cannot function properly without these cookies, and can only be disabled by changing your browser preferences.',
        on: 'On',
        off: 'Off',
        accept: 'Accept',
        settings: 'Cookie Preferences',
        acceptRecommended: 'Accept Recommended Settings',
        closeLabel: 'Close',
        accessibilityAlert: 'This site uses cookies to store information. Press accesskey C to learn more about your options.',
        rejectSettings: 'Reject All',
    },

Then define cookies which are necessary for the running of the site: these are allowed under GDPR and don’t require consent; in our case we’ve included those required for wordpress to operate and maintain a user’s logged in status, the cookie controller itself, and the cookie which is used for our online chat tool.

    necessaryCookies: [
        'wordpress_*',
        'wordpress_logged_in_*',
        'CookieControl',
        'messagesUtk'
    ],

Finally, the core config of cookies, what to do when they’re accepted, and what to do if they’re subsequently rejected. This allows for both explicit opt in and opt out. In our case we load both our Google Analytics scripts and Google Tag Manager when cookies are accepted, as we subsequently use GTM to load other scripts (one of which is the chat tool mentioned already), and which also has some analytics tags. If cookies are subsequently rejected then the onRevoke function deletes all analytics cookies:

    optionalCookies: [
        {
            name: 'analytics',
            label: 'Analytics',
            description: 'Analytical cookies help us to improve our website by collecting and reporting information on its usage. From time to time we also use cookies to help us analyse our advertising on other sites.',
            cookies: [
                '_ga',
                '_gid',
                '_gat'
            ],
            onAccept: function () {
                (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
                new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
                j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
                'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
                })(window,document,'script','dataLayer','GTM-ABCD123');
                (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
                (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
                m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
                })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
                ga('create', 'UA-12345678-1', 'auto');
                ga('send', 'pageview');
            },
            onRevoke: function () {
                window['ga-disable-UA-12345678-1'] = true;
            },
            recommendedState: 'on',
            lawfulBasis: 'consent',
        },
    ],

And wrap the whole thing up with the link to your own cookie policy:

    statement: {
        name: 'Cookie Policy',
        url: 'https://www.verdantspark.co.uk/privacy-policy/'
    },

Here’s the whole controller code:

<!-- Cookie controller-->
<script type="text/javascript" src="https://cc.cdn.civiccomputing.com/8/cookieControl-8.2.1.min.js"></script>
<script type="text/javascript">
    var config = {
        apiKey: '11111111111111111111111111111111',
        product: 'COMMUNITY',
        logConsent: false,
        notifyOnce: true,
        initialState: 'OPEN',
        position: 'LEFT',
        theme: 'LIGHT',
        layout: 'SLIDEOUT',
        toggleType: 'slider',
        iabCMP: false,
        closeStyle: 'button',
        consentCookieExpiry: 90,
        subDomains :  true,
        rejectButton: false,
        settingsStyle : 'button',
        encodeCookie : false,
        accessibility: {
            accessKey: 'C',
            highlightFocus: false
        },
        text: {
            title: 'This site uses cookies',
            intro: 'Some of these cookies are essential, while others help us to improve your experience by providing insights into how the site is being used.',
            necessaryTitle: 'Necessary Cookies',
            necessaryDescription: 'Necessary cookies enable core functionality. The website cannot function properly without these cookies, and can only be disabled by changing your browser preferences.',
            on: 'On',
            off: 'Off',
            accept: 'Accept',
            settings: 'Cookie Preferences',
            acceptRecommended: 'Accept Recommended Settings',
            closeLabel: 'Close',
            accessibilityAlert: 'This site uses cookies to store information. Press accesskey C to learn more about your options.',
            rejectSettings: 'Reject All',
        },
        necessaryCookies: [
            'wordpress_*',
            'wordpress_logged_in_*',
            'CookieControl',
            'messagesUtk'
        ],
        optionalCookies: [
            {
                name: 'analytics',
                label: 'Analytics',
                description: 'Analytical cookies help us to improve our website by collecting and reporting information on its usage. From time to time we also use cookies to help us analyse our advertising on other sites.',
                cookies: [
                    '_ga',
                    '_gid',
                    '_gat'
                ],
                onAccept: function () {
                    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
                    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
                    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
                    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
                    })(window,document,'script','dataLayer','GTM-ABCD123');
                    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
                    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
                    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
                    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
                    ga('create', 'UA-12345678-1', 'auto');
                    ga('send', 'pageview');
                },
                onRevoke: function () {
                    window['ga-disable-UA-12345678-1'] = true;
                },
                recommendedState: 'on',
                lawfulBasis: 'consent',
            },
        ],
        statement: {
            name: 'Cookie Policy',
            url: 'https://www.verdantspark.co.uk/privacy-policy/'
        },
    };
    CookieControl.load(config);
</script>
<!-- End cookie controller-->

WORDPRESS IMPLEMENTATION

As already mentioned, this can be done using a plugin, but we’ve elected to inject the code directly into the header using our child theme. Our theme uses two different header files: header.php and header-homepage.php. Never wanting to maintain code in two places, we added the cookie code into a separately maintainable file and just included it in the two header files as follows:

  <?php include get_stylesheet_directory() . '/cookie.php'; ?>

Where get_stylesheet_directory() returns the reference to the directory the child theme is served from (see get_stylesheet_directory).

CONCLUSION

Civic Cookie Controller v8 offers a very straightforward implementation which can be used in any website, so we’re a fan here; it can help you to ensure that your cookies are being handled correctly and in line with ICO guidance to stay GDPR compliant.

If you need assistance with cookies, GDPR, and how to ensure your website is operating as it should don’t hesitate to contact us.

0 Comments