Message us

All great projects start with a conversation.

Thank you. We received your message and will get back to you soon!

Browse our showcase

or Send another message?

UX & UI

Cookie consent in Craft CMS

James Smith

Should you use Craft’s native capabilities for consent management instead of maintaining yet another third-party subscription tool?

A battleground for visitors’ privacy

For some visitors, they’re a reassuring indication that the people behind the website they’re visiting actually care about preserving their privacy... For most, though, they’re just a daily annoyance where they blindly click “Accept All” to gain faster access to what they’re looking for.

The burden of website owners’ responsibilities relating to data protection and privacy has increased in both weight and complexity: in order to comply with evolving and globally diverse legislation, as well as to maintain visitors’ trust, websites must offer a way for visitors to reject unnecessary cookies and related tracking technologies.

Probably the best way for someone to define their online privacy preferences would be a centralised setting, natively inside the browser itself, and have those preferences apply to every website that person visits. Google’s Privacy Sandbox initiative partly aims to achieve that goal by introducing a set of new web standards and APIs. Until recently, Google even set their Chrome browser on a path towards blocking third-party cookies entirely, but they have since made a dramatic U-turn on this decision. Cynically, one could probably assume that the decimation of advertisers’ profits would be one of the major motivations in their reversal.

The Privacy Sandbox initiative is not without its controversies: the W3C’s swift riposte to their U-turn, “Third-party cookies have got to go” gives an interesting insight into the in-fighting; and in any case, in its current form, it’ll require collaboration (and compliance) not only with multiple regulatory bodies, but also with third-party providers who’ll need to move to an entirely new system of tracking. In the meantime then, we’re going to be stuck with these cookie consent banners for potentially a long time.

Craft CMS and cookies

We are staunch advocates (and also partners) of Craft CMS; it’s our preferred content management platform for almost all types and sizes of websites. One of Craft’s best features is its ‘blank canvas’ approach to the front end. This means that it doesn’t have any built-in mechanism for managing your visitors’ consent preferences - and nor should anyone expect it to, because it has no intrinsic knowledge of the individual things that require consent, if any.

However, Craft already provides everything you need to create your own native solution that empowers site owners to manage the components of their site that require visitors’ consent.

Not only do you not need a third-party solution to manage cookie consent on a Craft CMS site, but it’s also possible that deploying a native solution in Craft will be better for everyone. All projects are different, of course, and there are pros and cons to each approach - Get in touch with us today and we can help you assess the best way for your business to implement consent management in Craft CMS.

“Just install Cookiebot”?

There are countless subscription-based third-party turnkey services, known formally as “Consent Management Platforms”, or informally as “cookie banners”, that purport to solve all of this for you with minimum effort and a monthly fee. Unfortunately, despite some of them being highly sophisticated, these services all suffer from common flaws that cannot always be adequately resolved.

To understand and evaluate those flaws we first need to understand how these tools work. Typically they:

  1. Conduct regular scans of your website to identify what cookie-planting scripts you might be using;
  2. Log all those usages in their system so they can be categorised accordingly;
  3. Load themselves with high priority from your site’s <head> so that they can attempt to block all the logged script usages that they encounter before they get a chance to execute;
  4. Present the visitor with an interface to allow them to accept or reject cookies based on their category;
  5. Attempt to enable or disable the right scripts at the right time;
  6. Remember the user’s choice so that they’re not asked again for a certain period;
  7. Provide an interface to show a summary of cookie descriptions based on the scan results.

This is a significant amount of work for anyone to have to do, so it’s understandable that site owners and developers alike are seduced into offloading this to a third-party. Unfortunately each of the steps above introduce multiple pitfalls that might negatively impact a website in different ways:

Reasons to Go Native for cookie consent in Craft CMS

1. Compliance & Accuracy 😇

You’d probably expect that by using a third-party service - particularly one that you have to pay for - that “compliance” with all relevant laws and regulations would be something you could take for granted. Unfortunately the reality is that these services cannot guarantee proper compliance.

Use of some third-party cookie banners might in itself even be a breach of certain legislation due to, for example, the undisclosed technology partners that they use to deliver their service, such as Content Delivery Networks.

Dynamically injected scripts. A native solution can be fully aware of cookies that might be injected dynamically - e.g., for lazy-loaded components that are only instantiated when a visitor scrolls close to them, or for functionality hidden behind facades, which only load fully when the user starts to interact with them, or for websites that dynamically replace the entire page’s content during navigation without a traditional full page reload. Things like captchas, maps, videos, live chat, reviews, forms, recipes, and a myriad of other third-party embeddable widgets all have the potential to require consent, as they can track your visitors’ behaviour.

