Skip to main content

Cookiebot and the Web Content Accessibility Guidelines (WCAG)

Published
9 minutes read

One of the most popular Cookie Consent Platforms (CMPs) is Cookiebot, Being a Google CMP partner means you'll often see Cookiebot (Usercentrics) cookie consent banners on a lot of websites (including this one!), however Cookiebot unfortunately has some accessibility issues which are potentially problematic and I wanted to explore what options there were to try and resolve or fix some of those issues.

These days implementing a managed cookie consent platform is often the preferred approach to comply to the latest cookies laws from your territory, in addition with Google making Consent Mode mandatory to continue using various services like Google Analytics or measuring conversions for products like Google Ads this is becoming a mandatory requirement. Because of this there are various Google CMP partners who integrate directly with Google Consent Mode, often alongside implementations through Google Tag Manager.

Cookiebot is one of those partners and well-used across various websites. While being one of the major names you'll likely see on advertising around cookie consent and Google Consent Mode, the out of the box cookie consent banner template and customisation are not WCAG complaint. This is a problem for websites which are required to comply to a minimum WCAG standard either by legislation/law or by self-regulation. For public sector bodies in the United Kingdom this is of particular importance, given the minimum requirement is WCAG 2.2 AA as of October 2024.

The accessibility issues with Cookiebot

The default Cookiebot consent banner template is known as "Swift" and is customisable in various ways, both by banner type e.g. bar vs dialog/modal, colour scheme and consent properties. A WCAG scan with the tool pa11y of a website using the dialog Cookiebot Swift banner template highlights the areas of WCAG non-compliance related to the HTML structure of the banner.

 Error: This button element does not have a name available to an accessibility API. Valid names are: title undefined, element content, aria-label undefined, aria-labelledby undefined.
   ├── WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.Button.Name
   ├── #CybotCookiebotDialogHeader > button
   └── <button class="CybotCookiebotBannerCloseButton" aria-label=""><svg xmlns="http://www.w3.org/2...</button>
 
Error: This form does not contain a submit button, which creates issues for those who cannot submit the form using the keyboard. Submit buttons are INPUT elements with type attribute "submit" or "image", or BUTTON elements with type "submit" or omitted/invalid.
   ├── WCAG2AA.Principle3.Guideline3_2.3_2_2.H32.2
   ├── #CybotCookiebotDialogBodyLevelButtonsSelectPane > form
   └── <form><fieldset><legend class="visual...</form>
 
Error: This form does not contain a submit button, which creates issues for those who cannot submit the form using the keyboard. Submit buttons are INPUT elements with type attribute "submit" or "image", or BUTTON elements with type "submit" or omitted/invalid.
   ├── WCAG2AA.Principle3.Guideline3_2.3_2_2.H32.2
   ├── #CybotCookiebotDialogDetailBodyContentCookieContainerNecessaryCard > div:nth-child(1) > div > form
   └── <form><input type="checkbox" id="Cybo...</form>
 
Error: This form does not contain a submit button, which creates issues for those who cannot submit the form using the keyboard. Submit buttons are INPUT elements with type attribute "submit" or "image", or BUTTON elements with type "submit" or omitted/invalid.
   ├── WCAG2AA.Principle3.Guideline3_2.3_2_2.H32.2
   ├── #CybotCookiebotDialogDetailBodyContentCookieContainerPreferenceCard > div:nth-child(1) > div > form
   └── <form><input type="checkbox" id="Cybo...</form>
 
Error: This form does not contain a submit button, which creates issues for those who cannot submit the form using the keyboard. Submit buttons are INPUT elements with type attribute "submit" or "image", or BUTTON elements with type "submit" or omitted/invalid.
   ├── WCAG2AA.Principle3.Guideline3_2.3_2_2.H32.2
   ├── #CybotCookiebotDialogDetailBodyContentCookieContainerStatisticsCard > div:nth-child(1) > div > form
   └── <form><input type="checkbox" id="Cybo...</form>
 
Error: This form does not contain a submit button, which creates issues for those who cannot submit the form using the keyboard. Submit buttons are INPUT elements with type attribute "submit" or "image", or BUTTON elements with type "submit" or omitted/invalid.
   ├── WCAG2AA.Principle3.Guideline3_2.3_2_2.H32.2
   ├── #CybotCookiebotDialogDetailBodyContentCookieContainerAdvertisingCard > div:nth-child(1) > div > form
   └── <form><input type="checkbox" id="Cybo...</form>
 
Error: This form does not contain a submit button, which creates issues for those who cannot submit the form using the keyboard. Submit buttons are INPUT elements with type attribute "submit" or "image", or BUTTON elements with type "submit" or omitted/invalid.
   ├── WCAG2AA.Principle3.Guideline3_2.3_2_2.H32.2
   ├── #CybotCookiebotDialogBodyButtons > div:nth-child(1) > form
   └── <form class="CybotCookiebotDialogBodyLevelButtonSliderWrapper"><input type="checkbox" id="Cybo...</form>
 
Error: This button element does not have a name available to an accessibility API. Valid names are: title undefined, element content, aria-label undefined, aria-labelledby undefined.
   ├── WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.Button.Name
   ├── #CybotCookiebotBannerCloseButtonE2E
   └── <button id="CybotCookiebotBannerCloseButtonE2E" class="CybotCookiebotBannerCloseButton" aria-label=""><svg xmlns="http://www.w3.org/2...</button>
 

While there are multiple errors, there are actually just two areas of WCAG success criterion flagged:

  1. WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.Button.Name
  2. WCAG2AA.Principle3.Guideline3_2.3_2_2.H32.2

WCAG 2.0 Success Criterion 4.1.2: Name, Role, Value

