diff --git a/core/lib/bodl/bodl.ts b/core/lib/bodl/bodl.ts index 8eb143419..b47f6ccfe 100644 --- a/core/lib/bodl/bodl.ts +++ b/core/lib/bodl/bodl.ts @@ -26,6 +26,10 @@ export class Bodl { readonly cart = this.getCartEvents(); readonly navigation = this.getNavigationEvents(); + private readonly bodlScriptId = 'bodl-events-script'; + private readonly dataLayerScriptId = 'data-layer-script'; + private readonly gtagScriptId = 'gtag-script'; + constructor(private config: BodlConfig) { if (Bodl.#instance) { return Bodl.#instance; @@ -58,7 +62,16 @@ export class Bodl { throw new Error('Bodl is only available in the browser environment'); } - this.bindJavascriptLibrary(); + this.initializeBodlEvents(); + this.initializeDataLayer(); + this.initializeGTM(); + + Bodl.waitForBodlEvents(() => { + subscribeOnBodlEvents( + this.config.googleAnalytics.id, + this.config.googleAnalytics.consentModeEnabled, + ); + }); } catch (error) { // eslint-disable-next-line no-console console.warn(error); @@ -75,26 +88,60 @@ export class Bodl { } } - private bindJavascriptLibrary() { - // Subscribe analytic providers to BODL events here - const load = () => { - subscribeOnBodlEvents( - this.config.googleAnalytics.id, - this.config.googleAnalytics.developerId, - this.config.googleAnalytics.consentModeEnabled, - ); - }; + private initializeBodlEvents() { + const existingScript = document.getElementById(this.bodlScriptId); - const el = document.getElementsByTagName('body')[0]; - - if (!el) return; + if (existingScript) { + return; + } const script = document.createElement('script'); + script.id = this.bodlScriptId; script.type = 'text/javascript'; script.src = 'https://microapps.bigcommerce.com/bodl-events/index.js'; - script.onload = load; - el.appendChild(script); + + document.body.appendChild(script); + } + + private initializeDataLayer() { + const existingScript = document.getElementById(this.dataLayerScriptId); + + if (existingScript) { + return; + } + + const script = document.createElement('script'); + + script.id = this.dataLayerScriptId; + script.type = 'text/javascript'; + script.innerHTML = ` + window.dataLayer = window.dataLayer || []; + function gtag() { + dataLayer.push(arguments); + } + gtag('js', new Date()); + gtag('set', 'developer_id.${this.config.googleAnalytics.developerId}', true); + gtag('config', '${this.config.googleAnalytics.id}'); + `; + + document.body.appendChild(script); + } + + private initializeGTM() { + const existingScript = document.getElementById(this.gtagScriptId); + + if (existingScript) { + return; + } + + const script = document.createElement('script'); + + script.id = this.gtagScriptId; + script.src = `https://www.googletagmanager.com/gtag/js?id=${this.config.googleAnalytics.id}`; + script.async = true; + + document.head.appendChild(script); } private getCartEvents() { diff --git a/core/lib/bodl/providers/ga4/google_analytics4.js b/core/lib/bodl/providers/ga4/google_analytics4.js index 9b35fef26..069fe6e43 100644 --- a/core/lib/bodl/providers/ga4/google_analytics4.js +++ b/core/lib/bodl/providers/ga4/google_analytics4.js @@ -1,14 +1,8 @@ -export function subscribeOnBodlEvents(measurementId, developerId, consentModeEnabled) { - window.dataLayer = window.dataLayer || []; - +export function subscribeOnBodlEvents(measurementId, consentModeEnabled) { if (!window || typeof window.bodlEvents === 'undefined') { return; } - function gtag() { - dataLayer.push(arguments); - } - function addDestination(payload) { return Object.assign({}, payload, { send_to: measurementId }); } @@ -360,26 +354,6 @@ export function subscribeOnBodlEvents(measurementId, developerId, consentModeEna subscribeOnConsentEvents(); } - function setupGtag() { - function configureGtag() { - gtag('js', new Date()); - gtag('set', 'developer_id.' + developerId, true); - gtag('config', measurementId); - } - - function addGtagScript() { - var script = document.createElement('script'); - - script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`; - script.async = true; - - document.head.appendChild(script); - } - - addGtagScript(); - configureGtag(); - } - function subscribeOnEcommerceEvents() { subscribeOnCheckoutEvents(); subscribeOnCartEvents(); @@ -388,6 +362,5 @@ export function subscribeOnBodlEvents(measurementId, developerId, consentModeEna } setupConsent(); - setupGtag(); subscribeOnEcommerceEvents(); }