A simple cookie banner implementation (JavaScript)
20 Dec 2020 - tsp
Last update 20 Dec 2020
7 mins
Yes, no-one really likes cookie banners. And technically they donāt serve any
real purpose. But there is a bunch of people without much knowledge about
web technology that seem to be incapable of configuring their browsers and
tend to decide on some strange laws and so here we are with the (in)famous
EU directive 2009/136/EC
also known as the cookie law. Please note that Iām not a lawyer so nothing
on this page is legal advice.
As we all know these banners are required in case someone includes some third
domain content that might add an Set-Cookie http header that might include
some stuff that might be used for user tracking. So here is one of the most
simple methods on how to implement such a banner in case these third party
resources are only loaded - or are legally promising - to only set these headers
after some kind of action has been taken (the cookie constent).
Warning: Personal opinion following up to the next heading ā¦
First off - I personally donāt think this is a good solution and there is a really
simple and easy way to solve that problem:
- In case one doesnāt want to have any cookies set at all simply configure your
browser to not allow it to store cookies. This is not required by the HTTP
specification although since itās the only standard conforming way of
storing state by means of HTTP some pages that have to keep track of login
status or similar might not work any more in this case. But one can whitelist
pages in any modern browser - in fact for Chromium it takes exactly two clicks
to allow or disallow cookie storage for a given page
- Simply disallow loading of third domain content. Iād really favor this solution
but there is currently no browser that allows one to set such a policy without
the usage of extensions. But theyāre out there and are pretty easy to use.
- Configure your browser to store session cookies only. This means the browser
is clearing itās cookie storage every time you close it. Thatās an really
effective solution.
- Visit pages that you donāt want to store anything with private mode tabs. These
only create a temporary local storage store for cookies and some other local
storage - nothing more and nothing else.
And keep in mind that cookies are not the only means of tracking as long as
you have JavaScript enabled.
But as of today politicans seem to lack understanding of the basic principles
of the WWW and so we are required to display banners asking one if one wants to
allow the page to store information - which is technically not valid since the
browser stores this information and returns it voluntarily on behalf of the
user to the servers at the next request - and requires the users to rely on the
pages author being honest and storing tracking information only after consent
instead of technically preventing it which would be way easier.
The implementation
The following solution works in case all actions that require the consent banner
to be displayed are triggered by JavaScript and not simple HTTP tags (note that
this might also be the case).
The idea is pretty simply:
- Provide a simple block level container element for the banner to be filled
by some javascript. This block level element (
div) will be empty
in markup so it doesnāt disturbe anyone when having scripts disabled.
- Adding a JavaScript file thatās loaded and that is registering an
DOMContentLoaded
listener. The event handler is simply
- Checking if the consent has already been given. In this case some code to
enable the scripted behaviour is run
- If not fill the banner with content and register accept and deny button
handlers. Then display the banner.
- In case the banner is accepted execute the same startup code as previously,
set a cookie to remember the choice and hide the banner.
- In case no consent is given hide the banner and donāt set any cookie at all.
So letās dive directly into the code. On the HTML page one only requires
the element to be filled anywhere inside the body:
<div id="cookieBanner"></div>
Inside the head section one imports the script:
<script type="text/javascript" src="/cookieconsent.js"></script>
The script file is also pretty simple. First off it contains three simple
helper functions for easier cookie handling:
function cookieConsentSetCookie(name, expires, content) {
let currentDate = new Date();
currentDate.setTime(currentDate.getTime() + (expires * 24 * 60 * 60 * 1000));
document.cookie = name + "=" + content + ";expires="+(currentDate.toUTCString())+";path=/";
}
function cookieConsentDeleteCookie(name) {
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/";
}
function cookieConsentGetCookie(name) {
let pstring = name + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let cookieArray = decodedCookie.split(';');
for(var i = 0; i < cookieArray.length; i++) {
let cookie = cookieArray[i];
// Trim whitespace
while (cookie.charAt(0) == ' ') {
cookie = cookie.substring(1);
}
if (cookie.indexOf(pstring) == 0) {
return cookie.substring(name.length, cookie.length);
}
}
return false;
}
These helper functions allow one to set a cookie with name and parameter, delete
a cookie by setting itās expiration date into the past and a method to read a given
cookie from the browsers context. Note that these are rather generic although
one has to keep in mind that not all cookies are accessible from JavaScript.
Then there is a function that contains some custom code that will be executed
after consent has been given - this can be used to load additional features
like social media sharing, advertising javascript, start fetching of ads, etc.:
function cookieconsentStartAdProcessing() {
// ToDo
}
The last part is the event handler that gets executed as soon as the DOM is
ready:
window.addEventListener('DOMContentLoaded', () => {
if(!cookieConsentGetCookie('cookieConsent')) {
let banner = document.getElementById('cookieBanner');
if(!banner) { return; }
// Fill with content. Replace with your own content
banner.innerHTML = "<h2>Cookie consent</h2> <button id=\"cookieNope\">No Cookies</button> <button id=\"cookieOk\">Ok, accept cookies</button>";
let buttonNope = document.getElementById('cookieNope');
let buttonOk = document.getElementById('cookieOk');
if(buttonNope) {
buttonNope.addEventListener('click', () => {
banner.style = "display: none;";
});
}
if(buttonOk) {
buttonOk.addEventListener('click', () => {
banner.style = "display: none;";
cookieconsentStartAdProcessing();
cookieConsentSetCookie("cookieConsent", 31, "yes");
});
}
banner.style = "display: block;";
} else {
cookieconsentStartAdProcessing();
cookieConsentSetCookie("cookieConsent", 31, "yes");
}
});
As one can see the code is really simple. At first it locates the div that
will be used as banner container and fills it by writing into the innerHTML
property. This is the easiest way to get content into an HTML element using
JavaScript. Then it located the single button or both buttons inside the form that
will be used to give or decline consent. The event handler attached to decline
simply hides the banner again, the accept button hides the banner too, calls
the startup function, and sets a cookie for the next 31 days. Everytime the
user visits the page again the cookie is set again for another 31 days. One has
of course also to provide a way of revoking consent - this can be done simply by
providing an button that calls the cookieConsentDeleteCookie function again - on
this page itās done on the data protection policy
page.
The last element required is some kind of design. As the current page suggests
Iām not a designer so there are not many tips I can give for that. Basically
what Iāve done for this page is a simple stylesheet based approach that positions
the banner at a fixed window location, allows one to scroll inside (for mobile
devices with smaller screens) and of course set the banner to be hidden
by default. Since Iām using float objects inside my cookie banner Iāve also
added a clear statement after the banner division itself.
#cookieBanner {
position: fixed;
top: 20%;
max-height: 50%;
overflow: scroll;
display: none;
border: 5px solid red;
background-color: yellow;
padding: 1em 1em 1em 1em;
margin-left: 1em;
margin-right: 1em;
}
#cookieBanner:after {
clear: both;
}
This article is tagged: