UNPKG

@primarix/easy-consent

Version:

A lightweight consent management solution for Google Analytics and related services. This is a beta version and should be used with caution.

212 lines (164 loc) 6.71 kB
import { type Mode, type Options, Config, type ConsentEventKey, type ConsentEventMode, ConsentUpdateEventDetail, ConsentUpdateEvent, type PartialConfig } from "./types"; declare global { interface Window { dataLayer: any[]; gtag: (...args: any[]) => void; } } declare global { interface WindowEventMap { 'consent-updated': ConsentUpdateEvent; } } export class EasyConsent { public isNewUser:boolean public state:Config; private head:HTMLElement private analytics_lib:HTMLElement private init_consent:HTMLElement private init_GA:HTMLElement private consentConfigDuration = 180; private getCookie(name: string) { const cookies = document.cookie.split("; "); for (let cookie of cookies) { const [key, value] = cookie.split("="); if (key === name) { try { return JSON.parse(decodeURIComponent(value)); } catch (error) { console.error("Error al parsear el contenido de la cookie:", error); return null; } } } return null; } private setCookie(name: string, value: Config, days: number) { const jsonValue = JSON.stringify(value); const encodedValue = encodeURIComponent(jsonValue); const expires = days ? "; expires=" + new Date(Date.now() + days * 864e5).toUTCString() : ""; document.cookie = `${name}=${encodedValue}${expires}; path=/; SameSite=Lax; Secure`; } constructor (private id:string){ const config = this.getCookie("consentConfig") if(config){ this.state = config; this.isNewUser = false; } else{ this.isNewUser = true; this.state = { 'ad_storage': 'denied', 'analytics_storage': 'denied', 'functionality_storage': 'denied', 'personalization_storage': 'denied', 'ad_user_data':'denied', 'ad_personalization': 'denied', 'security_storage': 'denied' } this.setCookie("consentConfig", this.state , this.consentConfigDuration) } this.head = document.head; this.analytics_lib = document.createElement("script"); this.init_consent = document.createElement("script"); this.init_GA = document.createElement("script"); this.analytics_lib.setAttribute("src",`https://www.googletagmanager.com/gtag/js?id=${this.id}`); this.analytics_lib.setAttribute("async", "true"); this.init_consent.setAttribute("data-cookieconsent", "ignore") this.init_consent.textContent = ` window.dataLayer = window.dataLayer || []; function gtag(){ dataLayer.push(arguments); } gtag('consent', 'default', ${JSON.stringify(this.state)}); gtag('set', 'ads_data_redaction', true); gtag('set', 'url_passthrough', true); ` this.init_GA.textContent = ` gtag('js', new Date()); gtag('config', '${this.id}', { send_page_view: false }); ` this.head.appendChild(this.init_consent); this.analytics_lib.onload = () => { this.head.appendChild(this.init_GA); }; this.head.appendChild(this.analytics_lib); } private pageView(){ if (this.state.analytics_storage === 'granted') { window.gtag('event', 'page_view', { page_path: window.location.pathname, page_title: document.title, }); } } private dispatchCustomEvent(key:ConsentEventKey,mode:ConsentEventMode){ const event = new CustomEvent<ConsentUpdateEventDetail>('consent-updated', { detail: { key, mode, state: this.state, timestamp: Date.now().toString()} }); window.dispatchEvent(event); } update(key:Options, mode:Mode){ if(!window.dataLayer) throw new Error("The gtag function is not defined"); this.state = {...this.state, [key]: mode} this.setCookie("consentConfig", this.state ,this.consentConfigDuration) window.gtag("consent", "update", { [key]: mode }); this.pageView(); this.dispatchCustomEvent(key,mode); } acceptAll() { try { if (!window.dataLayer) throw new Error("The gtag function is not defined"); const v1 = Object.keys(this.state) as Options[]; const v2 = v1.map((key) => [key ,"granted"]) this.state = Object.fromEntries(v2) as Config; window.gtag("consent", "update", this.state); this.setCookie("consentConfig", this.state, this.consentConfigDuration) this.pageView(); this.dispatchCustomEvent("all","accept-all"); } catch (error) { console.error("Error in acceptAll:", error); } } rejectAll(){ try{ if(!window.dataLayer) throw new Error("The gtag function is not defined"); const v1 = Object.keys(this.state) as Options[]; const v2 = v1.map((key) => [key ,"denied"]) this.state = Object.fromEntries(v2) as Config; window.gtag("consent", "update", this.state); this.setCookie("consentConfig", this.state ,this.consentConfigDuration) this.dispatchCustomEvent("all","reject-all"); } catch(error){ console.error("Error in rejectAll:", error) } } isAllConsented(): boolean { return Object.values(this.state).every(value => value === 'granted'); } isAllDenied(): boolean { return Object.values(this.state).every(value => value === 'denied'); } updateMultiple(new_state:PartialConfig){ try{ this.state = {...this.state,...new_state} window.gtag("consent", "update", new_state); this.setCookie("consentConfig", this.state ,this.consentConfigDuration) Object.entries(new_state).forEach(([key, mode]) => { this.dispatchCustomEvent(key as Options, mode as Mode); }); this.pageView(); } catch(error){ console.error("Error in updateMultiple:", error) } } }