Blockmode "Auto" will not work in Drupal 8 with core's domready library

Created on 30 October 2019, about 5 years ago
Updated 3 September 2024, 3 months ago

I just invested serveral hours in digging deep into the structures how Cookiebots auto-blocking works and why Drupal 8 scripts are not working correctly in combination with it.

Today there isn't much time left for this topic, so I'll try to sum up what's the problem and what may be our workaround. Finally we should further investigate if there are safe ways to fix this (perhaps with the Cookiebot team, because they would also have a huge benefit for their script for non jQuery environments) or live with that workaround and harden it for edge-cases.

Context

Using Cookiebot in Drupal 8 with data-blockingmode="auto" (https://www.cookiebot.com/en/automatic-cookie-control/) which is very helpful in general. Also see #3090518: Make blocking mode configurable for a switch for the blockingmode.

Drupal 7 uses regular jQuery document.ready() so this problem will not exist here.

Problem / TLDR:

Due to #1974580: Introduce domReady to remove jQuery dependency from drupal.js and clean it up. Drupal 8 uses https://github.com/ded/domready instad of jQuery document.ready() while Cookiebot relies on https://api.jquery.com/jQuery.holdReady to trigger Script execution after everything has been loaded (it postpones the regular event, until all external scripts have been handled, which is very clever).

In core/misc/drupal.init.js you can find this code:

(function (domready, Drupal, drupalSettings) {
  domready(function () {
    Drupal.attachBehaviors(document, drupalSettings);
  });
})(domready, Drupal, window.drupalSettings);

Which in former times was jQuery, as described here: https://www.lullabot.com/articles/understanding-javascript-behaviors-in-...

Because the jQuery.holdReady(0) from cookiebot has no effect on this, Drupal.attachBehaviors(document, drupalSettings); already runs to early, when no scripts have been loaded.
Perhaps we may even have race conditions here, which would be worse.

UPDATE: SEE https://www.drupal.org/node/3086669

Proposed solution:

We won't change core so I only see three possible solutions for us (best to worst):

  1. Instead of relying on jQuery, Cookiebot uses Vanilla JS which halts the the code behind jQuery AND vanilla solutions like the one in domready: https://github.com/ded/domready/blob/master/src/ready.js setting the readystate unready - All projects without jQuery would be fixed then!
  2. We find a safe way for this Drupal 8 module to ensure that domready() is only executed once AFTER Cookiebot did its job. It should then be bulletproof to also work if Cookiebot doesn't work or can't be loaded due to any reasons.
  3. We use the following workaround and HOPE that there are no side-effects or race conditions. I'd hope I could believe in that, but I can't yet...

Short version: Add the following code to cookiebot.js in this module:

jQuery(function () {
  Drupal.attachBehaviors(document, Drupal.settings);
});

which will be automatically called by the Cookiebot script after all scripts have been handled.

I'll create a long version with a variable to ensure it's only called once as patch.

Tasks

  • After #3090518: Make blocking mode configurable has been fixed: Only run the P-O-C code if autoblocking is enabled
  • Review & test if the fix works
  • Implement a clean solution based on the working code
  • Commit and create a new release

Sidenote:

Before I used

$window.on('CookiebotOnTagsExecuted', function () {}

instead, but I think that's less stable and may be called several times on several events (load, accept, ...)

Suggestions:

I guess we should encapsulate that workaround into
#3090518: Make blocking mode configurable to only be executed if block mode is set to "auto".

Thank you!

PS: Is anyone in contact with the Team from Cookiebot? They might have a look and help to find a clever JS solution!

🐛 Bug report
Status

Needs work

Version

1.0

Component

Code

Created by

🇩🇪Germany Anybody Porta Westfalica

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇧🇪Belgium jelle_s Antwerp, Belgium

    Straight reroll of #45

  • 🇦🇹Austria DrColossos

    Huge respect for finding the root of the problem! We got stuck at the same problem. The patch from #56 seems to solve the problem in a very nice way. This really should be pushed forward to be able to get into dev.

    BTW: Cookiebot should not rely on third-party libraries being available on the site. This seems like a huge design problem.

  • 🇬🇧United Kingdom SoulReceiver

    This patch works great, but when we use it we found that on every page request where the user has not yet approved or denied the use of cookies, the console was being filled with this error:

    Uncaught TypeError: Cannot read properties of undefined (reading 'get')

    Which relates to this line in the original JS:
    if (Cookiebot.consent[cookieName] === true && cookies.get('cookiebot-consent--' + cookieName) !== '1') {

    Seems when the attachBehaviours runs we do not have the derived cookies object from the window.Cookies. Played around with this and if adding this condition to the others seemingly solves the issue, and it doesn't seem to affect the functionality of when the cookies are either approved or denied in our current implementation:

    if (typeof Cookiebot === 'undefined' || Cookiebot.consent === void (0) || typeof cookies === 'undefined') {
      return;
    }
    

    Added the fix as a new patch, but would appreciate it if it could be more broadly tested.

Production build 0.71.5 2024