The site scans performed by third-party consent providers try to uncover all usages of cookie-planting scripts across your whole site, but some of them can miss these dynamically injected ones.

Hidden pages. Other scripts on your site might be hidden on private pages that are not discoverable through an automated scan, or they might be protected by a login - you’d need to manually account for these when using a third-party provider, assuming your chosen provider gives you that ability.

Scanning inaccuracies. Depending on the frequency/scheduling of your scans, you’re likely to also suffer some periods where certain third-party scripts have not yet been discovered, and/or old ones are still being referenced in your usage table, leading to non-compliance. It’s not uncommon for some of our customers to test out several different service providers all within a single day! These need to be accounted-for and reflected immediately in your consent solution for proper compliance.

In some cases, third-party solutions will also block essential first-party resources, requiring extra workarounds to ensure that certain scripts are never blocked.

2. Performance 🚀

A third-party solution will block the initial rendering of the site while it downloads and executes, attempting to prevent all of the other scripts from executing unless/until consent has been given for their corresponding category. This expensive, horse-before-cart, ex post-facto operation is downright bad practice. Performance issues aside, if for some reason the third-party’s heavyweight script fails to load, the floodgates are opened and none of your visitors’ consent preferences will be respected.

(Aside: it’s a deliciously predictable irony that our industry’s response to the problem of taming the amount of third-party JavaScript permitted to run on a site is to… add hundreds of kilobytes more third-party JavaScript).

With a native solution in Craft, all cookie usage is known in advance: there’s no need for scans, and no need to block page rendering, because none of the scripts that require consent are included in the initial page load in the first place! This mirrors progressive enhancement - one of the cornerstones of Web Standards - we start with the most simple base functionality (which, importantly, shouldn’t block anyone from using the site), before layering-on extra complexity.

The <head> section of your website should be sacred territory - nothing should be allowed there that’s not absolutely critical to the smooth rendering of your site.

The deep site scans that are run by third-party providers can also take a toll on performance by consuming server resources, especially as they typically attempt to emulate real users. (You’re not exactly DDoS-ing yourself, but you probably wouldn’t want to be running those deep scans at the same time that the marketing department is sending its monthly newsletter email!)

3. User experience 🤩

When a third-party consent provider has successfully found and categorised a script that has not been consented-to, their simplistic solution is usually to completely block it. A visitor would be left completely unaware, for example, that an embedded video has not been loaded, or that the site has a now-inaccessible live chat function that they might have wanted to use at a later stage of their journey (i.e., later than the point at which they first chose their consent options).

With a native solution, however, you can provide a much better user experience by showing a facade and asking for the appropriate consent (and only the appropriate consent) on-demand, when a visitor tries to interact with a blocked component (in addition to, or instead of, asking for consent upfront).

Some of the more advanced third-party solutions might allow developers to access an API to build this kind of functionality on top of their platform, which is great - but for the same amount of effort you might as well be building a native solution instead!

Like everything else in Craft, with a native solution you have complete control over everything from styles, fonts, and transitions, to the level of detail you want to show and, crucially, the level of obtrusiveness. You can make it blend in seamlessly with your site and choose not to completely block your visitors from browsing. Third party providers vary a lot in terms of the options they give you, but they are typically far too heavy on detail and too obtrusive, often completely blocking access to the site to ask for upfront consent.

A native solution can be integrated with your normal content management workflows and content components. For example, it becomes trivial to output a table that summarises all the cookies or third-party service providers in use across your site, and that table can be seamlessly embedded as part of the page flow inside your cookie policy content. Some third parties provide this functionality too, but they are typically far too detailed for an average user to understand, and presented in completely generic terms that can apply to any website. A native solution can be tailored to describe how and why your business uses each provider.

4. Cost 𐄷

With every bit of functionality that a project implements, it’ll accrue technical debt. It’s important to consider whether the technical debt from an extra third-party dependency, cost, trust relationship, and security risk outweighs the technical debt you’d inevitably also accrue from a native solution.

A native solution also affords your clients the opportunity to fully manage their service providers directly in Craft without having to administer and tweak settings in a separate system (along with gaining and maintaining access to that system for the right members of staff and ensuring they are trained on how to use it).

“Just install a Craft plugin”?

