From 64f4e8555b67707d77b7c00584fb514f0da9869a Mon Sep 17 00:00:00 2001 From: Kshitij Sobti Date: Thu, 4 Jan 2024 09:59:49 +0530 Subject: [PATCH] feat: Add support for Google Tag Manger This change adds support for Google Tag Manager along with some common options for Google Tag Manager. --- src/initialize.js | 4 +- src/scripts/GoogleTagManagerLoader.js | 60 +++++++++++ src/scripts/GoogleTagManagerLoader.test.js | 117 +++++++++++++++++++++ src/scripts/index.js | 1 + 4 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 src/scripts/GoogleTagManagerLoader.js create mode 100644 src/scripts/GoogleTagManagerLoader.test.js diff --git a/src/initialize.js b/src/initialize.js index 2c7223595..a66fffce9 100644 --- a/src/initialize.js +++ b/src/initialize.js @@ -68,7 +68,7 @@ import { import { configure as configureAnalytics, SegmentAnalyticsService, identifyAnonymousUser, identifyAuthenticatedUser, } from './analytics'; -import { GoogleAnalyticsLoader } from './scripts'; +import { GoogleAnalyticsLoader, GoogleTagManagerLoader } from './scripts'; import { getAuthenticatedHttpClient, configure as configureAuth, @@ -290,7 +290,7 @@ export async function initialize({ analyticsService = SegmentAnalyticsService, authService = AxiosJwtAuthService, authMiddleware = [], - externalScripts = [GoogleAnalyticsLoader], + externalScripts = [GoogleAnalyticsLoader, GoogleTagManagerLoader], requireAuthenticatedUser: requireUser = false, hydrateAuthenticatedUser: hydrateUser = false, messages, diff --git a/src/scripts/GoogleTagManagerLoader.js b/src/scripts/GoogleTagManagerLoader.js new file mode 100644 index 000000000..139a187df --- /dev/null +++ b/src/scripts/GoogleTagManagerLoader.js @@ -0,0 +1,60 @@ +/** + * @implements {GoogleTagManagerLoader} + * @memberof module:GoogleTagManager + */ +class GoogleTagManagerLoader { + constructor({ config }) { + this.gtmId = config.GOOGLE_TAG_MANAGER_ID; + this.gtmArgs = ''; + if (config.GOOGLE_TAG_MANAGER_AUTH) { + this.gtmArgs += `>m_auth=${config.GOOGLE_TAG_MANAGER_AUTH}`; + } + if (config.GOOGLE_TAG_MANAGER_PREVIEW) { + this.gtmArgs += `>m_preview=${config.GOOGLE_TAG_MANAGER_PREVIEW}`; + } + if (config.GOOGLE_TAG_MANAGER_ADDNL_ARGS) { + if (!config.GOOGLE_TAG_MANAGER_ADDNL_ARGS.startsWith('&')) { + this.gtmArgs += '&'; + } + this.gtmArgs += config.GOOGLE_TAG_MANAGER_ADDNL_ARGS; + } + } + + loadScript() { + if (!this.gtmId) { + return; + } + + global.googleTagManager = global.googleTagManager || []; + const { googleTagManager } = global; + + // If the snippet was invoked do nothing. + if (googleTagManager.invoked) { + return; + } + + // Invoked flag, to make sure the snippet is never invoked twice. + googleTagManager.invoked = true; + + googleTagManager.load = (key, args, options) => { + const scriptSrc = document.createElement('script'); + scriptSrc.type = 'text/javascript'; + scriptSrc.async = true; + scriptSrc.innerHTML = ` + (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': + new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], + j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= + 'https://www.googletagmanager.com/gtm.js?id='+i+dl+'${args}';f.parentNode.insertBefore(j,f); + })(window,document,'script','dataLayer','${key}'); + `; + document.head.insertBefore(scriptSrc, document.head.getElementsByTagName('script')[0]); + + googleTagManager._loadOptions = options; // eslint-disable-line no-underscore-dangle + }; + + // Load GoogleTagManager with your key. + googleTagManager.load(this.gtmId, this.gtmArgs); + } +} + +export default GoogleTagManagerLoader; diff --git a/src/scripts/GoogleTagManagerLoader.test.js b/src/scripts/GoogleTagManagerLoader.test.js new file mode 100644 index 000000000..12022764c --- /dev/null +++ b/src/scripts/GoogleTagManagerLoader.test.js @@ -0,0 +1,117 @@ +import { GoogleTagManagerLoader } from './index'; + +const gtmId = 'test-key'; + +describe('GoogleTagManager', () => { + let gtmScriptId; + let firstScriptTag; + + beforeEach(() => { + window.googleTagManager = []; + document.head.innerHTML = 'Testing'; + document.body.innerHTML = '