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

Created on 30 October 2019, over 5 years ago
Updated 27 March 2023, almost 2 years 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

Merge Requests

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.

  • 🇬🇧United Kingdom John Cook

    I've tested the patch in #58 🐛 Blockmode "Auto" will not work in Drupal 8 with core's domready library Needs work and it works as expected.

    I've check the patch and it doesn't appear that @dmsmidt's points in #43 🐛 Blockmode "Auto" will not work in Drupal 8 with core's domready library Needs work have been addressed. This will need to be done before this can proceed further.

  • 🇳🇱Netherlands tim_dj Netherlands

    This patch addresses the following from #43:

    Did you write es6 first and than transpiled? Doesn't look like you did.

    I've removed the non-es6 javascript. This is no longer required since D10: https://www.drupal.org/node/3305487

    You should never call jQuery directly like this. Use the scoped version from the self invoking function $.

    Using $(function() { now

    This is not confirm coding standards.

    Updated the referenced lines

    This should be drupalSettings right?

    Removed using drupalSettings completely in this function call since attachBehaviours() defaults to drupalSettings if no settings variable is provided.

    I did add core/drupalSettings to dependencies because that was missing and drupalSettings are used elsewhere in this js

    so if autoblocking is off, this still gets set to 'true', while it is not true.

    Renamed the function to provide better insight in what it does. It does not seem to depend on autoblockingmode.

  • 🇳🇱Netherlands tim_dj Netherlands
  • 🇳🇱Netherlands basvredeling Amsterdam

    patch looks good

  • 🇧🇪Belgium BramDriesen Belgium 🇧🇪

    Let's make an issue fork as it's easier to work on and review.

  • 🇨🇿Czech Republic myst1c

    Patch #60 looks good to me.

  • 🇳🇱Netherlands tim_dj Netherlands

    @bramdriesen Created MR. This MR is the same as patch in #60

  • Pipeline finished with Success
    1 day ago
    Total: 147s
    #436808
Production build 0.71.5 2024