Skip to content

How to introduce cookies

First, we need to determine which cookie provider we will be using, and we will make a file similar to this one (made for CookieBot) where we can control the consent given by the user:

js/modules/utilities/handleCookiesConsent.js
export function handleCookiesConsent(emitter, debug) {
const processConsent = () => {
try {
if (typeof Cookiebot !== "undefined" && Cookiebot.consented) {
emitter.emit("cookies:consentGiven");
}
} catch (e) {
debug && console.warn("Cookiebot consent processing failed:", e);
}
};
// Execute if it exists
if (typeof Cookiebot !== "undefined") {
processConsent();
}
// Wait for the event
window.addEventListener("CookiebotOnConsentReady", processConsent);
}
export function isCookieConsentGranted() {
return typeof Cookiebot !== "undefined" && Cookiebot.consented === true;
}

This file will vary depending on the type of cookie provider we are using.

The important thing is that the file emits an event cookies:consentGiven that we will use in our handler to execute actions.

It is also important to have a method that we can call throughout the application to know if the consent is present.

We need to execute this as soon as the project is initialized, so we will do it on our Project.js class:

Project.js
async init() {
try {
this.boostify.onload({
maxTime: 2400,
callback: async () => {
// This handles consent given to cookies
handleCookiesConsent(this.emitter, this.terraDebug);
},
});
//...other code
}}

This will check consent right as we enter the page and, as we have an event listener in the handler, will know when the user has hit the β€˜Accept cookies’ button.

Once the user has given consent, we are going to control every action we execute depending on this consent from a handler.

In our case, we are using the cookies to display hubspot forms and a chatbot.

js/handler/cookies/Handler.js
class Handler extends CoreHandler {
constructor(payload) {
super(payload);
this.init();
this.events();
this.hubspotFooterLoaded = false;
this.hubspotTransitionLoaded = false;
this.config = {
boostify: this.boostify,
className: "js--chat-a",
scriptCode: `
window.intercomSettings = {
api_base: "https://api-iam.intercom.io",
app_id: "wcgicak1",
};
`,
secondScriptCode: `(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic("reattach_activator");ic("update",w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Intercom=i;var l=function(){var s=d.createElement("script");s.type="text/javascript";s.async=true;s.src="https://widget.intercom.io/widget/wcgicak1";var x=d.getElementsByTagName("script")[0];x.parentNode.insertBefore(s,x);};if(document.readyState==="complete"){l();}else if(w.attachEvent){w.attachEvent("onload",l);}else{w.addEventListener("load",l,false);}}})();`,
thirdScriptCode: ` setTimeout(() => { window.Intercom("show");}, 1000);`,
};
}
get updateTheDOM() {
return {
hubspotChecker: document.querySelectorAll(".js--hubspot-script"),
hubspotFooterChecker: document.querySelectorAll(".js--hubspot-script--footer"),
};
}
init() {}
//...other code
}

This first part of the handler contains the usual information for any of our handlers:

  • Extends CoreHandler - in this case we are using this only to pass the payload, but we are not using its assignInstances method
  • We have a couple flags we will use to ensure hubspot is not loaded more than once
  • We have the configuration for the chatbot, that we will later use
  • We have an updateTheDOM method that searches for our hubspot elements
async loadScripts({ element, id }) {
try {
await this.boostify.loadScript({
url: "https://js.hsforms.net/forms/v2.js",
});
await this.boostify.loadScript({
inlineScript: `
hbspt.forms.create({
region: "na1",
portalId: "${element.getAttribute("data-portal-id")}",
formId: "${element.getAttribute("data-form-id")}"
});`,
appendTo: element,
attributes: [`id=${id}`],
});
} catch (e) {
this.terraDebug && console.error("Error loading HubSpot script: ", error);
}
}

We will also be using here a helper function to load the hubspot scripts, where we only change the ID

And the most important part of our handler, our events.

As we used an event in our handleCookiesConsent file, we need to listen for that event here to know when the user has consented and be able to inject the hubspot scripts:

this.emitter.on("cookies:consentGiven", async () => {
this.DOM = this.updateTheDOM;
if (this.DOM.hubspotChecker.length) {
if (!this.hubspotTransitionLoaded) {
this.DOM.hubspotChecker.forEach(async (element) => {
await this.loadScripts({ element, id: "general-hubspot" });
});
}
}
if (this.DOM.hubspotFooterChecker.length) {
this.DOM.hubspotFooterChecker.forEach(async (element) => {
if (!this.hubspotFooterLoaded) {
this.boostify.observer({
options: {
root: null,
rootMargin: "0px",
threshold: 0.5,
},
element: element,
callback: async () => {
if (!this.hubspotFooterLoaded) {
this.hubspotFooterLoaded = true;
await this.loadScripts({ element, id: "footer-hubspot" });
modifyTag({
element: element.children[0],
attributes: {
"data-swup-ignore-script": "",
},
delay: 250,
});
}
},
});
}
});
}
const { checkChatBot } = await import("@js/motion/transition/utilities");
checkChatBot(this.config);
});

This piece of code:

  • Updates the DOM to check for hubspot elements
  • If it has main hubspot elements and the flag is false (meaning that the scripts have not yet been loaded) - it loads the hubspot script
  • If it has footer hubspot elements and the flag is false - it adds an observer so when the user reaches the footer, the hubspot script is loaded
  • It imports the chatbot and initializes it using the configuration from the constructor
this.emitter.on("MitterContentReplaced", async () => {
const canUseHubspot = isCookieConsentGranted();
this.DOM = this.updateTheDOM;
if (this.DOM.hubspotChecker.length && canUseHubspot) {
this.hubspotTransitionLoaded = true;
this.DOM.hubspotChecker.forEach(async (element) => {
await this.loadScripts({ element, id: "general-hubspot" });
});
}
if (this.DOM.hubspotFooterChecker.length && canUseHubspot) {
this.DOM.hubspotFooterChecker.forEach(async (element) => {
this.boostify.observer({
options: {
root: null,
rootMargin: "0px",
threshold: 0.5,
},
element: element,
callback: async () => {
if (!this.hubspotFooterLoaded) {
console.log("SUBSTITUTING IN CONTENT REPLACED");
this.hubspotFooterLoaded = true;
await this.loadScripts({ element, id: "footer-hubspot" });
modifyTag({
element: element.children[0],
attributes: {
"data-swup-ignore-script": "",
},
delay: 250,
});
}
},
});
});
}
});

When entering the new page, we check for our hubspot elements in the DOM and we check the cookie consent using the isCookieConsentGranted() method from our handleCookiesConsent file.

The chatbot is a bit different, because we need to load it into the animation of the transition for it to work properly, so instead of here we will have it:

  1. In our Project.js file, after our handlers have loaded.
Project.js
if (tl.progress() >= 0.5 && !this.halfwayExecuted) {
this.halfwayExecuted = true;
const { default: Main } = await import("@js/Main.js");
new Main({
boostify: this.boostify,
terraDebug: this.terraDebug,
Manager: this.Manager,
emitter: this.emitter,
});
// This event is listened to in the cookies handler to introduce the chatbot script
this.emitter.emit("animation:loadChatBot");
}
  1. In our transition/index.js, when we start our animation.
js/motion/transition/index.js
var tl = gsap.timeline({
onStart: async () => {
// This event is listened to in the cookies handler to introduce the chatbot script
emitter.emit("animation:loadChatBot");
},
});
  1. And in our handler, listening to this event, we will check if we have our user consent and then load the bot.
this.emitter.on("animation:loadChatBot", async () => {
if (isCookieConsentGranted()) {
const { checkChatBot } = await import("@js/motion/transition/utilities");
checkChatBot(this.config);
}
});

We need:

  • A file to interact with our cookie provider of preference - handleCookiesConsent.js
    • This is executed in Project.js init() method inside our boostify.onload()
  • A handler to execute actions on consent given
  • OPTIONAL: If we have a chatbot, execute it according to cookie consent and load it:
    • In our Project.js after our handlers have executed
    • In our transition/index.js in the onStart callback of our animation

Knowledge Check

Test your understanding of this section

Loading questions...