A different approach might be to use a Craft plugin. We take a fairly strict stance in relation to CMS plugins. During upgrades and migrations, they are the single most problematic area your site faces. From poor quality integration with the core, to security and performance flaws, and to complete abandonment (even for paid plugins), the problems are wide-ranging, and, largely, avoidable. By sticking ‘close to the metal’ and maintaining your own solutions, you can react quickly to ongoing changes, such as Google’s recent insistence on their “Consent Mode V2” for sites that use their remarketing or advertising functions.

(For the record, we’re not anti-plugins, but I’d encourage everyone to undertake risk assessments and cost-benefit analyses for all but your simplest of projects. And remember, the “cost” in “cost-benefit” isn’t just a measure of the dollar-price of a plugin vs your hourly rate. We use plenty of plugins, but we are native-first.)

Moreover, when it comes to the issue of consent management, Craft already provides everything you need natively - sections, fields, relationships, and templates, so a third-party plugin is easily avoidable. If you want the cross-project portability benefits of a plugin, there’s no reason you shouldn’t upgrade your native solution into your own custom private plugin.

The case for third-party solutions

There will be some projects where opting for a third-party solution does make sense. Be sure to evaluate all of the downsides mentioned above first, though. How much do you care about performance? How serious is it if you’re never technically “compliant”, or if you have a few days or weeks of compliance failure before your next scan? The answers will vary according to your industry and your appetite for risk. There are some tempting benefits to the the third-party approach, which any native solution will be hard-pressed to match:

Cookie descriptions database - Third party solutions can draw on their vast databases of known cookies to give detailed descriptions of each one. Bear in mind, however, that not only is this information far too detailed for most people to understand or care about, but listing cookies individually by name and describing them is not actually mandated under the GDPR/PECR. Much better, in my opinion, to give descriptions at the provider and/or category level instead (see this guidance from the ICO under its explanation of “clear and comprehensive information”, which supports such an approach).

...a description of the types of things you use analytics cookies for on the site will be more likely to satisfy the requirements than simply listing all the cookies you use with basic references to their function. The Information Commissioner’s Office (ICO)

Still, if your legal department insists on listing cookies individually and describing each one in excruciating detail, this will take a reasonable amount of research and time in a native solution.

Plug-and-play - On the face of it, simply dumping a script tag into your <head> is generally going to be a faster process than manually administering your providers in Craft. But given the potential inaccuracies, don’t forget to factor in plenty of time to administrate and tweak your settings inside the third-party’s control panel.

Auto-categorisation - In a native solution, you’ll need to manually categorise each provider according to how you use them, whereas many third-party solutions can do this automatically based on their databases of known providers, saving you valuable seconds.

Internationalisation - Craft has some world-class multilingual features to help with translating your content, but having the third-party do that automatically could save you some significant time if you have a collection of multilingual sites.

Extreme granularity - Many of the larger third-party providers allow visitors to drill down to an extreme level of granularity, granting or denying permissions at the level of an individual provider instead of at a cookie category level. This usually results in a horribly confusing user experience, but if it’s important to your business for some reason, it’s worth considering. For the kind of sites that use lots of on-site advertising, for example, the extent of third-party tracking can be extreme, and some cookie scanning solutions will unearth over 1000 individual providers - many of which are dependencies of dependencies of an umbrella provider.

Usage analytics & tracking - At the risk of making my irony detector explode, it’s worth mentioning that some third-party solutions also come loaded with their own privacy-hostile user-tracking features. In some cases, this might be an important feature for your business, for example in order to provide a long-lasting record that a certain visitor gave you their consent at a certain time. You might also want to make use of the consent tool’s own usage statistics for some reason (though beyond mere curiosity I can’t imagine a single valuable use-case for collecting such data).

How the CLD Craft CMS cookie consent management solution works

With a solution native to Craft, it almost goes without saying that there are no limitations on how it could work, but here’s a quick tour of what we have come up with so far. (This article is not intended to be a technical “how-to” guide - not least because the implementation detail would vary enormously depending on how your site works), so I’ll keep it brief...

1. A “Scripts” section for managing any scripts/providers. Here, each entry in the section represents a single script or provider. Editors can categorise each one, and give extra details about what it’s for and even which cookies it sets and their durations (if it’s deemed necessary to go into such detail - though remember this is not a legal requirement). Editors can also add a raw script to be injected when a user consents to the script’s category, if any.

2. A “Cookie categories” section (or category group) for managing the scripts’ categories. Entries might typically include “Essential”, “Performance”, “Functionality” categories etc. Additionally, each category includes the opportunity to inject further category-level scripts, or, in our implementation we also allow selection from a set of presets for Google Tag Manager. This is important for being able to send consent signals into Google Tag Manager, and is also the way that you can implement the so-called “Advanced Implementation” of Google’s “Consent Mode V2″ natively. Any scripts held against the category will get injected alongside the individual script entries when a visitor consents to that category.

