diff --git a/scripts/index.js b/scripts/index.js deleted file mode 100644 index 73c5a4985..000000000 --- a/scripts/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default as TealiumLoader } from './TealiumLoader'; diff --git a/src/initialize.js b/src/initialize.js index 539e3e85d..438836585 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, TealiumLoader } from './scripts'; +import { GoogleAnalyticsLoader, ScriptInserter } from './scripts'; import { getAuthenticatedHttpClient, configure as configureAuth, @@ -290,7 +290,7 @@ export async function initialize({ analyticsService = SegmentAnalyticsService, authService = AxiosJwtAuthService, authMiddleware = [], - externalScripts = [GoogleAnalyticsLoader, TealiumLoader], + externalScripts = [GoogleAnalyticsLoader, ScriptInserter], requireAuthenticatedUser: requireUser = false, hydrateAuthenticatedUser: hydrateUser = false, messages, diff --git a/src/scripts/ScriptInserter.js b/src/scripts/ScriptInserter.js new file mode 100644 index 000000000..ca8bbcd7c --- /dev/null +++ b/src/scripts/ScriptInserter.js @@ -0,0 +1,77 @@ +/** + * Class representing a Script Inserter. + */ +class ScriptInserter { + /** + * Create a Script Inserter. + * @param {Array} scripts - An array of script objects to insert. + * @param {string} [scripts[].head] - The script to insert into the head section. + * @param {string} [scripts[].body.top] - The script to insert at the top of the body section. + * @param {string} [scripts[].body.bottom] - The script to insert at the bottom of the body section. + */ + constructor({ config }) { + this.scripts = config.EXTERNAL_SCRIPTS || []; + } + + /** + * Inserts the scripts into their respective locations (head, body start, body end). + */ + loadScript() { + if (!this.scripts.length) { + return; + } + + this.scripts.forEach((script) => { + if (script.head) { + this.insertToHead(script.head); + } + if (script.body?.top) { + this.insertToBodyTop(script.body.top); + } + if (script.body?.bottom) { + this.insertToBodyBottom(script.body.bottom); + } + }); + } + + /** + * Inserts content into the head section. + * @param {string} content - The content to insert into the head section. + */ + insertToHead(content) { + const { head } = document; + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = content; + while (tempDiv.firstChild) { + head.appendChild(tempDiv.firstChild); + } + } + + /** + * Inserts content at the start of the body section. + * @param {string} content - The content to insert at the top of the body section. + */ + insertToBodyTop(content) { + const { body } = document; + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = content; + while (tempDiv.firstChild) { + body.insertBefore(tempDiv.firstChild, body.firstChild); + } + } + + /** + * Inserts content at the end of the body section. + * @param {string} content - The content to insert at the bottom of the body section. + */ + insertToBodyBottom(content) { + const { body } = document; + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = content; + while (tempDiv.firstChild) { + body.appendChild(tempDiv.firstChild); + } + } +} + +export default ScriptInserter; diff --git a/src/scripts/ScriptInserter.test.js b/src/scripts/ScriptInserter.test.js new file mode 100644 index 000000000..e69de29bb diff --git a/src/scripts/TealiumLoader.js b/src/scripts/TealiumLoader.js deleted file mode 100644 index b707f1354..000000000 --- a/src/scripts/TealiumLoader.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @implements {TealiumLoader} - * @memberof module:TealiumLoader - */ -class TealiumLoader { - constructor({ config }) { - this.account = config.TEALIUM_ACCOUNT; - this.profile = config.TEALIUM_PROFILE; - this.env = config.TEALIUM_ENV; - } - - loadScript() { - if (!this.account && !this.profile && !this.env) { - return; - } - - global.tealiumAnalytics = global.tealiumAnalytics || []; - const { tealiumAnalytics } = global; - - // If the snippet was invoked do nothing. - if (tealiumAnalytics.invoked) { - return; - } - - // Invoked flag, to make sure the snippet - // is never invoked twice. - tealiumAnalytics.invoked = true; - - tealiumAnalytics.load = (account, profile, env) => { - const scriptTealium = document.createElement('script'); - scriptTealium.type = 'text/javascript'; - scriptTealium.innerHTML = ` - (function (a, b, c, d) { a = '//tags.tiqcdn.com/utag/${account}/${profile}/${env}/utag.js'; b = document; - c = 'script'; d = b.createElement(c); d.src = a; d.type = 'text/java' + c; d.async = true; a = b.getElementsByTagName(c)[0]; a.parentNode.insertBefore(d, a) })(); - `; - - // Insert our scripts next to the first script element. - const first = document.getElementsByTagName('script')[0]; - first.parentNode.insertBefore(scriptTealium, first); - }; - - // Load tealiumAnalytics. - tealiumAnalytics.load(this.account, this.profile, this.env); - } -} - -export default TealiumLoader; diff --git a/src/scripts/TealiumLoader.test.js b/src/scripts/TealiumLoader.test.js deleted file mode 100644 index 656f648f4..000000000 --- a/src/scripts/TealiumLoader.test.js +++ /dev/null @@ -1,69 +0,0 @@ -import { TealiumLoader } from '.'; - -describe('TealiumLoader', () => { - let body; - let tealiumScriptSrc; - let data; - - beforeEach(() => { - window.tealiumAnalytics = []; - }); - - function loadTealium(scriptData) { - const script = new TealiumLoader(scriptData); - script.loadScript(); - } - - describe('with valid TEALIUM_ACCOUNT, TEALIUM_PROFILE, and TEALIUM_ENV', () => { - beforeEach(() => { - document.body.innerHTML = '