Change log

  • 2022-08-07 : Fixed article and added an additional setting when using GTM.
  • 2022-07-10 : Page published

Introduction

Consent Management Platforms (CMPs) are gaining attention as a tool to explain to users what data a website or application collects and how it is used, and to obtain their consent.

There are several free tools and paid cloud services, but this article introduces the free JavaScript plugin Cookie Consent and how to implement it.

We will also introduce how to implement it for multilingual support and for using Google Analytics with Google Tag Manager.

What is Cookie Consent?

Cookie Consent is a free, GDPR-compliant JavaScript plugin.

You can download it below.

orestbida/cookieconsent: Simple cross-browser cookie-consent plugin written in vanilla js

Outline for settings

The following is an outline of the procedure.

  1. load the plugin's JavaScript
  2. load the CSS for the plugin
  3. write the configuration code of the plugin
  4. edit the <script> tag of the analyzer or such tools you are using

Note if you are using Google Tag Manager

If you are using Google Tag Manager (GTM), you must fire Cookie Consent before the GTM loading code.

Load the plugin's JavaScript and CSS

Load CSS and JS as follows.

The location of the JS can be in the body tag or in the head tag.

<html>
    <head>
        <!-- head content -->
        <!-- Deferred CSS loading (recommended) -->
        <link rel="stylesheet" href="<path-to-cookieconsent.css>" media="print" onload="this.media='all'">
    </head>
    <body>
        <!-- body content -->
        <script defer src="<path-to-cookieconsent.js>"></script>
    </body>
</html>

CSS and JS can also be loaded from CDN.

# CDN links
https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@v2.8.2/dist/cookieconsent.js
https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@v2.8.2/dist/cookieconsent.css

When using GTM, the order is as follows. GTM's script tag attributes are explained later in this article.

<!-- Plug-in JS -->
<script defer src="../../src/cookieconsent.js"></script>

<!-- Plugin Settings JS -->
<script defer src="cookieconsent-init.js"></script>

<!-- GTM Tag -->
<script type="text/plain" data-cookiecategory="analytics">
    // Google Tag Manager (configured with GA internally)
    (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-XXXXXXX');
</script>

Write the configuration code for the plugin - basic writing

Next, prepare the configuration code for the plugin.

The following is the basic settings.

See the comments in the code for details.

// Obtaining the Cookie Consent Plugin
var cc = initCookieConsent();

// Run the plugin with your settings.
cc.run({
    current_lang : 'en',  // Language Preferences. Multilingual support is described later in this article.
    autoclear_cookies : true,  // Automatically delete cookies when cookies in a particular category are opted out. default: false
    cookie_name: 'cc_cookie_demo1', // Cookie name for this plugin. default: 'cc_cookie'
    cookie_expiration : 365,  // Cookie expiration date for this plugin. default: 182
    page_scripts: true,  // If the plugin is set by an attribute value in the script tag as described in this article, set it to true.  default: false

    // auto_language: null,  // Automatic language setup. Described later.  default: null; could also be 'browser' or 'document'
    // autorun: true,  // default: true
    // delay: 0,  // default: 0
    // force_consent: false,
    // hide_from_bots: false,                   // default: false
    // remove_cookie_tables: false              // default: false
    // cookie_domain: location.hostname,        // default: current domain
    // cookie_path: "/",                        // default: root
    // cookie_same_site: "Lax",
    // use_rfc_cookie: false,                   // default: false
    // revision: 0,                             // default: 0

    // Layout Settings. You can change the layout by changing the options here.
    gui_options: {
        consent_modal: {
            layout: 'box',                      // box,cloud,bar
            position: 'bottom right',           // bottom,middle,top + left,right,center
            transition: 'slide'                 // zoom,slide
        },
        settings_modal: {
            layout: 'box',                      // box,bar
            // position: 'left',                // right,left (available only if bar layout selected)
            transition: 'slide'                 // zoom,slide
        }
    },

    // Code you want to run on first run
    onFirstAction: function(){
        console.log('onFirstAction fired');
    },

    // Code you want to run when the cookie is accepted
    onAccept: function (cookie) {
        console.log('onAccept fired ...');
    },

    // Code to be run when cookie consent content is changed
    onChange: function (cookie, changed_preferences) {
        console.log('onChange fired ...');
    },

    // Language-specific settings
    languages: {
        'en': {
            // Modal text
            consent_modal: {
                title: ' We use cookies! ',
                description: 'Hi, this website uses essential cookies to ensure its proper operation and tracking cookies to understand how you interact with it. The latter will be set only after consent. <button type="button" data-cc="c-settings" class="cc-link">Let me choose</button>',
                primary_btn: {
                    text: 'Accept all',
                    role: 'accept_all'              // 'accept_selected' or 'accept_all'
                },
                secondary_btn: {
                    text: 'Reject all',
                    role: 'accept_necessary'        // 'settings' or 'accept_necessary'
                }
            },

            // Detailed cookie settings explanation
            settings_modal: {
                title: `Cookie Settigs`,
                save_settings_btn: 'Save settings',
                accept_all_btn: 'Accept all',
                reject_all_btn: 'Reject all',
                close_btn_label: 'Close',

                // Name of the entry in the table that describes each cookie
                cookie_table_headers: [
                    {col1: 'Name'},
                    {col2: 'Domain'},
                    {col3: 'Expiration'},
                    {col4: 'Description'}
                ],
                blocks: [
                    {
                        title: 'Cookie usage',
                        description: 'I use cookies to ensure the basic functionalities of the website and to enhance your online experience. You can choose for each category to opt-in/out whenever you want. For more details relative to cookies and other sensitive data, please read the full <a href="#" class="cc-link">privacy policy</a>.'
                    }, {
                        title: 'Strictly necessary cookies',
                        description: 'These cookies are essential for the proper functioning of my website. Without these cookies, the website would not work properly',
                        toggle: {
                            value: 'necessary',  // Cookie category name. The category name defined here is specified in the data-cookiecategory attribute of the script tag.
                            enabled: true,
                            readonly: true          // cookie categories with readonly=true are all treated as "necessary cookies"
                        }
                    }, {
                        title: 'Performance and Analytics cookies',
                        description: 'These cookies allow the website to remember the choices you have made in the past',
                        toggle: {
                            value: 'analytics',  // Cookie category name. The category name defined here is specified in the data-cookiecategory attribute of the script tag.
                            enabled: false,
                            readonly: false
                        },
                        // Write text according to the names of the items in the table above.
                        // If you omit the cookie_table itself, you can also omit the description of each cookie.
                        cookie_table: [
                            {
                                col1: '^_ga',
                                col2: 'google.com',
                                col3: '2 years',
                                col4: 'description ...',
                                is_regex: true  // Enable/disable regular expressions
                            },
                            {
                                col1: '_gid',
                                col2: 'google.com',
                                col3: '1 day',
                                col4: 'description ...',
                            }
                        ]
                    }, {
                        title: 'Advertisement and Targeting cookies',
                        description: 'These cookies collect information about how you use the website, which pages you visited and which links you clicked on. All of the data is anonymized and cannot be used to identify you',
                        toggle: {
                            value: 'targeting',  // Cookie category name. The category name defined here is specified in the data-cookiecategory attribute of the script tag.
                            enabled: false,
                            readonly: false
                        }
                    }, {
                        title: 'More information',
                        description: 'For any queries in relation to my policy on cookies and your choices, please <a class="cc-link" href="https://orestbida.com/contact">contact me</a>.',
                    }
                ]
            }
        }
    }

});

Edit the <script> tag of the analysis tool etc. you are using

Edit the attribute values of the tags of the 3rd party scripts used by the analysis tool, etc. according to the values of settings_modal > blocks > toggle > value in the configuration code, like type="text/plain" data-cookiecategory="{category name}".

Please refer to the following sample.

<script type="text/plain" data-cookiecategory="analytics" src="analytics.js" defer></script>

<script type="text/plain" data-cookiecategory="ads">
    console.log('"ads" category accepted');
</script>

The setup is now complete.

Settings for using Google Analytics with GTM

When using Google Analytics with GTM, select a tag type that suits your measurement method, such as Universal Analytics or GA4, instead of Custom HTML on the GTM administration screen.

If you use Custom HTML and enter analytics measurement tags, you will receive the following warning.

Any gtag commands in custom HTML may not work as intended due to how the data layer processes information.

This means that you cannot directly edit the attribute values of the script tag.

In that case, a little tweak is needed.

First, you need to make sure that the GTM is loaded after the Cookie Consent, which is the same as the aforementioned code.

Then, put the attribute value for Cookie Consent in the attribute value of the script tag that loads the GTM.

<!-- Plug-in JS -->
<script defer src="../../src/cookieconsent.js"></script>

<!-- Plugin Settings JS -->
<script defer src="cookieconsent-init.js"></script>

<!-- GTM Tag -->
<script type="text/plain" data-cookiecategory="analytics">
    // Google Tag Manager (configured with GA internally)
    (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-XXXXXXX');
</script>

Next, in the Cookie Consent setting, write that data will be stored in the Google Analytics cookie if consent is obtained in the analytics category.

onChange: function(cookie, changed_preferences) {
    if (cc.allowedCategory('analytics')) {
        gtag('consent', 'update', {
            'analytics_storage': 'granted'
        });
    } else {
        gtag('consent', 'update', {
            'analytics_storage': 'denied'
        });
    }
}

onChange is a callback function that fires when the cookie consent setting is changed.

Please refer to the following

Available callbacks - orestbida/cookieconsent

For more information on allowedCategory, click here.

API methods - orestbida/cookieconsent

analytics_storage is one of the data that Google Tag Manager manages based on consent, and is one of the consent types to enable or disable cookies for analytics.

Another consent type that stores advertising-related cookies is ad_storage.

For more information, please refer to this article.

Manage consent settings (web)  |  Tags  |  Google Developers

Consent configuration - Tag Manager Help

Added on 2022-08-07
The code in the onChange callback function above did not set the cookie properly.

Therefore, I have solved this problem by adding the following code below the GTM measurement tag.

<!--- enable analytics when "analytics" category is selected --->
<script type="text/plain" data-cookiecategory="analytics">
    gtag('consent', 'update', {
        'analytics_storage': 'granted'
    });
</script>

Adding GTM Consent Mode features to Cookie Consent was mentioned in the following Issue, but currently, the above code is a recommended way to handle this issue.
(The thread also mentions the onChange method, but for some reason it didn't work in my environment)

Add native support of GTM's Consent Mode (GCM) · Issue #110 · orestbida/cookieconsent · GitHub

Trigger type for tags set in GTM

The trigger type for the tags managed by GTM should be "Page View" instead of "Initialization".

With "Initialization," the tags are not fired properly even if the user agrees to the use of cookies in the Cookie Consent banner.

Configure multiple languages

First, to configure multiple languages, prepare the following blocks for each language

languages: {
    'en': {}
}

Next, set the language to be displayed according to the page you are accessing.

If you want to explicitly change the language, set current_lang to the language you want to display.

If you want to change the language according to the environment, remove current_lang and apply auto_language.

There are two options for auto_language.

auto_language: 'browser',  // change according to your browser settings
auto_language: 'document', // change according to  <html lang="..."> 

That is all for this article.