Cookiebot breaks requirejs implementation
TL;DR;
As soon as i add cookiebot to a website, that uses requirejs to load javascript modules, everything breaks randomly.
More Details:
I found this post, that pretty much describes the same problem but could not solve it so far:
my stack looks like:
<!-- head -->
<script id="Cookiebot" src="https://consent.cookiebot.com/uc.js" data-cbid="hidden" data-blockingmode="auto" type="text/javascript"></script>
<script src="/path/to/requirejs.js" data-cookieconsent="ignore" type="text/javascript"></script>
<script src="/path/to/require_config.js" data-cookieconsent="ignore" type="text/javascript"></script>
<script type="text/javascript">
requirejs.config({
"onNodeCreated": function(node, config, name, url) {
node.setAttribute("data-cookieconsent", "ignore");
}
});
</script>
<!--arbitrary markup in document body-->
<!--Some invokation at end of body-->
<script type="text/javascript">
requirejs(["text!/abs/path/to/icons.svg", "core"], function(svgSprite, core) {
core.init(svgSprite);
});
</script>
The console reports various errors and the app does not work:
Uncaught Error: Mismatched anonymous define() module: function (module) {
Uncaught TypeError: plugin.load is not a function
Load timeout for modules: text!/path/to/icons.svg?v=1196d510276e85bc2246bdd166abc86b_unnormalized2,core,lazy-images,text!/path/to/icons.svg?v=1196d510276e85bc2246bdd166abc86b
Whats the problem here? Can you simply NOT fuck around with _LOCAL_ scripts being loaded?
-
So it seems this happens because of the text! plugin. If i remove the text plugin call, the app is working as expected.
If i change my invokation to the following it works:
<script type="text/javascript"> (function(){ function init(svgSprite) { requirejs(["core"], core => { core.init(svgSprite); }); } fetch('/abs/path/to/icons.svg').then(response => { if (response.ok) { response.text().then(init); } else { console.error(response.statusText); init(""); } }).catch(error => { console.error(error); init(""); }); }()); </script>
I tried to fix this inside requirejs.js but had no success doing so.
0 -
Okay no, that solved some problem but not all, of them. On certain other pages where i load different modules i still get errors that only occur once cookiebot is added to the page (no issue without cookiebot).
So cookiebot breaks requirejs/amd is the simple truth i fear - thus being a very bad option for other projects.
But honestly - i dont get it. Looking at the source it does not seem, that cookiebot overrides the define/requirejs methods. So i suspect cookiebot simply ignores data-cookieconsent="ignore" if a node is attached later on. The observer does not take this into account.
If i add the following hook i can avoid a bug but it does not seem safe to do this, because its no api:
UPDATE
I made a stupid mistake and tested a wrong instance of my app where cookiebot is disabled - this hack does not work i fear.
requirejs.config({
"onNodeCreated": function(node, config, name, url) {
node["consentProcessed"] = "1";
node.setAttribute("data-cookieconsent", "ignore");
}
});So we might be able to identify the problem as cookiebot bug and call it "Cookiebot does not take data-cookieconsent into account, when processing a node in its MutationObserver"
0 -
So it seems this happens because of the text! plugin. If i remove the text plugin call, the app is working as expected.
0 -
My initial problem was, that the dev-domain i use locally was not registered in the cookiebot admin tool. After we did this, it seemed to work. But i always tested with "accept all cookies". Once i tested with "Only mandatory" cookies, it did stop to work! So i tried "mandatory" as data-cookieconsent attribute but it did not work either.
But the reply (i wrote this myself a few days before your reply) still works. Avoiding the text! plugin makes the app work again. So this persists to be a cookiebot issue i guess.
The optimized call to avoid chained loading looks like:
(function(){
function init() {
Promise.all([
fetch('/abs/path/to/icons.svg'),
new Promise(resolve => {
requirejs(['core'], core => {
resolve(core);
});
})
]).catch(console.error /* or some errorLogger */).then(results => {
results[0].text().then(svgSprite => {
results[1].init(svgSprite);
});
});
}
if (document.querySelector('script#Cookiebot')) {
window.addEventListener('CookiebotOnConsentReady', init);
} else {
init();
}
}());0 -
And still the page-load where the user initially accepts "mandatory cookies" will fail due to a "Load timeout". Once you refresh the page, it sometimes works. But this is in no way acceptable. It does not even work, if i force a reload with a weird construct like this:
// need to use this event because "CookiebotOnDecline" is fired on every pagehit
window.addEventListener('CookiebotOnDialogDisplay', () => {
window.addEventListener('CookiebotOnDecline', () => {
location.reload();
});
window.addEventListener('CookiebotOnAccept', () => {
init();
});
});
if (Cookiebot && Cookiebot.hasResponse) {
init();
}The user NEEDS to make a reload of the page (ctrl+r) to invalidate some cache i guess. And even then it does not work reliable! Sometimes it will just throw various random errors due to unresolved modules.
This behaviour is absolutely unacceptable, i will highly dissuade my customers from using cookiebot in the future ever again.
Even though i attribute all scripts-tags as "mandatory" or "ignore" (via the data-cookieconsent attribute) the whole app wont work correctly if i dont accept _ALL_ cookies.
AMD/requirejs is an older standard, but it certainly IS a standard and besides systemjs one of the few available modular depdency systems out there.
0 -
Hello,
working for me (even using text! plugin):
1) don't use cookiebot automatic blocking mode (remove data-blockingmode="auto" attribute)
<script id="Cookiebot" src="https://consent.cookiebot.com/uc.js" data-cbid="00000000-0000-0000-0000-000000000000" type="text/javascript" async></script>
2) add data-cookieconsent="ignore" attribute to all scripts that cookiebot should ignore (including requirejs)
<script async data-cookieconsent="ignore" src="require.js?bust=14012019" data-main="/app"></script>
<script data-cookieconsent="ignore" src="yourscript.js"></script>3) Mark the script tags you want cookiebot to block cookies (marketing, statistics, preferences):
- add type="text/plain" attribute (be careful, not type="text/javascript")
- add data-cookieconsent="marketing" or data-cookieconsent="statistics" or data-cookieconsent="preferences"
- example for Google Analytics:<script type="text/plain" data-cookieconsent="statistics">
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-xxxxxxx-xx', 'auto');
ga('send', 'pageview');
</script>More infos: https://www.cookiebot.com/en/manual-implementation/
0
Please sign in to leave a comment.
Comments
6 comments