{"version":3,"sources":["idleDeadline.js","requestIdleCallback.js","webStorageHandler.js","tdvTracker.js","googleAnalyticsTracker.js","idleValue.js","idleQueue.js","eventTracker.js","identityTracker.js","impressionTracker.js","onDemandTracker.js","index.js"],"names":["global","NewHomeSource","Modules","previousIdleDeadline","IdleDeadline","this","startTime","Date","now","prototype","didTimeout","timeRemaining","Math","max","noConflict","window","previousRequestIdleCallback","requestIdleCallback","isRequestIdleCallbackSupported","RequestIdleCallback","cIC","handle","cancelIdleCallback","clearTimeout","cancelIdleCallbackShim","rIC","callback","timeout","deadline","setTimeout","requestIdleCallbackShim","previousModule","WebStorageHandler","CONFIGURATION","constants","localStorage","sessionStorage","get","key","setItemInStorage","value","maxAgeInSeconds","storageType","data","creationDate","getTime","setItem","JSON","stringify","removeItemFromStorage","removeItem","getItemFromStorage","getItem","string","json","parse","e","parseToJson","undefined","currentDate","floor","setLocalStorageItem","setSessionStorageItem","removeSessionStorageItem","removeLocalStorageItem","getLocalStorageItem","getSessionStorageItem","tdvTracker","Analytics","isBasic","document","getElementById","TdvTracker","inputSiteRoot","querySelector","siteRoot","baseUrl","googleEcommercePushUrl","paramsEventLogger","parametersEventMapper","communityId","marketId","paramsByQueryString","basicListingParameters","configurations","eventPrefix","impressionPrefix","getBasicListingParameters","parameters","basicParams","forEach","param","getParamsToUse","isBasicListing","getTdvAttributeName","datasetAttributeName","createUrl","url","getUrl","parameterSeparator","keysParameters","Object","keys","index","length","parameter","cleanParameter","replaceAll","toLowerCase","position","map","indexOf","googleAnalyticsClientId","getValue","googleAnalyticsUserId","postRequest","successCallback","xhr","XMLHttpRequest","open","setRequestHeader","send","onreadystatechange","readyState","status","response","logGoogleEcommerceEvent","eventName","isMpc","parentCommunity","params","community","specId","spec","planId","plan","builderName","communitiesIdsList","buildercommunitylist","homesIdsList","homeList","result","eval","logEvent","eventCode","urlToRequest","replace","getValidParentCommunityId","parentCommunityId","isVisitedMpc","visitedMpcIds","globalValues","getTdvEventDataset","eventTarget","parentTdvContainer","closest","mergedDataset","dataset","tdvEventDatasetAttributesList","entries","name","fromEntries","eventTracker","eventLabel","getAttribute","split","tdvDataset","event","impressionTracker","eventTrackerValidator","tdvEventLabel","onDemandTrackerValidator","eventType","onDemandTracker","label","impressionTrackerSelector","identityTracker","elementIdentity","form","identityTrackerValidator","tdvIdentity","buildTagWithEvent","element","attributes","setAttribute","attr","isNhs","cookieHandler","customDimensionsAttribute","GoogleAnalyticsTracker","pushToDataLayer","dataLayer","push","getAttributes","prefix","attribute","startsWith","cleanProperty","charAt","slice","googlePush","eventCategory","eventAction","eventNoInteraction","eventValue","nonInteraction","gaTrack","self","assign","gaLabelFullUrl","gaEventLabel","location","href","setFullUrlsAsEventLabel","gaEventCategory","gaEventAction","customDimensions","bind","getCustomDimension","gaEventNoInteraction","gaEventLabelEmpty","textContent","trim","cleanCustomDimensions","dimensions","cleanDimensions","dimension","ctaDetail","gaImpressionEventCategory","gaImpressionEventAction","gaImpressionEventLabel","isImpressionGa","gaImpression","gaIdentityCategory","gaIdentityAction","gaIdentityLabel","dataSet","gaEventTracker","category","action","newUserGa","readCookie","ga_newUser","logNewUser","previousIdleValue","IdleValue","cancelIdleCallbackFunction","requestIdleCallbackFunction","initVariable","init","cancelIdleInit","retryIfNull","setValue","previousIdleQueue","idleQueue","isSafari","safari","pushNotification","shouldYield","minimumTaskTime","scheduleTasksToRun","retry","idleCallbackHandle","runTasks","isDomCompleted","cancelScheduledRun","isProcessing","hasPendingTasks","taskQueue","minTaskTime","taskToRun","shift","isExecuted","task","state","timeLapsed","time","pushTask","call","addEventListener","onVisibilityChange","visibilityState","runTasksImmediately","IdleQueue","id","previousEventTracker","hasBeenAttached","onTouchProperties","startX","startY","distX","distY","inspectEvent","target","inspectedElement","parentElement","tagName","type","totalHandlers","handler","handlers","validator","queue","eventForget","onTouchStartEvent","changedTouches","pageX","pageY","onTouchEndEvent","abs","onChangeEvent","nodeName","selectedIndex","EventTracker","eventsQueue","passive","composed","useCapture","previousIdentityTracker","closestForm","identity","button","reportValidity","caller","cloneNode","IdentityTracker","previousImpressionTracker","mutationObserverOptions","childList","subtree","intersectionObserverOptions","threshold","walkNodeTree","node","elementsAdded","nodeType","impression","childNodesLength","childNodes","childElements","concat","handleMutationsOnViewPort","mutations","elements","currentMutation","isIntersecting","noUnobserve","intersectionObserver","unobserve","trackertElements","selector","count","handleMutationsAsync","mutationsLength","mutation","totalElementsAdded","addedNodes","elementIndex","impressionNodes","currentElement","observe","handleDomMutations","ImpressionTracker","MutationObserver","mutationObserver","IntersectionObserver","body","querySelectorAll","previousOnDemandTracker","OnDemandTracker","detail","startTracking","googleAnalyticsId","ga","getAll","filter"],"mappings":"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","file":"../trackersbundle-24a9efaf78.min.js","sourceRoot":"..","sourcesContent":["(function idleDeadline(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Modules = global.NewHomeSource.Modules || {};\r\n\r\n const previousIdleDeadline = global.NewHomeSource.Modules.IdleDeadline;\r\n\r\n /**\r\n * @constructs NewHomeSource.Modules.idleDeadline\r\n */\r\n function IdleDeadline() {\r\n this.startTime = Date.now();\r\n }\r\n\r\n /**\r\n * @public\r\n * didTimeout: always false. Method exists to support the interface.\r\n */\r\n IdleDeadline.prototype.didTimeout = function didTimeout() {\r\n return false;\r\n };\r\n\r\n /**\r\n * @public\r\n * timeRemaining: amount of time available after the IdleDeadline was instanced.\r\n */\r\n IdleDeadline.prototype.timeRemaining = function timeRemaining() {\r\n return Math.max(0, 50 - (Date.now() - this.startTime));\r\n };\r\n\r\n /**\r\n * @public\r\n *\r\n * noConflict: Returns control of NewHomeSource.SampleModule to the previous script.\r\n */\r\n IdleDeadline.noConflict = function noConflict() {\r\n global.NewHomeSource.Modules.IdleDeadline = previousIdleDeadline;\r\n return IdleDeadline;\r\n };\r\n\r\n global.NewHomeSource.Modules.IdleDeadline = IdleDeadline;\r\n}(window));\r\n","(function requestIdleCallback(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Modules = global.NewHomeSource.Modules || {};\r\n\r\n if (!global.NewHomeSource.Modules.IdleDeadline) {\r\n return;\r\n }\r\n\r\n const previousRequestIdleCallback = global.NewHomeSource.Modules.requestIdleCallback;\r\n const isRequestIdleCallbackSupported = typeof global.requestIdleCallback === 'function';\r\n\r\n /**\r\n * @private\r\n * cancelIdleCallbackShim: polyfills the cancelIdleCallback.\r\n *\r\n * @param {number} of the ID of the timeout function to cancel.\r\n */\r\n function cancelIdleCallbackShim(handle) {\r\n clearTimeout(handle);\r\n }\r\n\r\n /**\r\n * @private\r\n * requestIdleCallbackShim: polyfills the requestIdleCallback.\r\n *\r\n * @param {function} callback that will run in the next idle period.\r\n */\r\n function requestIdleCallbackShim(callback) {\r\n const deadline = new global.NewHomeSource.Modules.IdleDeadline();\r\n return setTimeout(() => {\r\n callback(deadline);\r\n }, 0);\r\n }\r\n\r\n /**\r\n * @constructs NewHomeSource.Modules.requestIdleCallback\r\n */\r\n function RequestIdleCallback() {\r\n }\r\n\r\n /**\r\n * @public\r\n * cIC: returns a cancelIdleCallback function.\r\n *\r\n * @param {any} handle that references the requestIdleCallback.\r\n */\r\n RequestIdleCallback.cIC = function cIC(handle) {\r\n return isRequestIdleCallbackSupported ? global.cancelIdleCallback(handle) : cancelIdleCallbackShim(handle);\r\n };\r\n\r\n /**\r\n * @public\r\n * rIC: returns a requestIdleCallback function.\r\n *\r\n * @param {function} callback to execute in an idle period.\r\n * @param {number} timeout max time to wait before running the callback.\r\n */\r\n RequestIdleCallback.rIC = function rIC(callback, timeout) {\r\n return isRequestIdleCallbackSupported\r\n ? global.requestIdleCallback(callback, timeout)\r\n : requestIdleCallbackShim(callback);\r\n };\r\n\r\n /**\r\n * @public\r\n *\r\n * noConflict: Returns control of NewHomeSource.SampleModule to the previous script.\r\n */\r\n RequestIdleCallback.noConflict = function noConflict() {\r\n global.NewHomeSource.Modules.requestIdleCallback = previousRequestIdleCallback;\r\n return RequestIdleCallback;\r\n };\r\n\r\n global.NewHomeSource.Modules.requestIdleCallback = RequestIdleCallback;\r\n}(window));\r\n","/**\r\n * This module is a wrapper of the sessionStorage and localStorage APIs but with two improvements\r\n * that those APIs don't have:\r\n * 1. The APIs only allow to save strings. If you want to save any other type, you will need to\r\n * stringify the data as a json when saving it and parse it when reading it. This module handles\r\n * that automatically, you can save any type of data: numbers, booleans, object, etc.\r\n * 2. You can pass a expiry date to the data you save, so it behaves like a cookie.\r\n * For example, you can save an item with an expiry date of a day. If you try to access the item\r\n * from the storage after that time, it will return null and the item will be deleted if you try\r\n * to read it. If you don't pass an expiry date, the data won't be deleted.\r\n */\r\n(function webStorageHandler(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n\r\n const previousModule = global.NewHomeSource.WebStorageHandler;\r\n\r\n /**\r\n * @constructs NewHomeSource.WebStorageHandler\r\n */\r\n function WebStorageHandler() { }\r\n\r\n const CONFIGURATION = (function () {\r\n const constants = {\r\n localStorage: 'localStorage',\r\n sessionStorage: 'sessionStorage',\r\n };\r\n\r\n const get = function (key) {\r\n return constants[key];\r\n };\r\n\r\n return {\r\n get\r\n };\r\n }());\r\n\r\n /**\r\n * @private\r\n * @description Helper to parse a string to json, handles the exception if the string is not parseable.\r\n * @param {string} string The string to check if can be parsed to Json.\r\n * @returns {any} Json object if the string is parseable, null otherwise.\r\n */\r\n function parseToJson(string) {\r\n let json;\r\n\r\n try {\r\n json = JSON.parse(string);\r\n } catch (e) {\r\n json = null;\r\n }\r\n\r\n return json;\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {string} key The name of the key.\r\n * @param {string} value The value to save for that key.\r\n * @param {number} maxAgeInSeconds The amount of time in seconds the item should be valid.\r\n * @param {string} storageType The storage api we want to use.\r\n */\r\n function setItemInStorage(key, value, maxAgeInSeconds, storageType) {\r\n if (!global.localStorage) {\r\n return;\r\n }\r\n\r\n const data = {\r\n creationDate: new Date().getTime(),\r\n maxAgeInSeconds: maxAgeInSeconds > 0\r\n ? maxAgeInSeconds\r\n : 0\r\n };\r\n\r\n // workaround for resource combiner because it doesn't allows me to do something like [key]: value\r\n // inside a json object declaration. just die already please.\r\n // ToDo remove this workaround when migrating this module to gulp.\r\n data[key] = value;\r\n\r\n if (storageType === CONFIGURATION.get('localStorage')) {\r\n global.localStorage.setItem(key, JSON.stringify(data));\r\n } else if (storageType === CONFIGURATION.get('sessionStorage')) {\r\n global.sessionStorage.setItem(key, JSON.stringify(data));\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * @description Removes a value stored in the browser's api storage.\r\n * @param {any} key The key to remove from storage.\r\n * @param {any} storageType The storage api we want to use.\r\n */\r\n function removeItemFromStorage(key, storageType) {\r\n if (!global[storageType]) {\r\n return;\r\n }\r\n\r\n global[storageType].removeItem(key);\r\n }\r\n\r\n /**\r\n * @description Gets a value stored in the browser's api storage.\r\n * @param {string} key The name of the key.\r\n * @param {string} storageType The storage api we want to use.\r\n * @returns The item stored in the browser's storage.\r\n */\r\n function getItemFromStorage(key, storageType) {\r\n if (!global[storageType]) {\r\n return null;\r\n }\r\n\r\n let data = global[storageType].getItem(key);\r\n\r\n if (data === null) {\r\n return null;\r\n }\r\n\r\n data = parseToJson(data);\r\n\r\n if (data === null || data[key] === undefined) {\r\n return null;\r\n }\r\n\r\n if (data.maxAgeInSeconds === 0) {\r\n return data[key];\r\n }\r\n\r\n const currentDate = new Date().getTime();\r\n const differenceInSeconds = Math.floor((currentDate - data.creationDate) / 1000);\r\n\r\n if (differenceInSeconds > data.maxAgeInSeconds) {\r\n global[storageType].removeItem(key);\r\n return null;\r\n }\r\n\r\n return data[key];\r\n }\r\n\r\n /**\r\n * @public\r\n * @description: Saves a key/value pair in the browser's local storage,\r\n * if the browser supports the Window.localStorage api.\r\n * @param {string} key The name of the key.\r\n * @param {any} value The value to save for that key.\r\n * @param {number} maxAgeInSeconds The amount of time in seconds the item should be valid.\r\n * If not provided, the item will always be valid.\r\n */\r\n WebStorageHandler.setLocalStorageItem = function (key, value, maxAgeInSeconds) {\r\n const storageType = CONFIGURATION.get('localStorage');\r\n setItemInStorage(key, value, maxAgeInSeconds, storageType);\r\n };\r\n\r\n /**\r\n * @public\r\n * @description: Saves a key/value pair in the browser's session storage,\r\n * if the browser supports the Window.sessionStorage api.\r\n * @param {string} key The name of the key.\r\n * @param {any} value The value to save for that key.\r\n * @param {number} maxAgeInSeconds The amount of time the item should be valid, in seconds.\r\n * If not provided, the item will always be valid.\r\n */\r\n WebStorageHandler.setSessionStorageItem = function (key, value, maxAgeInSeconds) {\r\n const storageType = CONFIGURATION.get('sessionStorage');\r\n setItemInStorage(key, value, maxAgeInSeconds, storageType);\r\n };\r\n\r\n /**\r\n * @public\r\n * @description Removes a key/value stored in the browser's session storage,\r\n * if the browser supports the Window.sessionStorage api.\r\n * This method should only be used to remove data saved in the session storage\r\n * with the WebStorageHandler.setSessionStorageItem method.\r\n * @param {any} key The key to remove from session storage.\r\n */\r\n WebStorageHandler.removeSessionStorageItem = function (key) {\r\n const storageType = CONFIGURATION.get('sessionStorage');\r\n removeItemFromStorage(key, storageType);\r\n };\r\n\r\n /**\r\n * @public\r\n * @description Removes a key/value stored in the browser's local storage,\r\n * if the browser supports the Window.localStorage api.\r\n * This method should only be used to remove data saved in the local storage\r\n * with the WebStorageHandler.setLocalStorageItem method.\r\n * @param {any} key The key to remove from session storage.\r\n */\r\n WebStorageHandler.removeLocalStorageItem = function (key) {\r\n const storageType = CONFIGURATION.get('localStorage');\r\n removeItemFromStorage(key, storageType);\r\n };\r\n\r\n /**\r\n * @public\r\n * @description Gets a value stored in the browser's local storage,\r\n * if the browser supports the Window.localStorage api (returns null otherwise).\r\n * This method should only be used to retrieve data saved in the local storage\r\n * with the WebStorageHandler.setLocalStorageItem method.\r\n * @param {string} key The name of the key to retrieve from the local storage\r\n * @returns The item stored in the local storage.\r\n */\r\n WebStorageHandler.getLocalStorageItem = function (key) {\r\n const storageType = CONFIGURATION.get('localStorage');\r\n\r\n return getItemFromStorage(key, storageType);\r\n };\r\n\r\n /**\r\n * @public\r\n * @description Gets a value stored in the browser's session storage,\r\n * if the browser supports the Window.sessionStorage api (returns null otherwise).\r\n * This method should only be used to retrieve data saved in the session storage\r\n * with the WebStorageHandler.setSessionStorageItem method.\r\n * @param {string} key The name of the key to retrieve from the session storage\r\n * @returns The item stored in the local storage.\r\n */\r\n WebStorageHandler.getSessionStorageItem = function (key) {\r\n const storageType = CONFIGURATION.get('sessionStorage');\r\n\r\n return getItemFromStorage(key, storageType);\r\n };\r\n\r\n /**\r\n * @public\r\n * noConflict: Returns control of NewHomeSource.SampleModule to the previous script.\r\n */\r\n WebStorageHandler.noConflict = function noConflict() {\r\n global.NewHomeSource.WebStorageHandler = previousModule;\r\n return WebStorageHandler;\r\n };\r\n\r\n global.NewHomeSource.WebStorageHandler = WebStorageHandler;\r\n\r\n return WebStorageHandler;\r\n}(window));\r\n","/*\r\n * This module is for TDV events.\r\n * To start tracking you will need to the following data attribute\r\n * data-builder='builder id value'\r\n * data-community='community id value'\r\n * data-parent-community-id='parent community id value'\r\n * data-community-list='list id of communities value'\r\n * data-market='market id value'\r\n * data-plan-id='plan id value'\r\n * data-spec-id='spec id value'\r\n * data-basic-listing-id='basic listing id value'\r\n * data-refer='refer value'\r\n * data-totalHomes='totalHomes value'\r\n * data-builder-community-list='BuilderId CommunityId ParentCommunityId MarketId,'\r\n * data-basic-listing-list='BuilderId ListingId,'\r\n * data-home-list='homeId (s||p),'\r\n */\r\n\r\n(function tdvTracker(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Analytics = global.NewHomeSource.Analytics || {};\r\n const isBasic = document.getElementById('IsBasic');\r\n const previousModule = global.NewHomeSource.Analytics.TdvTracker;\r\n const inputSiteRoot = document.querySelector('#nhs_siteRootLogger');\r\n const siteRoot = (inputSiteRoot && inputSiteRoot.value) || '/';\r\n const baseUrl = siteRoot + 'eventlogger/logevent-[EventCode]';\r\n const googleEcommercePushUrl = '/googleanalytics/getgoogleecommercepush';\r\n const paramsEventLogger = ['builder', 'community', 'parentCommunityId', 'market', 'planId', 'specId',\r\n 'basicListingId', 'refer', 'totalHomes'];\r\n const parametersEventMapper = {\r\n communityId: 'community',\r\n marketId: 'market'\r\n };\r\n const paramsByQueryString = ['communityList', 'builderCommunityList', 'basicListingList', 'homeList',\r\n 'homeImpression'];\r\n const basicListingParameters = ['market', 'basicListingId', 'basicListingList'];\r\n const configurations = {\r\n eventPrefix: 'data-tdv-event-label',\r\n impressionPrefix: 'data-tdv-impression-label',\r\n isBasic: isBasic && isBasic.value === 'True'\r\n };\r\n\r\n function getBasicListingParameters(parameters) {\r\n const basicParams = [];\r\n basicListingParameters.forEach((param) => {\r\n if (parameters[param] && parameters[param] !== '0') {\r\n basicParams[param] = parameters[param];\r\n }\r\n });\r\n\r\n return basicParams;\r\n }\r\n\r\n function getParamsToUse(parameters) {\r\n return parameters.isBasicListing === 'true' ? getBasicListingParameters(parameters) : parameters;\r\n }\r\n\r\n /**\r\n * @private\r\n * Gets rthe correct naming for the TDV events.\r\n * @returns The correct TDV parameter name.\r\n */\r\n function getTdvAttributeName(datasetAttributeName) {\r\n const tdvParameter = parametersEventMapper[datasetAttributeName] || datasetAttributeName;\r\n return tdvParameter;\r\n }\r\n\r\n /**\r\n * @private\r\n * createUrl: create the url with the parameters reviced, it will match with keys of urls object\r\n * with the keys of dataset of the element.\r\n *\r\n * @param {String} url base url to be requested.\r\n * @param {Array} parameters that match with urls object keys and use the value to replace [Id].\r\n * @returns the url to be requested for logging.\r\n */\r\n function createUrl(url, parameters) {\r\n let getUrl = url;\r\n let parameterSeparator = '?';\r\n const keysParameters = Object.keys(getParamsToUse(parameters));\r\n for (let index = 0; index < keysParameters.length; index += 1) {\r\n const parameter = keysParameters[index];\r\n const cleanParameter = parameter.replaceAll('-', '').toLowerCase();\r\n const cleanParamsEventLogger = paramsEventLogger.map((value) => value.toLowerCase());\r\n const position = cleanParamsEventLogger.indexOf(cleanParameter);\r\n if (position > -1 && parameters[parameter] && parameters[parameter] !== '0') {\r\n getUrl += '/' + paramsEventLogger[position] + '-' + parameters[parameter];\r\n }\r\n }\r\n\r\n getUrl += '/GAClientId-' + configurations.data.googleAnalyticsClientId.getValue(true) +\r\n '/GAUserId-' + configurations.data.googleAnalyticsUserId.getValue(true);\r\n\r\n keysParameters.forEach((parameter) => {\r\n const cleanParameter = parameter.replaceAll('-', '').toLowerCase();\r\n const cleanParamsEventLogger = paramsByQueryString.map((value) => value.toLowerCase());\r\n const position = cleanParamsEventLogger.indexOf(cleanParameter);\r\n if (position > -1 && parameters[parameter] && parameters[parameter] !== '0') {\r\n getUrl += parameterSeparator + paramsByQueryString[position] + '=' + parameters[parameter];\r\n parameterSeparator = '&';\r\n }\r\n });\r\n\r\n return getUrl;\r\n }\r\n\r\n /**\r\n * @private\r\n * postRequest: to create an HTTP Post request to send data.\r\n *\r\n * @param {String} url to be requested.\r\n * @param {Object} data with the information to log.\r\n * @param {Function} successCallback to be executed on request is success.\r\n */\r\n function postRequest(url, data, successCallback) {\r\n const xhr = new XMLHttpRequest();\r\n xhr.open('POST', url, true);\r\n xhr.setRequestHeader('Content-Type', 'application/json');\r\n xhr.send(JSON.stringify(data));\r\n\r\n xhr.onreadystatechange = function () {\r\n if (xhr.readyState !== 4) {\r\n return;\r\n }\r\n\r\n if (xhr.status === 200) {\r\n if (typeof successCallback === 'function') {\r\n successCallback(xhr.response);\r\n }\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * @private\r\n * logGoogleEcommerceEvent: log google ecommerce event and execute in datalayer.\r\n *\r\n * @param {String} eventName event to be logged on analytics\r\n * @param {Array} parameters data used to get the information from the page.\r\n */\r\n function logGoogleEcommerceEvent(eventName, parameters) {\r\n const isMpc = parameters.parentCommunity !== 0;\r\n const params = {\r\n eventName,\r\n communityId: parameters.community,\r\n specId: parameters.spec,\r\n planId: parameters.plan,\r\n builderName: parameters.builderName || '',\r\n communitiesIdsList: parameters.buildercommunitylist,\r\n homesIdsList: parameters.homeList,\r\n isMpc\r\n };\r\n postRequest(googleEcommercePushUrl, params, (result) => {\r\n // The GetDataLayerPush method of the Google Analytics Controller returns a js that needs to be executed\r\n // eslint-disable-next-line no-eval\r\n eval(result);\r\n });\r\n }\r\n\r\n /**\r\n * @private\r\n * logEvent: log event related to TDV.\r\n *\r\n * @param {String} eventCode that will be tracker.\r\n * @param {Array} parameters that will be add on the url to track.\r\n */\r\n function logEvent(eventCode, parameters) {\r\n if (eventCode) {\r\n const url = baseUrl.replace('[EventCode]', eventCode);\r\n const urlToRequest = createUrl(url, parameters);\r\n logGoogleEcommerceEvent(eventCode, parameters);\r\n postRequest(urlToRequest);\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n *\r\n * Checks if the parent community id belongs to a MPC that was already visited.\r\n * @param {number} parentCommunityId\r\n * @returns The same parent community id if the MPC was visited, 0 otherwise.\r\n */\r\n function getValidParentCommunityId(parentCommunityId) {\r\n if (parentCommunityId === 0) {\r\n return 0;\r\n }\r\n\r\n const isVisitedMpc = configurations.data.visitedMpcIds();\r\n\r\n if (!isVisitedMpc || isVisitedMpc.indexOf(parentCommunityId) === -1) {\r\n return 0;\r\n }\r\n\r\n return parentCommunityId;\r\n }\r\n\r\n /**\r\n * @constructs NewHomeSource.Analytics.TdvTracker\r\n */\r\n function TdvTracker(globalValues) {\r\n configurations.data = globalValues;\r\n }\r\n\r\n /**\r\n * Gets the dataset information to be used for loggin the TDV Events.\r\n * @param {HTMLElement} eventTarget Element where the event was triggered.\r\n * @returns An object with the dataset to be used on the TDV events.\r\n */\r\n function getTdvEventDataset(eventTarget) {\r\n const parentTdvContainer = eventTarget.closest('[data-tdv-container]');\r\n const parentTdvDataset = parentTdvContainer ? parentTdvContainer.dataset : {};\r\n const mergedDataset = { ...parentTdvDataset, ...eventTarget.dataset };\r\n mergedDataset.parentCommunity = getValidParentCommunityId(eventTarget.dataset.parentCommunity);\r\n\r\n const datasetAttributesList = Object.entries(mergedDataset);\r\n const tdvEventDatasetAttributesList = datasetAttributesList.map(([name, value]) => {\r\n const tdvAttributeName = getTdvAttributeName(name);\r\n\r\n return [tdvAttributeName, value];\r\n });\r\n const tdvEventDataset = Object.fromEntries(tdvEventDatasetAttributesList);\r\n\r\n return tdvEventDataset;\r\n }\r\n\r\n /**\r\n * @public\r\n * eventTracker: send data related to user action events.\r\n */\r\n TdvTracker.eventTracker = function eventTracker() {\r\n const eventLabel = this.getAttribute(configurations.eventPrefix).split(',');\r\n\r\n if (!eventLabel) {\r\n return true;\r\n }\r\n\r\n const tdvDataset = getTdvEventDataset(this);\r\n eventLabel.forEach((event) => {\r\n logEvent(event, tdvDataset);\r\n });\r\n\r\n return true;\r\n };\r\n\r\n /**\r\n * @public\r\n * impressionTracker: send data related to display events.\r\n */\r\n TdvTracker.impressionTracker = function impressionTracker() {\r\n for (let index = 0; index < this.length; index += 1) {\r\n const eventLabel = this[index].getAttribute(configurations.impressionPrefix).split(',');\r\n\r\n if (!eventLabel) {\r\n return true;\r\n }\r\n\r\n const tdvDataset = getTdvEventDataset(this[index]);\r\n eventLabel.forEach((event) => {\r\n logEvent(event, tdvDataset);\r\n });\r\n }\r\n\r\n return true;\r\n };\r\n\r\n /**\r\n * @public\r\n * eventTrackerValidator: validates if the dataset passed as parameter represents a segment event being tracked.\r\n */\r\n TdvTracker.eventTrackerValidator = function eventTrackerValidator(dataset) {\r\n if (dataset.tdvEventLabel) {\r\n return true;\r\n }\r\n\r\n return false;\r\n };\r\n\r\n /**\r\n * @public\r\n * onDemandTrackerValidator: validates if the dataset passed as parameter represents a segment event being tracked.\r\n */\r\n TdvTracker.onDemandTrackerValidator = function eventTrackerValidator(data) {\r\n return data && data.eventType === 'tdvEvent';\r\n };\r\n\r\n /**\r\n * @public\r\n * onDemandTracker: send data related to events that cannot be mapped to the HTML.\r\n *\r\n * @param {object} status of the scheduled idle task.\r\n */\r\n TdvTracker.onDemandTracker = function onDemandTracker() {\r\n const label = this.label;\r\n\r\n if (!label) {\r\n return true;\r\n }\r\n\r\n this.parentCommunity = getValidParentCommunityId(this.parentCommunity);\r\n logEvent(label, this);\r\n\r\n return true;\r\n };\r\n /**\r\n * @public\r\n * impressionTrackerSelector: returns the expression that can be used to query the DOM.\r\n */\r\n TdvTracker.impressionTrackerSelector = function impressionTrackerSelector() {\r\n return configurations.impressionPrefix;\r\n };\r\n\r\n TdvTracker.identityTracker = function identityTracker() {\r\n const elementIdentity = this.form.querySelector('[data-tdv-identity]');\r\n\r\n if (!elementIdentity) {\r\n return true;\r\n }\r\n\r\n const data = elementIdentity.dataset;\r\n\r\n if (!data.eventCode) {\r\n return true;\r\n }\r\n\r\n data.parentCommunity = getValidParentCommunityId(data.parentCommunity);\r\n logEvent(data.eventCode, data);\r\n\r\n return true;\r\n };\r\n\r\n /**\r\n * @public\r\n * identityTrackerValidator: validates if the dataset passed as parameter represents a segment identity being tracked.\r\n */\r\n TdvTracker.identityTrackerValidator = function identityTrackerValidator(dataset) {\r\n return !!dataset.tdvIdentity;\r\n };\r\n\r\n TdvTracker.buildTagWithEvent = function (element, event, attributes) {\r\n element.setAttribute('data-event', 'true');\r\n element.setAttribute('data-tdv-event-label', event);\r\n attributes.forEach((attr) => {\r\n element.setAttribute(attr.name, attr.value);\r\n });\r\n };\r\n\r\n /**\r\n * @public\r\n *\r\n * noConflict: Returns control of NewHomeSource.Segment to the previous script.\r\n */\r\n TdvTracker.noConflict = function noConflict() {\r\n global.NewHomeSource.Analytics.TdvTracker = previousModule;\r\n return TdvTracker;\r\n };\r\n\r\n global.NewHomeSource.Analytics.TdvTracker = TdvTracker;\r\n}(window));\r\n","/* This module should be the one we keep using for google analytics events\r\n * It uses the logic created by Carlos to handle the events in a performant way.\r\n *\r\n * How to use it: dev should add four data attributes to the element it wants to track:\r\n * data-event='true'\r\n * data-ga-event-category='my event category'\r\n * data-ga-event-action='my event action'\r\n * data-ga-event-label='my event label'\r\n * The data-ga-event-label is optional, if not included, it will use the text of the element.\r\n *\r\n * Data Values for impression tracker:\r\n * data-impression=\"true\"\r\n * data-ga-impression=\"true\"\r\n * data-ga-impression-event-category='event category'\r\n * data-ga-impression-event-action='event action'\r\n * data-ga-impression-event-label= 'event label'\r\n *\r\n * The event tracker listens for the click function,\r\n * if for some reason there's an event.preventDefault that prevents tracking your event,\r\n * add a data-event-type=\"mousedown\" for desktop or data-event-type=\"touchend\" for mobile.\r\n *\r\n * If you need to track a event programatically instead of when clicking an element,\r\n * use the onDemandTracker method instead. Example:\r\n *\r\n * if (global.NewHomeSource.Analytics.onDemandTracker) {\r\n * const myEvent = {\r\n * event: 'GAEvent',\r\n * eventCategory: 'my event category',\r\n * eventAction: 'my event action',\r\n * eventLabel: 'my event label',\r\n * };\r\n *\r\n * global.NewHomeSource.Analytics.onDemandTracker.push(myEvent);\r\n*/\r\n\r\n(function googleAnalyticsTracker(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Analytics = global.NewHomeSource.Analytics || {};\r\n\r\n /**\r\n * Constant flag to avoid log new user event in wordpress pages.\r\n */\r\n const isNhs = !!global.NewHomeSource.Modules.cookieHandler;\r\n\r\n const configurations = {\r\n customDimensionsAttribute: 'gaDimension'\r\n };\r\n\r\n /*\r\n * Dependencies as\r\n * if (!global.NewHomeSource.MyDependency) {\r\n * return;\r\n * }\r\n */\r\n\r\n const previousModule = global.NewHomeSource.Analytics.GoogleAnalyticsTracker;\r\n\r\n /**\r\n * @constructs NewHomeSource.Analytics.GoogleAnalyticsTracker\r\n */\r\n function GoogleAnalyticsTracker(globalValues) {\r\n configurations.globalValues = globalValues;\r\n }\r\n\r\n function pushToDataLayer(data) {\r\n const dataLayer = window.dataLayer;\r\n\r\n if (dataLayer) {\r\n dataLayer.push(data);\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * getAttributes: get the attributes that starts with data-ga-dimension\r\n *\r\n * @param {DOMStringMap} dataset properties of the object.\r\n * @param {*} prefix to evaluate the properties we want to retrieve.\r\n * @param {*} attribute being evaluated.\r\n * @returns object with the property.\r\n */\r\n function getAttributes(dataset, prefix, attribute) {\r\n if (!attribute.startsWith(prefix)) {\r\n return;\r\n }\r\n\r\n const cleanProperty = attribute.replace(prefix, '');\r\n const name = cleanProperty.charAt(0).toLowerCase() + cleanProperty.slice(1);\r\n\r\n if (!name) {\r\n return;\r\n }\r\n\r\n this[name] = dataset[attribute];\r\n }\r\n\r\n /**\r\n * @private\r\n * getCustomDimension: gets a custom dimensions object based on data-ga-dimension attributes\r\n *\r\n * @param {DOMStringMap} dataset properties of the object.\r\n */\r\n function getCustomDimension(dataset) {\r\n const customDimensions = {};\r\n Object.keys(dataset)\r\n .forEach(getAttributes.bind(customDimensions, dataset, configurations.customDimensionsAttribute));\r\n\r\n return customDimensions;\r\n }\r\n\r\n /**\r\n * Pushes the google analytics event to the dataLayer.\r\n * @param {*} eventCategory Google analytics category name for the event.\r\n * @param {*} eventAction Google analytics action name for the event.\r\n * @param {*} eventLabel Google analytics label name for the event.\r\n * @param {*} eventNoInteraction Google analytics label name for the event.\r\n */\r\n function googlePush(eventCategory, eventAction, eventLabel, eventNoInteraction) {\r\n const dataLayer = window.dataLayer;\r\n\r\n if (dataLayer) {\r\n dataLayer.push({\r\n event: 'GAEvent',\r\n eventCategory,\r\n eventAction,\r\n eventLabel,\r\n eventValue: undefined,\r\n nonInteraction: eventNoInteraction || 0\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * gaTrack: log google analytics event with google analytics object.\r\n *\r\n * @param {*} eventCategory Google analytics category name for the event.\r\n * @param {*} eventAction Google analytics action name for the event.\r\n * @param {*} eventLabel Google analytics label name for the event.\r\n */\r\n function gaTrack(eventCategory, eventAction, eventLabel) {\r\n pushToDataLayer({\r\n event: 'GAEvent',\r\n eventCategory,\r\n eventAction,\r\n eventLabel,\r\n eventValue: undefined,\r\n nonInteraction: 1\r\n });\r\n }\r\n\r\n function logNewUser() {\r\n const newUserGa = global.NewHomeSource.Modules.cookieHandler.readCookie('_ga');\r\n if (global.dataLayer && !newUserGa) {\r\n global.dataLayer.push({\r\n event: 'newUser',\r\n ga_newUser: 'true'\r\n });\r\n }\r\n }\r\n\r\n function setFullUrlsAsEventLabel(data) {\r\n const dataset = data;\r\n if (dataset.gaLabelFullUrl === 'true') {\r\n dataset.gaEventLabel = global.location.href;\r\n }\r\n return dataset;\r\n }\r\n\r\n /**\r\n * cleanCustomDimensions: pushes to the data layer the default values for all custom dimensions\r\n * recently pushed in an event. We need this for scenarios like Search Results Pages where\r\n * we don't want to keep in the data layer specific values like listing Ids recently clicked since\r\n * not all of the upcoming events are going to be bound to this particular Id.\r\n *\r\n * @param {*} dimensions is the custom dimensions for an event recently pushed.\r\n */\r\n function cleanCustomDimensions(dimensions) {\r\n const cleanDimensions = Object.assign({}, dimensions);\r\n Object.keys(cleanDimensions).forEach((dimension) => { cleanDimensions[dimension] = null; });\r\n\r\n pushToDataLayer(cleanDimensions);\r\n }\r\n\r\n GoogleAnalyticsTracker.onDemandTracker = function () {\r\n const dataLayer = window.dataLayer;\r\n const self = Object.assign({}, this);\r\n\r\n if (dataLayer) {\r\n dataLayer.push(self);\r\n }\r\n\r\n return true;\r\n };\r\n\r\n GoogleAnalyticsTracker.eventTracker = function () {\r\n const dataset = setFullUrlsAsEventLabel(this.dataset);\r\n const eventCategory = dataset.gaEventCategory;\r\n const eventAction = dataset.gaEventAction;\r\n\r\n const customDimensions = getCustomDimension(dataset);\r\n pushToDataLayer(customDimensions);\r\n\r\n if (eventCategory && eventAction) {\r\n let eventLabel = dataset.gaEventLabel;\r\n const eventNoInteraction = +dataset.gaEventNoInteraction || 0;\r\n\r\n if (!eventLabel && dataset.gaEventLabelEmpty !== 'true') {\r\n eventLabel = this.textContent.trim() + ' Clicks';\r\n }\r\n\r\n googlePush(eventCategory, eventAction, eventLabel, eventNoInteraction);\r\n\r\n if (this.dataset.cleanCustomDimensions) {\r\n cleanCustomDimensions(customDimensions);\r\n }\r\n }\r\n\r\n if (this.dataset.ctaDetail) {\r\n this.dataset.ctaDetail.split(',').forEach((data) => pushToDataLayer({ ctaDetail: data }));\r\n }\r\n\r\n return true;\r\n };\r\n\r\n /**\r\n * @public\r\n * impressionTrackerSelector: returns the expression that can be used to query the DOM for impression events.\r\n */\r\n GoogleAnalyticsTracker.impressionTrackerSelector = function () {\r\n return 'data-ga-impression';\r\n };\r\n\r\n /**\r\n * @public\r\n * impressionTracker: send data related to display events.\r\n *\r\n * @param {object} status of the scheduled idle task.\r\n */\r\n GoogleAnalyticsTracker.impressionTracker = function () {\r\n const length = this.length;\r\n for (let index = 0; index < length; index += 1) {\r\n const data = this[index].dataset;\r\n const eventCategory = data.gaImpressionEventCategory;\r\n const eventAction = data.gaImpressionEventAction;\r\n const eventLabel = data.gaImpressionEventLabel;\r\n const isImpressionGa = data.gaImpression;\r\n\r\n if (eventCategory && isImpressionGa && eventAction) {\r\n gaTrack(eventCategory, eventAction, eventLabel || null);\r\n }\r\n }\r\n return true;\r\n };\r\n\r\n /**\r\n * @public\r\n * identityTracker: send data related when user send the form.\r\n *\r\n */\r\n GoogleAnalyticsTracker.identityTracker = function identityTracker() {\r\n const dataset = this.form.querySelector('[data-ga-identity-category]').dataset;\r\n googlePush(dataset.gaIdentityCategory, dataset.gaIdentityAction, dataset.gaIdentityLabel || '');\r\n return true;\r\n };\r\n\r\n GoogleAnalyticsTracker.eventTrackerValidator = function (dataSet) {\r\n if ((dataSet.gaEventCategory && dataSet.gaEventAction) || dataSet.gaEventTracker) {\r\n return true;\r\n }\r\n\r\n return false;\r\n };\r\n\r\n GoogleAnalyticsTracker.onDemandTrackerValidator = function (data) {\r\n return data && data.eventType === 'GAEvent';\r\n };\r\n\r\n /**\r\n * @public\r\n * identityTrackerValidator: validates if the dataset passed as parameter represents a google analytics identity\r\n * being tracked.\r\n */\r\n GoogleAnalyticsTracker.identityTrackerValidator = function identityTrackerValidator(dataset) {\r\n return !!dataset.gaIdentityCategory && !!dataset.gaIdentityAction;\r\n };\r\n\r\n /**\r\n * @public\r\n * buildTagWithEvent: build tag to have the attributes to log analytics event.\r\n *\r\n * @param {Element} element to add the attributes.\r\n * @param {String} category Google analytics category name for the event.\r\n * @param {String} action Google analytics action name for the event.\r\n * @param {String} label Google analytics label name for the event.\r\n */\r\n GoogleAnalyticsTracker.buildTagWithEvent = function (element, category, action, label) {\r\n if (element) {\r\n element.setAttribute('data-event', 'true');\r\n element.setAttribute('data-ga-event-category', category);\r\n element.setAttribute('data-ga-event-action', action);\r\n element.setAttribute('data-ga-event-label', label);\r\n }\r\n };\r\n\r\n /**\r\n * @public\r\n * noConflict: Returns control of NewHomeSource.SampleModule to the previous script.\r\n */\r\n GoogleAnalyticsTracker.noConflict = function noConflict() {\r\n global.NewHomeSource.Analytics.GoogleAnalyticsTracker = previousModule;\r\n return GoogleAnalyticsTracker;\r\n };\r\n\r\n global.NewHomeSource.Analytics.GoogleAnalyticsTracker = GoogleAnalyticsTracker;\r\n if (isNhs) {\r\n logNewUser();\r\n }\r\n\r\n return GoogleAnalyticsTracker;\r\n}(window));\r\n","(function idleValue(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Modules = global.NewHomeSource.Modules || {};\r\n\r\n if (!global.NewHomeSource.Modules.requestIdleCallback) {\r\n return;\r\n }\r\n\r\n const previousIdleValue = global.NewHomeSource.Modules.IdleValue;\r\n const cancelIdleCallbackFunction = global.NewHomeSource.Modules.requestIdleCallback.cIC;\r\n const requestIdleCallbackFunction = global.NewHomeSource.Modules.requestIdleCallback.rIC;\r\n\r\n /**\r\n * @private\r\n *\r\n * initVariable: assign the value of the variable from the callback;\r\n */\r\n function initVariable() {\r\n this.value = this.callback();\r\n }\r\n\r\n /**\r\n * @constructs NewHomeSource.Modules.IdleValue\r\n *\r\n * @param {function} callback that initializes a value for a variable.\r\n */\r\n function IdleValue(callback) {\r\n this.callback = callback;\r\n this.value = undefined;\r\n this.init = requestIdleCallbackFunction(initVariable.bind(this));\r\n }\r\n\r\n /**\r\n * @public\r\n * cancelIdleInit: cancels the init of the IdleValue.\r\n */\r\n IdleValue.prototype.cancelIdleInit = function cancelIdleInit() {\r\n if (!this.init) {\r\n return;\r\n }\r\n\r\n cancelIdleCallbackFunction(this.init);\r\n this.init = null;\r\n };\r\n\r\n /**\r\n * @public\r\n * getValue: gets the value from the IdleValue.\r\n *\r\n * @param {boolean} retryIfNull take null value as wrong values and execute the callback.\r\n */\r\n IdleValue.prototype.getValue = function getValue(retryIfNull) {\r\n if (this.value === undefined || (retryIfNull && this.value === null)) {\r\n this.cancelIdleInit();\r\n this.value = this.callback();\r\n }\r\n\r\n return this.value;\r\n };\r\n\r\n /**\r\n * @public\r\n * setValue: sets a new value to the IdleValue.\r\n *\r\n * @param {any} value to be assigned.\r\n */\r\n IdleValue.prototype.setValue = function setValue(value) {\r\n this.cancelIdleInit();\r\n this.value = value;\r\n };\r\n\r\n /**\r\n * @public\r\n *\r\n * noConflict: Returns control of NewHomeSource.Modules.IdleValue to the previous script.\r\n */\r\n IdleValue.noConflict = function noConflict() {\r\n global.NewHomeSource.Modules.IdleValue = previousIdleValue;\r\n return IdleValue;\r\n };\r\n\r\n global.NewHomeSource.Modules.IdleValue = IdleValue;\r\n}(window));\r\n","(function idleQueue(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Modules = global.NewHomeSource.Modules || {};\r\n\r\n if (!global.NewHomeSource.Modules.requestIdleCallback) {\r\n return;\r\n }\r\n\r\n const previousIdleQueue = global.NewHomeSource.idleQueue;\r\n const isSafari = !!(typeof global.safari === 'object' && global.safari.pushNotification);\r\n const minTaskTime = 10;\r\n const requestIdleCallbackFunction = global.NewHomeSource.Modules.requestIdleCallback.rIC;\r\n const cancelIdleCallbackFunction = global.NewHomeSource.Modules.requestIdleCallback.cIC;\r\n\r\n /**\r\n * @private\r\n * shouldYield: true if no deadline is defined or if the timeRemaining\r\n * is not greater than the minimumTaskTime, otherwise false.\r\n *\r\n * @param {number} deadline reamining time available from the request idle callback.\r\n * @param {number} minimumTaskTime minimum ramianing time available to execute the task.\r\n */\r\n function shouldYield(deadline, minimumTaskTime) {\r\n if (deadline <= minimumTaskTime) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * @private\r\n * scheduleTasksToRun: schedules the task queue to be processed.\r\n *\r\n * @param {boolean} retry true if the task should be enqueue in case of error, otherwise false.\r\n */\r\n function scheduleTasksToRun(retry) {\r\n if (this.idleCallbackHandle) {\r\n return;\r\n }\r\n\r\n // eslint-disable-next-line no-use-before-define\r\n this.idleCallbackHandle = requestIdleCallbackFunction(runTasks.bind(this, retry));\r\n }\r\n\r\n /**\r\n * @private\r\n * runTasks: runs as many tasks in the queue as it can before reaching the deadline.\r\n * If no deadline is pass, it will run all tasks.\r\n *\r\n * @param {boolean} retry true if the task should be enqueue in case of error, otherwise false.\r\n * @param {IdleDeadline} deadline input parameter to idle callbacks.\r\n */\r\n function runTasks(retry, deadline) {\r\n // Do not start processing the pending tasks until the DOM has reached the ready state.\r\n const isDomCompleted = global.document.readyState === 'complete';\r\n this.cancelScheduledRun();\r\n\r\n if (this.isProcessing) {\r\n return;\r\n }\r\n\r\n this.isProcessing = true;\r\n\r\n while (this.hasPendingTasks() && isDomCompleted) {\r\n const remainingTime = deadline ? deadline.timeRemaining() : 50;\r\n\r\n if (shouldYield(remainingTime, this.taskQueue[0].minTaskTime)) {\r\n break;\r\n }\r\n\r\n const taskToRun = this.taskQueue.shift();\r\n const isExecuted = taskToRun.task(taskToRun.state);\r\n const timeLapsed = +new Date() - taskToRun.state.time;\r\n\r\n if (!isExecuted && retry && timeLapsed < 15000) {\r\n this.pushTask(taskToRun.task, taskToRun.state.time);\r\n }\r\n }\r\n\r\n if (this.hasPendingTasks()) {\r\n if (isDomCompleted) {\r\n scheduleTasksToRun.call(this, retry);\r\n } else {\r\n window.addEventListener('load', scheduleTasksToRun.bind(this, retry));\r\n }\r\n }\r\n\r\n this.isProcessing = false;\r\n }\r\n\r\n /**\r\n * @public\r\n * onVisibilityChange: exectutes the pending tasks in a sync way when the page is hidden.\r\n */\r\n function onVisibilityChange() {\r\n if (document.visibilityState !== 'hidden') {\r\n return;\r\n }\r\n\r\n this.runTasksImmediately();\r\n }\r\n\r\n /**\r\n * @constructs NewHomeSource.Modules.IdleQueue\r\n */\r\n function IdleQueue(name) {\r\n this.idleCallbackHandle = null;\r\n this.taskQueue = [];\r\n this.isProcessing = false;\r\n this.id = name;\r\n\r\n if (isSafari) {\r\n global.addEventListener('beforeunload', IdleQueue.prototype.runTasksImmediately.bind(this), true);\r\n }\r\n\r\n global.addEventListener('visibilitychange', onVisibilityChange.bind(this), true);\r\n }\r\n\r\n /**\r\n * @public\r\n * cancelScheduledRun: cancels any scheduled idle callback and removes the handler.\r\n */\r\n IdleQueue.prototype.cancelScheduledRun = function cancelScheduledRun() {\r\n cancelIdleCallbackFunction(this.idleCallbackHandle);\r\n this.idleCallbackHandle = null;\r\n };\r\n\r\n /**\r\n * @public\r\n * hasPendingTasks: true if the queue still has tasks pending to run, otherwise false.\r\n */\r\n IdleQueue.prototype.hasPendingTasks = function hasPendingTasks() {\r\n return this.taskQueue.length > 0;\r\n };\r\n\r\n /**\r\n * @public\r\n *\r\n * pushTask: adds a new task to the idleQueue to be executed.\r\n * @param {function} task to be executed.\r\n * @param {number} time when the task was added to the queue.\r\n */\r\n IdleQueue.prototype.pushTask = function pushTask(task, time) {\r\n if (typeof task !== 'function') {\r\n return;\r\n }\r\n\r\n const taskToRun = {\r\n id: this.id,\r\n minTaskTime,\r\n task,\r\n state: {\r\n time: time || +new Date(),\r\n visibilityState: global.document.visibilityState\r\n }\r\n };\r\n\r\n this.taskQueue.push(taskToRun);\r\n scheduleTasksToRun.call(this, true);\r\n };\r\n\r\n /**\r\n * @public\r\n * runTasksImmediately: runs all the pending tasks in sync way.\r\n */\r\n IdleQueue.prototype.runTasksImmediately = function runTasksImmediately() {\r\n runTasks.call(this, false);\r\n };\r\n\r\n /**\r\n * @public\r\n *\r\n * noConflict: Returns control of NewHomeSource.Modules.IdleQueue to the previous script.\r\n */\r\n IdleQueue.noConflict = function noConflict() {\r\n global.NewHomeSource.Modules.IdleQueue = previousIdleQueue;\r\n return IdleQueue;\r\n };\r\n\r\n global.NewHomeSource.Modules.IdleQueue = IdleQueue;\r\n}(window));\r\n","(function eventTracker(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Analytics = global.NewHomeSource.Analytics || {};\r\n\r\n const previousEventTracker = global.NewHomeSource.Analytics.eventTracker;\r\n const configurations = {\r\n hasBeenAttached: false\r\n };\r\n const onTouchProperties = {\r\n startX: 0,\r\n startY: 0,\r\n distX: 0,\r\n distY: 0\r\n };\r\n\r\n function inspectEvent(event, target) {\r\n const inspectedElement = target || event.target;\r\n\r\n if (!inspectedElement || !inspectedElement.dataset || !inspectedElement.dataset.event) {\r\n if (inspectedElement.parentElement && inspectedElement.parentElement.tagName !== 'BODY') {\r\n inspectEvent(event, inspectedElement.parentElement);\r\n }\r\n\r\n return;\r\n }\r\n\r\n if (event.type === 'mousedown' && inspectedElement.dataset.eventType !== 'mousedown') {\r\n return;\r\n }\r\n\r\n if (event.type === 'touchend' && inspectedElement.dataset.eventType !== 'touchend') {\r\n return;\r\n }\r\n if (event.type === 'change' && inspectedElement.dataset.eventType !== 'change') {\r\n return;\r\n }\r\n\r\n const dataset = inspectedElement.dataset;\r\n\r\n for (let index = 0; index < configurations.totalHandlers; index += 1) {\r\n const handler = configurations.handlers[index].eventTracker;\r\n const validator = configurations.handlers[index].eventTrackerValidator;\r\n\r\n if (validator(dataset, inspectedElement)) {\r\n configurations.queue.pushTask(handler.bind(inspectedElement));\r\n }\r\n }\r\n\r\n if (inspectedElement.dataset.eventForget) {\r\n delete inspectedElement.dataset.event;\r\n }\r\n }\r\n\r\n /**\r\n * touchend event handler\r\n * @param {event} event The touchstart event\r\n */\r\n function onTouchStartEvent(event) {\r\n onTouchProperties.startX = event.changedTouches[0].pageX;\r\n onTouchProperties.startY = event.changedTouches[0].pageY;\r\n }\r\n\r\n /**\r\n * touchend event handler\r\n * @param {event} event The touchend event\r\n */\r\n function onTouchEndEvent(event) {\r\n onTouchProperties.distX = event.changedTouches[0].pageX - onTouchProperties.startX;\r\n onTouchProperties.distY = event.changedTouches[0].pageY - onTouchProperties.startY;\r\n\r\n if (Math.abs(onTouchProperties.distX) >= 7 || Math.abs(onTouchProperties.distY) >= 10) {\r\n return;\r\n }\r\n\r\n inspectEvent(event);\r\n }\r\n\r\n /**\r\n * on change event handler\r\n * @param {event} event The on change event\r\n */\r\n function onChangeEvent(event) {\r\n let inspectedElement = event.target;\r\n\r\n if (!inspectedElement) {\r\n return;\r\n }\r\n\r\n if (inspectedElement.nodeName === 'SELECT') {\r\n inspectedElement = inspectedElement[inspectedElement.selectedIndex];\r\n }\r\n\r\n inspectEvent(event, inspectedElement);\r\n }\r\n\r\n /**\r\n * @constructs NewHomeSource.Analytics.EventTracker;\r\n *\r\n * @param {IdleQueue} eventsQueue that runs the tasks on idle periods.\r\n * @param {Array} handlers that will react to the impression tracking.\r\n */\r\n function EventTracker(eventsQueue, handlers) {\r\n configurations.queue = eventsQueue;\r\n configurations.handlers = [];\r\n\r\n const totalHandlers = handlers.length;\r\n\r\n for (let index = 0; index < totalHandlers; index += 1) {\r\n if (handlers[index] &&\r\n typeof handlers[index].eventTracker === 'function' &&\r\n typeof handlers[index].eventTrackerValidator === 'function') {\r\n configurations.handlers.push(handlers[index]);\r\n }\r\n }\r\n\r\n configurations.totalHandlers = configurations.handlers.length;\r\n }\r\n\r\n /**\r\n * @public\r\n * init: attaches a event listeners to the mousedown and click events.\r\n */\r\n EventTracker.init = function init() {\r\n if (configurations.hasBeenAttached) {\r\n return;\r\n }\r\n\r\n configurations.hasBeenAttached = true;\r\n\r\n // As in some places of the code developers break the bubbling behavior we listen for both events\r\n // mousedown and click. Only one of them will be handled, click as default and mousedown\r\n // when indicated as data attribute.\r\n document.addEventListener('touchstart', onTouchStartEvent, { passive: true });\r\n document.addEventListener('touchend', onTouchEndEvent, { passive: true });\r\n document.addEventListener('mousedown', inspectEvent, { composed: true, useCapture: true });\r\n document.addEventListener('click', inspectEvent, { composed: true, useCapture: true });\r\n document.addEventListener('change', onChangeEvent, { composed: true, useCapture: true });\r\n };\r\n\r\n /**\r\n * @public\r\n *\r\n * noConflict: Returns control of NewHomeSource.Analytics.eventTracker to the previous script.\r\n */\r\n EventTracker.noConflict = function noConflict() {\r\n global.NewHomeSource.Analytics.eventTracker = previousEventTracker;\r\n return EventTracker;\r\n };\r\n\r\n global.NewHomeSource.Analytics.eventTracker = EventTracker;\r\n}(window));\r\n","(function identityTracker(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Analytics = global.NewHomeSource.Analytics || {};\r\n\r\n const previousIdentityTracker = global.NewHomeSource.Analytics.identityTracker;\r\n const configurations = {\r\n hasBeenAttached: false\r\n };\r\n\r\n /**\r\n * @private\r\n * closestForm: finds the closes Form element that contains the given inspectedElement.\r\n *\r\n * @param {HTMLNodeElement} inspectedElement which parents are being analyzed.\r\n */\r\n function closestForm(inspectedElement) {\r\n if (inspectedElement.tagName === 'FORM') {\r\n return inspectedElement;\r\n }\r\n\r\n if (inspectedElement.parentElement && inspectedElement.parentElement.tagName !== 'BODY') {\r\n return closestForm(inspectedElement.parentElement);\r\n }\r\n\r\n return null;\r\n }\r\n\r\n function inspectEvent(event, target) {\r\n const inspectedElement = target || event.target;\r\n\r\n if (!inspectedElement || !inspectedElement.dataset || !inspectedElement.dataset.identity || event.button !== 0) {\r\n if (inspectedElement.parentElement && inspectedElement.parentElement.tagName !== 'BODY') {\r\n inspectEvent(event, inspectedElement.parentElement);\r\n }\r\n\r\n return;\r\n }\r\n\r\n if (event.type === 'mousedown' && inspectedElement.dataset.eventType !== 'mousedown') {\r\n return;\r\n }\r\n\r\n const dataset = inspectedElement.dataset;\r\n const form = closestForm(inspectedElement);\r\n\r\n if (!form || !form.reportValidity()) {\r\n return;\r\n }\r\n\r\n const data = {\r\n caller: inspectedElement.cloneNode(true),\r\n form: form.cloneNode(true)\r\n };\r\n\r\n for (let index = 0; index < configurations.totalHandlers; index += 1) {\r\n const handler = configurations.handlers[index].identityTracker;\r\n const validator = configurations.handlers[index].identityTrackerValidator;\r\n\r\n if (validator(dataset)) {\r\n configurations.queue.pushTask(handler.bind(data));\r\n }\r\n }\r\n\r\n if (inspectedElement.dataset.eventForget) {\r\n delete inspectedElement.dataset.event;\r\n }\r\n }\r\n\r\n /**\r\n * @constructs NewHomeSource.Analytics.IdentityTracker;\r\n *\r\n * @param {IdleQueue} eventsQueue that runs the tasks on idle periods.\r\n * @param {Array} handlers that will react to the impression tracking.\r\n */\r\n function IdentityTracker(eventsQueue, handlers) {\r\n configurations.queue = eventsQueue;\r\n configurations.handlers = [];\r\n\r\n const totalHandlers = handlers.length;\r\n\r\n for (let index = 0; index < totalHandlers; index += 1) {\r\n if (handlers[index] &&\r\n typeof handlers[index].identityTracker === 'function' &&\r\n typeof handlers[index].identityTrackerValidator === 'function') {\r\n configurations.handlers.push(handlers[index]);\r\n }\r\n }\r\n\r\n configurations.totalHandlers = configurations.handlers.length;\r\n }\r\n\r\n /**\r\n * @public\r\n * init: attaches a event listeners to the mousedown and click events.\r\n */\r\n IdentityTracker.init = function init() {\r\n if (configurations.hasBeenAttached) {\r\n return;\r\n }\r\n\r\n configurations.hasBeenAttached = true;\r\n\r\n // As in some places of the code developers break the bubbling behavior we listen for both events\r\n // mousedown and click. Only one of them will be handled, click as default and mousedown\r\n // when indicated as data attribute.\r\n document.addEventListener('mousedown', inspectEvent, { composed: true, useCapture: true });\r\n document.addEventListener('click', inspectEvent, { composed: true, useCapture: true });\r\n };\r\n\r\n /**\r\n * @public\r\n *\r\n * noConflict: Returns control of NewHomeSource.Analytics.eventTracker to the previous script.\r\n */\r\n IdentityTracker.noConflict = function noConflict() {\r\n global.NewHomeSource.Analytics.identityTracker = previousIdentityTracker;\r\n return IdentityTracker;\r\n };\r\n\r\n global.NewHomeSource.Analytics.identityTracker = IdentityTracker;\r\n}(window));\r\n","(function impressionTracker(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Modules = global.NewHomeSource.Modules || {};\r\n\r\n const previousImpressionTracker = global.NewHomeSource.Analytics.impressionTracker;\r\n const configurations = {\r\n hasBeenAttached: false,\r\n mutationObserverOptions: {\r\n childList: true,\r\n subtree: true,\r\n },\r\n intersectionObserverOptions: {\r\n threshold: 0.5\r\n },\r\n };\r\n\r\n /**\r\n * @private\r\n * Iterates through all descends of a DOM node and pushes them to the nodes list.\r\n *\r\n * @param {Node} node The DOM node to walk.\r\n */\r\n function walkNodeTree(node) {\r\n let elementsAdded = [];\r\n\r\n if (node.nodeType === 1 && node.dataset && node.dataset.impression) {\r\n elementsAdded.push(node);\r\n }\r\n\r\n const childNodesLength = node.childNodes.length;\r\n\r\n for (let index = 0; index < childNodesLength; index += 1) {\r\n const child = node.childNodes[index];\r\n const childElements = walkNodeTree(child);\r\n\r\n if (childElements.length > 0) {\r\n elementsAdded = [].concat(elementsAdded, childElements);\r\n }\r\n }\r\n\r\n return elementsAdded;\r\n }\r\n\r\n /**\r\n * @private\r\n * handleDomMutations: callback to be execute after an element has been added to the DOM.\r\n *\r\n * @param {Array} mutations a list of MutationRecord intstances.\r\n */\r\n function handleDomMutations(mutations) {\r\n if (!mutations) {\r\n return;\r\n }\r\n\r\n let elementsAdded = [];\r\n const mutationsLength = mutations.length;\r\n\r\n for (let index = 0; index < mutationsLength; index += 1) {\r\n const mutation = mutations[index];\r\n const totalElementsAdded = mutation.addedNodes ? mutation.addedNodes.length : 0;\r\n\r\n for (let elementIndex = 0; elementIndex < totalElementsAdded; elementIndex += 1) {\r\n const addedElement = mutation.addedNodes[elementIndex];\r\n const impressionNodes = walkNodeTree(addedElement);\r\n\r\n if (impressionNodes.length > 0) {\r\n elementsAdded = [].concat(elementsAdded, impressionNodes);\r\n }\r\n }\r\n }\r\n\r\n if (elementsAdded.length === 0) {\r\n return;\r\n }\r\n\r\n for (let currentElement = 0; currentElement < elementsAdded.length; currentElement += 1) {\r\n configurations.intersectionObserver.observe(\r\n elementsAdded[currentElement],\r\n configurations.intersectionObserverOptions\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * handleDomMutations: callback to be execute after an element has been added to the DOM.\r\n *\r\n * @param {Array} mutations a list of MutationRecord intstances.\r\n */\r\n function handleMutationsOnViewPort(mutations) {\r\n if (!mutations) {\r\n return;\r\n }\r\n\r\n const elements = [];\r\n let currentMutation;\r\n for (let index = 0; index < mutations.length; index += 1) {\r\n currentMutation = mutations[index];\r\n if (currentMutation.isIntersecting) {\r\n elements.push(currentMutation.target);\r\n if (currentMutation.target.dataset.noUnobserve !== 'true') {\r\n configurations.intersectionObserver.unobserve(currentMutation.target);\r\n }\r\n }\r\n }\r\n if (elements.length > 0) {\r\n let trackertElements = [];\r\n for (let index = 0; index < configurations.totalHandlers; index += 1) {\r\n const handler = configurations.handlers[index];\r\n const selector = configurations.handlers[index].impressionTrackerSelector();\r\n for (let count = 0; count < elements.length; count += 1) {\r\n const element = elements[count];\r\n if (typeof selector === 'string' && element.getAttribute(selector) !== null) {\r\n trackertElements.push(element);\r\n }\r\n }\r\n if (trackertElements.length > 0) {\r\n configurations.queue.pushTask(handler.impressionTracker.bind(trackertElements));\r\n }\r\n trackertElements = [];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * handleMutationsAsync: callback to be execute after an element has been added to the DOM async.\r\n *\r\n * @param {Array} mutations a list of MutationRecord intstances.\r\n */\r\n function handleMutationsAsync(mutations) {\r\n setTimeout(() => handleDomMutations(mutations), 0);\r\n }\r\n\r\n /**\r\n * @constructs NewHomeSource.Analytics.impressionTracker\r\n *\r\n * @param {IdleQueue} eventsQueue that runs the tasks on idle periods.\r\n * @param {Array} handlers that will react to the impression tracking.\r\n */\r\n function ImpressionTracker(eventsQueue, handlers) {\r\n if (!global.MutationObserver) {\r\n return;\r\n }\r\n\r\n configurations.queue = eventsQueue;\r\n configurations.handlers = [];\r\n\r\n const totalHandlers = handlers.length;\r\n\r\n for (let index = 0; index < totalHandlers; index += 1) {\r\n if (handlers[index] &&\r\n typeof handlers[index].impressionTracker === 'function' &&\r\n typeof handlers[index].impressionTrackerSelector === 'function') {\r\n configurations.handlers.push(handlers[index]);\r\n }\r\n }\r\n\r\n configurations.totalHandlers = configurations.handlers.length;\r\n }\r\n\r\n /**\r\n * @public\r\n * init: creates a new MutationObserver to observe changes in the body of the document.\r\n */\r\n ImpressionTracker.init = function init() {\r\n if (configurations.hasBeenAttached) {\r\n return;\r\n }\r\n\r\n configurations.hasBeenAttached = true;\r\n configurations.mutationObserver = new global.MutationObserver(handleMutationsAsync);\r\n configurations.intersectionObserver = new global.IntersectionObserver(handleMutationsOnViewPort);\r\n configurations.mutationObserver.observe(global.document.body, configurations.mutationObserverOptions);\r\n\r\n for (let index = 0; index < configurations.totalHandlers; index += 1) {\r\n const handler = configurations.handlers[index];\r\n const elements = document.querySelectorAll('[' + handler.impressionTrackerSelector() + ']');\r\n for (let currentElement = 0; currentElement < elements.length; currentElement += 1) {\r\n configurations.intersectionObserver.observe(\r\n elements[currentElement],\r\n configurations.intersectionObserverOptions\r\n );\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * @public\r\n *\r\n * noConflict: Returns control of NewHomeSource.SampleModule to the previous script.\r\n */\r\n ImpressionTracker.noConflict = function noConflict() {\r\n global.NewHomeSource.Analytics.impressionTracker = previousImpressionTracker;\r\n return ImpressionTracker;\r\n };\r\n\r\n global.NewHomeSource.Analytics.impressionTracker = ImpressionTracker;\r\n}(window));\r\n","(function onDemandTracker(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Analytics = global.NewHomeSource.Analytics || {};\r\n\r\n const previousOnDemandTracker = global.NewHomeSource.Analytics.OnDemandTracker;\r\n const configurations = {\r\n hasBeenAttached: false\r\n };\r\n\r\n /**\r\n * @constructs NewHomeSource.Analytics.onDemandTracker;\r\n *\r\n * @param {IdleQueue} eventsQueue that runs the tasks on idle periods.\r\n * @param {Array} handlers that will react to the impression tracking.\r\n */\r\n function OnDemandTracker(eventsQueue, handlers) {\r\n configurations.queue = eventsQueue;\r\n configurations.handlers = [];\r\n\r\n const totalHandlers = handlers.length;\r\n\r\n for (let index = 0; index < totalHandlers; index += 1) {\r\n if (handlers[index] &&\r\n typeof handlers[index].onDemandTracker === 'function') {\r\n configurations.handlers.push(handlers[index]);\r\n }\r\n }\r\n\r\n configurations.totalHandlers = configurations.handlers.length;\r\n }\r\n\r\n /**\r\n * @public\r\n * init: creates a new MutationObserver to observe changes in the body of the document.\r\n * Sets up a listener in the document.body for on demand events.\r\n */\r\n OnDemandTracker.init = function init() {\r\n if (configurations.hasBeenAttached) {\r\n return;\r\n }\r\n\r\n configurations.hasBeenAttached = true;\r\n\r\n document.body.addEventListener('trackOnDemandEvent', (event) => {\r\n for (let index = 0; index < configurations.totalHandlers; index += 1) {\r\n const handler = configurations.handlers[index].onDemandTracker;\r\n const validator = configurations.handlers[index].onDemandTrackerValidator;\r\n if (typeof validator === 'function' && validator(event.detail.data)) {\r\n configurations.queue.pushTask(handler.bind(event.detail.data));\r\n }\r\n }\r\n });\r\n };\r\n\r\n /**\r\n * @public\r\n *\r\n * noConflict: Returns control of NewHomeSource.Analytics.onDemandTracker to the previous script.\r\n */\r\n OnDemandTracker.noConflict = function noConflict() {\r\n global.NewHomeSource.Analytics.onDemandTracker = previousOnDemandTracker;\r\n return OnDemandTracker;\r\n };\r\n\r\n global.NewHomeSource.Analytics.onDemandTracker = OnDemandTracker;\r\n}(window));\r\n","/**\r\n * If you need to add a new tracker for Facelift NHS.\r\n */\r\n(function index(global) {\r\n 'use strict';\r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n global.NewHomeSource.Analytics = global.NewHomeSource.Analytics || {};\r\n\r\n if (!global.NewHomeSource.Analytics.impressionTracker ||\r\n !global.NewHomeSource.Analytics.identityTracker ||\r\n !global.NewHomeSource.Analytics.eventTracker ||\r\n !global.NewHomeSource.Modules.IdleQueue ||\r\n !global.NewHomeSource.Modules.IdleValue\r\n ) {\r\n return;\r\n }\r\n\r\n const nhsTrackingId = 'UA-40843711-4';\r\n\r\n function getGoogleAnalyticsClientId() {\r\n let googleAnalyticsId;\r\n\r\n if (global.ga && global.ga.getAll) {\r\n const trackers = global.ga.getAll().filter((element) => element.get('trackingId') === nhsTrackingId);\r\n googleAnalyticsId = trackers[0].get('clientId');\r\n }\r\n\r\n return googleAnalyticsId;\r\n }\r\n\r\n function getUserId() {\r\n return localStorage.getItem('UserId');\r\n }\r\n\r\n function getVisitedMpcIds() {\r\n return global.NewHomeSource.WebStorageHandler.getSessionStorageItem('visitedMpcIds');\r\n }\r\n\r\n function startTracking() {\r\n global.NewHomeSource.Analytics.eventTracker.init();\r\n global.NewHomeSource.Analytics.identityTracker.init();\r\n global.NewHomeSource.Analytics.impressionTracker.init();\r\n global.NewHomeSource.Analytics.onDemandTracker.init();\r\n }\r\n\r\n const eventsQueue = new global.NewHomeSource.Modules.IdleQueue();\r\n\r\n const handlers = [];\r\n const globalValues = {\r\n googleAnalyticsClientId: new global.NewHomeSource.Modules.IdleValue(getGoogleAnalyticsClientId),\r\n googleAnalyticsUserId: new global.NewHomeSource.Modules.IdleValue(getUserId),\r\n visitedMpcIds: getVisitedMpcIds,\r\n };\r\n\r\n handlers.push(global.NewHomeSource.Analytics.TdvTracker);\r\n handlers.push(global.NewHomeSource.Analytics.GoogleAnalyticsTracker);\r\n global.NewHomeSource.Analytics.eventTracker(eventsQueue, handlers);\r\n global.NewHomeSource.Analytics.identityTracker(eventsQueue, handlers);\r\n global.NewHomeSource.Analytics.impressionTracker(eventsQueue, handlers);\r\n global.NewHomeSource.Analytics.onDemandTracker(eventsQueue, handlers);\r\n global.NewHomeSource.Analytics.TdvTracker(globalValues);\r\n global.NewHomeSource.Analytics.GoogleAnalyticsTracker(globalValues);\r\n\r\n if (global.document.readyState === 'complete') {\r\n startTracking();\r\n } else {\r\n document.addEventListener('DOMContentLoaded', startTracking);\r\n }\r\n}(window));\r\n"]}