Two errors are related to the close button on the Cookiebot banner, this is an optional setting which can be customised to be visible or not, but regardless of this setting it will appear in the banner markup even if display: none; is set. The button itself uses an SVG icon for a close button but does not have any text label to describe the button and what it does. What is odd however, there is an aria-label property on the close button currently, but it is empty, which is very strange to go as far as adding ARIA properties but not actually implement them properly.

WCAG 2.0 Success Criterion 3.2.2: On Input

The remaining errors are related to forms. Depending on the type of consent banner being used, you can use a consent mode where each category of "Necessary" "Preferences", "Statistics" and "Marketing" is available as individual options to tick or untick, compared to the Allow All or Deny All approach. Necessary would always be default as on/checked whereas the others are considered optional through consent. The problem with this mode specifically is the form controls do not have a submit button, which is a potential issue for keyboard only navigation, making interacting with the form elements confusing.

Mitigation/modifications

The markup of the default Swift banner is not directly able to be modified, but there is a potential option to use the Cookiebot SDK to hook into events to make modifications, specifically using callbacks.

The CookiebotCallback_OnDialogDisplay callback is raised when the Cookiebot consent banner is displayed to the user. This gives us an opportunity to add a JavaScript event listener to hook into when this happens. As we are going to be modifying the HTML markup we need to have reliable point to execute such code to ensure the banner exists in the DOM.

window.addEventListener('CookiebotOnDialogDisplay', function (e) {
    // JavaScript code to execute
}, false);

The following is suitable for the dialog type banner but can be adapted to others.

Tackling the first problem of lack of meaningful text label on close buttons we can query the CSS class .CybotCookiebotBannerCloseButton

document.querySelectorAll('.CybotCookiebotBannerCloseButton').forEach(element => {
    element.setAttribute('aria-label', 'Close');
});

This will add a meaningful label to any close button present in the accessibility tree.

Depending on the type of consent banner being used if you aren't using individual consent categories, you can safely remove the hidden form elements (toggle switchhes), as they are not used and could cause confusion to screen readers or keyboard only navigation. These are contained in wrappers which can be removed entirely, rather than just targeting form elements.

document.querySelectorAll('.CybotCookiebotDialogBodyLevelButtonSliderWrapper').forEach(element => {
    element.remove();
});

Finally, another wrapper needs to be removed which contains a form without any submit button.


const cookiebotBottomWrapper = document.querySelector('.CybotCookiebotDialogBodyBottomWrapper');
if (cookiebotBottomWrapper) {
    cookiebotBottomWrapper.remove();
}

Putting it all together we have:

window.addEventListener('CookiebotOnDialogDisplay', function (e) {
    // Set aria-label on close buttons
    document.querySelectorAll('.CybotCookiebotBannerCloseButton').forEach(element => {
        element.setAttribute('aria-label', 'Close');
    });
    // Remove invalid form elements
    document.querySelectorAll('.CybotCookiebotDialogBodyLevelButtonSliderWrapper').forEach(element => {
       element.remove();
    });
    // Remove bottom wrapper with invalid form elements
    const cookiebotBottomWrapper = document.querySelector('.CybotCookiebotDialogBodyBottomWrapper');
    if (cookiebotBottomWrapper) {
        cookiebotBottomWrapper.remove();
    }
}, false);

The event listener ensures this code runs when the cookie dialog is being shown, if it is not visible or hasn't initialised then this code won't run, which is what we want as timing is crucial. This should be executed in your main JS file e.g. if using a bundler like Vite your main entry point JS file.

Custom templates

There is another more robust solution, but it means you'll need to write the HTML, CSS and JavaScript for your cookie banner all on your own, which when picking a cookie consent platform is probably not what you intend to do, given most of these platforms also charge a premium. Cookiebot offers the custom template option which allows you to control all the markup, styling and JavaScript functionality, but the documentation is pretty lacking with very little fully working examples available (that aren't behind some outrageous reseller pricing). I came across an accessible template and the original author has gone to great lengths to make something more accessible, but the problem the code is several years old and there have been various Cookiebot changes with the various HTML placeholders and naming conventions to update.

It is possible to extract the Swift template HTML and CSS contents through sniffing the network requests of a website using the Cookiebot template. The uc.js request from consent.cookiebot.com injects the template into your website and a <style> block with the ID of CookiebotWidgetStylesheet, providing the CSS. The JavaScript implementation however is less easy to extract to use, custom templates define show and hide JavaScript functions which you must implement, along with any other JavaScript functions required.

The other problem with custom templates is they are very difficult to test without saving changes to a domain group. The preview process does not really exist for custom templates unlike the prebuilt banner. The code for any custom template is also managed in the Cookiebot admin panel, making it very difficult for maintain or track changes given the lack of source control. There is also the additional requirement of validating and testing your cookie consent banner regularly in the event upstream changes to HTML placeholders occur, which requires updates to the markup.

This solution is obviously for developers only, but even as a developer myself, it seems very complex and potentially adding significant maintain burden when you often implement a CMP to avoid having to implement a lot of this yourself.

Accessibility is important

I have had several conversations about WCAG areas of the Cookiebot consent banner template to the Cookiebot support team. While they do acknowledge they are aware of WCAG issues related to their banner template, it is important for any customer or even user of website which uses Cookiebot to highlight the importance of accessibility. I have personally seen several accessibility statements of public sector bodies actively highlighting accessibility problems for their website specifically because of Cookiebot. While the mitigation examples can help improve things, it is certainly not the best fix and ideally should be implemented by Cookiebot themselves so all can benefit from such an implementation.

The mitigation examples above allow for better WCAG compliance but can only go as far as modify what is existing, completely refactoring or changing the core markup is really only possible with Cookiebot themselves making changes or custom templates and even that option has some shortcomings as well.