3. A new block type in the site’s main content builder (the “Body Builder”) matrix that outputs a cookie usage table.

As far as Craft is concerned, that’s all we need in order for our site editors to be able to self-serve and entirely manage their providers in Craft - all just simple, native Craft functionality.

A note on Google Tag Manager

It’s worth adding a warning regarding Google Tag Manager, if it’s being used on the site, because what we’re creating here is essentially replicating that functionality, and if an editor decides to inject scripts via GTM instead of Craft, it could potentially bypass all the visitor consents! With the consent signals that we send to GTM when certain categories are permitted or denied, we can wire up a custom trigger in GTM (just like providers like Cookiebot do) to allow editors to continue using GTM to inject scripts based on the visitors’ given consents, but in practical terms, there’s not really much advantage to doing this unless they’re using very advanced targeting - it’s a lot simpler to just keep everything in Craft. Event/goal tracking in GTM via Google Analytics is unaffected, so if editors are using it just for that, then there’s no extra work needed. In either case, GTM will receive everything it needs in order to be updated with the visitor’s consents.

It’s also worth noting here that (at the time of writing this article at least!), GTM on its own does not plant any cookies or related tracking technologies. It therefore doesn’t require consent, so it’s ok for editors to mark it as “Essential”. Typically though, it’ll be used in conjunction with Google Analytics, which does require consent.

Templates and front end

Here’s where it starts to get interesting! Being somewhat obsessed with performance, we’re big fans of static caching and use it wherever practical. Mainly for this reason, the bulk of your consent management logic should be in JavaScript so that it can be dynamically applied to the current visitor on top of a static page view. If JavaScript is unavailable or delayed for some reason (see everyonehasjs for an excellent summary of why progressive enhancement and graceful degradation are still relevant), then no cookie consents will be recorded and no consentable scripts will attempt to be loaded.

For the majority of visitors, however, if there are some scripts that require consent, the visitor will be presented on load with an unobtrusive, non-blocking, cookie banner asking for their consent or offering the opportunity to fine-tune which categories they’d like to consent to.

When the visitor submits their choice, if they haven’t declined everything, we asynchronously fetch a standard Craft template that gets the relevant scripts (using a simple native element query in Twig), and then we parse the response and inject them into the page. We then set our own cookies to remember which categories have been consented-to so that we can pre-fill the options if the visitor wants to edit them later, and we’ll also use another cookie to remember that the banner has been dismissed so it doesn’t show up again (and so we can instead show a control to edit their preferences). These cookies also allow us to re-inject the right scripts on each page view.

Blocking and facades

We frequently emphasise the importance of proper content modelling - something that Craft CMS enables at a fundamental level - and with a native cookie consent management solution, having your content properly modelled is critical - your site needs to ‘know’ the difference between a lump of text and an embedded video or form etc, so that you can apply special treatment to any content components that might require consent.

For any functionality that relies on the visitor having accepted a “Functionality” category (or whatever you want to name it), we show a facade of the real thing, that gets dynamically replaced at the appropriate time (either on load, or on scroll or on an interaction like a click). If the visitor has not consented to the Functionality category of cookies, the facade never gets replaced with the real thing, but instead triggers a modal window or component overlay asking the visitor to give their consent for that category. We try to make this as seamless as possible, so we’ll also trigger a click on the real thing alongside the consent acceptance here so that it immediately does whatever it is supposed to (i.e., in the case of a video it would start playing, in the case of live chat, it’ll popup the real live chat window). Interestingly, since we typically use facades for embedded videos for everyone anyway (for better performance), what you end up with in the case of videos is essentially a double facade!

A modal window that appears after attempting to click a Live Chat facade having previously refused functionality cookies.

Take the plunge, Go Native.

In my opinion, this native solution works very well - it’s highly performant, it gives editors complete control over their choice of service providers, allows the site owners to achieve full compliance all the time, and gives a better experience for end users too. When it’s fully under your ownership and control, you can add all the extra features you need as a project progresses. (For example, if an editor adds a brand new category of cookies to the site after your consent solution has already been launched, you might want to add a way to automatically invalidate all visitors’ prior consents based on the time of their last consent).

If you’d like to find out more about our Craft CMS services and how best to implement consent management or appropriate content modelling for your Craft site, please get in touch.