Master the cookie law with ExpressionEngine

Cookies are delicious. So it’s understandable why ExpressionEngine likes to consume them: from remembering your last visit, tracking where you are, remembering your shopping cart or whether you’re logged in – they’re just handy.

However, where it starts to crumble (I’m not ditching this trail of puns – get used to it), is for sites that can’t get by without running cookie-less, and running on an “implied consent” basis simply doesn’t cut it.

It’s now pretty widely accepted that sites that need cookies to operate do not need opt-in for that functionality; probably the most common example of this is a shopping cart. So that’s all well and good, but what if your site also uses third-party cookies served up by Google Analytics, advertisements and even Twitter, Facebook and Google+ buttons? They are arguably non-essential, and because they’re third-party, implied consent may not be enough.

Here’s where there will be differing schools of thought. But for this article I’m going to make the argument that if we want cookies for other things such as Google Analytics, serving ads, A/B testing and the countless other things you may wish to do in EE, then we may as well have one single up-front message covering it all in one go.

Modular approach

ExpressionEngine is increasingly modular: it’s been a focus for EllisLab for some time. They generally take the approach that if they can’t build a new first-party feature with the API, they will add it to the API first.

This approach means that for some time EE has had a “Set Cookie” method in the API – which, in turn, means that the vast majority of third-party add-ons use it (those that don't are doing it wrong!)

Because of this, EllisLab has been able to modify the way cookies are set – and as of ExpressionEngine 2.5 (now available as a free upgrade for existing 2.x customers) you can enable a free “Cookie Consent Module”, which declines add-ons requests to set cookies unless the user agrees.

Technical installation

First of all, ensure that your ExpressionEngine website is using at least version 2.5.0; the module isn’t compatible with older versions because of changes to the core that has made it possible.

Once it’s installed, don’t be concerned that you can’t find the module in your control panel – it’s not actually distributed in ExpressionEngine; instead it is available from the first party add-ons page.

Simply upload the files into /system/expressionengine/third_party/ and enable your new module from your administration panel, Add-Ons > Modules.

That’s it! You’ve now done the technical installation. On to the design…

Design installation

Of course, the design for the cookie consent is going to differ on a site-by-site basis; both from a visual and linguistic point of view to be convey the reason to the audience at hand. For example, while a government website might take a formal route, a children’s TV show’s website may pitch the message as “Go grab your parents…”.

Your consent message will vary both visually and linguistically depending on your audience

Your consent message will vary both visually and linguistically depending on your audience

ExpressionEngine’s cookie consent module adopts the same templating engine used for the rest of your website, so implementation is simple and flexible.

The difficulty, of course is making it not feel like an error. If the user thinks it’s broken, they’re going to leave.

  1. If we’re asking for consent anyway, we have a good reason to use cookies. Explain that to the user as succinctly as possible and link them to the full list of cookies your site uses (as dictated by the law).
  2. Avoid red colours – this encourages the assumption that something is wrong
  3. Make the message stand out – you want their consent.
  4. However, make it suit the website. Don’t try to emulate a native browser message or hide the page entirely.

Having a strap at the top of a website asking for permission seems to be the preferred way to implement cookie consent. The BBC, ICO and Channel 4 all use this technique; it doesn’t distract from the reason they are on the website (the content) but is prominent enough for people to want to click it – even if the reason is just to make it go away!

The implementation of a bar like this is incredibly simple. Within your template, which is most likely going to be your header or simply add (and tweak) the following:

{exp:cookie_consent:message} {if cookies_allowed!="yes"} <div id="cookie-message"> <h4>{site_name} uses cookies to enhance your experience...</h4> <p>Cookies are small text files that are safely stored on your computer. They allow websites to do clever things like remember if you’ve asked to stay logged in or what you have in your shopping cart. We also use cookies to find out how people use this website so that we can make it even better in future. These cookies don’t contain any personal or sensitive information and are only used by {site_name} and our trusted partners such as Facebook and Google. <a href="{cookies_allowed_link}">Accept &amp; Close this message</a></p> </div> {/if}{/exp:cookie_consent:message}

So let’s break that down. First of all, we want to load the new cookie consent module. Within that there is a handy variable {cookies_allowed}, which is a simple Boolean telling us, quite simply, whether the user has given us permission to use cookies or not.

Using this, we can quickly detect that the user hasn’t yet given us permission and render up some additional HTML. Quite simply we have an overlay div which adds the dimmed background and within that the message itself.

Finally, you want to give the user the opportunity to delete the cookies and decline future cookies being stored. For this, we again use the trust if-statement but this time inverse it – so we’re effectively doing, “if cookies have been accepted, let’s show a link to disable them”.

{exp:cookie_consent:message}{if cookies_allowed == 'yes'}<a href="{clear_ee_cookies_link}">Forget my cookies and don’t store any more...</a>{/if}{/exp:cookie_consent:message}

And with that, you’re done with a basic implementation of the Cookie Consent Module.

Shortcomings and overcoming them

The Cookie Consent module only works if the cookie was set using the ExpressionEngine API. External cookies, such as those set in JavaScript (Google Analytics for example) do not honour the user’s decision here. One way to solve this is to wrap said JavaScript in this:

{exp:cookie_consent:message}{if cookies_allowed == 'yes'}{/if}{/exp:cookie_consent:message}

That way, it will only render once the users gives ExpressionEngine (thus your site) permission. Of course, you would still need a way to remove the cookies set by Google; one potential way is to run some JavaScript on the “Cookies are cleared” system messages… talking of which, I hate the ExpressionEngine “User Messages” system.

I think they’re inherently ugly and take users out of your site’s overall style. Unfortunately, the module uses these system messages to proudly tell the user for around five seconds “Cookies have been accepted”. While these are loosely stylable, they fall outside of ExpressionEngine’s templating system and as typically look like error messages – plug-ins such as will enable further site integration.

An alternative trick I have used on one or two builds using this module is to send a jQuery POST request to the “I accept” URL – using this method you can bypass the system screens and opt to display your own, well designed, thank you message.

ExpressionEngine s quot User Message quot system messages are inherently ugly

ExpressionEngine's "User Message" system messages are inherently ugly

My ultimate goal is to make sites only request cookies as and when they first need it. It’s a double-edged sword because Google Analytics are of course invaluable so I really want that consent within the first second of them visiting the site – but I have a feeling this may not work so well. So perhaps we can be a bit smarter about it (without being too much like Clippy from Office):

  • “To add this product to your basket – click here to accept cookies”
  • “By logging into the site, you agree that we can store cookies on your computer”

Finally, this law is EU specific – and even then it differs slightly from country-to-country. Utimately we’d love to see it so the behaviour of the module changes based on the user’s location using the built-in “IP to Nation” module. This isn’t possible yet. But it’s also early days.


While we can complain about the law, we really can’t about the assistance EllisLab have given us to comply with it. The responsible approach taken by the company ensures that the CMS can be continued to be used in EU countries without hacks or (potentially expensive) workarounds.

The implementation is also simple. It should take less than half an hour on a 2.5 install – and while the law does require slightly more than just this, it does cover the largest technical aspect of the problem.