Introduction

intro picture

This is a follow up to a previous tutorial regarding a GDPR cookie consent banner for Jekyll sites. I have since switched from Jekyll to Hugo. Since I needed to modify how the cookie consent banner was implemented, I thought it would be appropriate to cover the steps taken.

This tutorial considers you want to use Google analytics cookies, and the banner will enable the client browser to download the cookies only if consent is given. If it is denied, then no analytics cookies are downloaded and the banner disappears.

I made a github repository with the code that you will need for this tutorial, thought you can follow along here and copy the code directly from here.

Process

Firstly, find the file that is including the default google_analytics.html file. Usually this will be in the head.html file found in your theme files. Since I am using the PaperMod theme, I have a file in my partials directory that is called head.html. The point is, you must find the code that will be in the head of your website.

At the end of my head.html file, I had something like this:

{{- /* Misc */}}
{{- if hugo.IsProduction | or (eq .Site.Params.env "production") }}
{{- template "_internal/google_analytics.html" . }}
{{- template "_internal/google_news.html" . }}
{{- template "partials/templates/opengraph.html" . }}
{{- template "partials/templates/twitter_cards.html" . }}
{{- template "partials/templates/schema_json.html" . }}

Take note that the third line is including some defaults that are included with the theme for adding Google analytics functionality. Comment out/remove such a line if you have it, and replace it for the following:

{{- template "partials/templates/cookie-consent.html" . }}

The partials/templates/cookie-consent.html part is the location of the new file that needs to be created called cookie-consent.html. The path is not important as far as you know where it is, this was to keep it organized within my current theme.

Create the cookie-consent.html file in the specified directory and add the following contents:

<div id="cookie-notice">
<span>We would like to use third party cookies and scripts to improve the 
functionality of this website.</span>
<a id="cookie-notice-accept" class="btn btn-primary btn-sm">Approve</a>
<a id="cookie-notice-deny" class="btn btn-primary btn-sm">Deny</a>
<a href="/privacy" class="btn btn-primary btn-sm">More info</a></div>
<script>
    function createCookie(name,value,days) {
        var expires = "";
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days*24*60*60*1000));
            expires = "; expires=" + date.toUTCString();
        }
        document.cookie = name + "=" + value + expires + "; path=/";
    }
    function readCookie(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for(var i=0;i < ca.length;i++) {
            var c = ca[i];
            while (c.charAt(0)==' ') c = c.substring(1,c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
        }
        return null;
    }
    function eraseCookie(name) {
        createCookie(name,"",-1);
    }

    if(readCookie('cookie-notice-option')=='true') {
        {{ if hugo.IsProduction | or (eq .Site.Params.env "production") }}
        
        function loadScriptAsync(scriptSrc, callback) {
            if (typeof callback !== 'function') {
                throw new Error('Not a valid callback for async script load');
            }
            var script = document.createElement('script');
            script.onload = callback;
            script.src = scriptSrc;
            document.head.appendChild(script);
        }

        /* This is the part where you call the above defined function and "calls back" 
        your code which gets executed after the script has loaded */
        //REPLACE WITH YOUR GA TAG!
        loadScriptAsync('https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX', function () {
            window.dataLayer = window.dataLayer || [];
            function gtag() { dataLayer.push(arguments); }
            gtag('js', new Date());
            gtag('config', 'G-XXXXXXXXXX', { 'anonymize_ip': true }); //REPLACE WITH YOUR GA TAG!
        })

        {{ end }}
    } else if (readCookie('cookie-notice-option')!='false'){
        document.getElementById('cookie-notice').style.display = 'block';
    }

    document.getElementById('cookie-notice-accept').addEventListener("click",function() {
        createCookie('cookie-notice-option','true',31);
        document.getElementById('cookie-notice').style.display = 'none';
        location.reload();
    });

    document.getElementById('cookie-notice-deny').addEventListener("click",function() {
        createCookie('cookie-notice-option','false',31);
        document.getElementById('cookie-notice').style.display = 'none';
        location.reload();
    });

</script>

Credit to this stack overflow question for the help.

Notice that you must replace the G-XXXXXXXXXX with your google analytics tag where specified.

The base cookie-consent.html file is also on my github repository.

This will allow the google analytics cookie only if the user agrees with the banner. This base cookie banner includes a “Accept” “Deny” and “More info” buttons. The more info button will redirect to the page located at /privacy, though it can be changed by modifying the href of the More info button.

Finally, let’s add some styling to the banner!

The style code I use for my website is the following:

#cookie-notice {font-size: larger; padding: 0.5rem 1rem; display: none;
text-align: center; position: fixed; bottom: 0; left: 20px; padding-top: 40px;
padding-bottom: 40px; width: 100%; background: rgb(70, 70, 70);
color: rgba(255,255,255,0.8);}

#cookie-notice a {font-weight: 600; display: inline-flex; cursor: pointer; margin-left: 0.5rem;}
#cookie-notice-accept {color:rgb(86, 228, 58)}
#cookie-notice-deny {color:rgb(243, 34, 34)}
@media (max-width: 767px) {
    #cookie-notice span {display: block; padding-top: 3px; margin-bottom: 1rem;}
    #cookie-notice a {position: relative; bottom: 4px;}
    #cookie-notice {left: 0px;}
}

Your theme should have a main.css file or similar. Add it there. If you can’t find this file and can’t figure out which css file it is that you should add it to (there are some themes with a LOT of css files), then worse case you can add some html style tags inline with the cookie-consent.html code.

This will make the banner stick to the bottom and color the different buttons. Feel free to modify it to your liking.

That’s it! Now you can run the Hugo server using hugo server -D.

Hope it was helpful! Please share this on social media if you know someone that it might help! Links below!