-
-
Save LCHCAPITALHUMAIN/cf460372d532248fe26d4cd11a100023 to your computer and use it in GitHub Desktop.
JavaScript for persisting dataLayer array and data model composition across pages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
// Set the timeout for when the dataLayer history should be purged. The default is 30 minutes. | |
// The timeout needs to be in milliseconds. | |
var timeout = 30*60*1000; | |
// Change dataLayerName only if you've defined another named for the dataLayer array in your | |
// GTM container snippet. | |
var dataLayerName = 'dataLayer'; | |
// Don't change anything below. | |
// Initial settings | |
var initialLoad = true, | |
oldPush = window[dataLayerName].push; | |
// Method to copy items from dataLayer from before the GTM container snippet was loaded. | |
var backfillHistory = function() { | |
var tempHistory = [], | |
i = 0, | |
len = window[dataLayerName].length - 1; | |
for (; i < len; i++) { | |
tempHistory.push(window[dataLayerName][i]); | |
} | |
return tempHistory; | |
}; | |
// Method to check if object is a plain object. | |
// From https://bit.ly/2A3Fuqe | |
var isPlainObject = function(value) { | |
if (!value || typeof value !== 'object' || // Nulls, dates, etc. | |
value.nodeType || // DOM nodes. | |
value === value.window) { // Window objects. | |
return false; | |
} | |
try { | |
if (value.constructor && !value.hasOwnProperty('constructor') && | |
!value.constructor.prototype.hasOwnProperty('isPrototypeOf')) { | |
return false; | |
} | |
} catch (e) { | |
return false; | |
} | |
var key; | |
for (key in value) {} | |
return key === undefined || value.hasOwnProperty(key); | |
}; | |
// Method to merge the stored data model and the history model together. | |
// From https://bit.ly/2FrPQWL | |
var mergeStates = function(storedModel, historyModel) { | |
for (var property in storedModel) { | |
if (storedModel.hasOwnProperty(property)) { | |
var storedProperty = storedModel[property]; | |
if (Array.isArray(storedProperty)) { | |
if (!Array.isArray(historyModel[property])) historyModel[property] = []; | |
mergeStates(storedProperty, historyModel[property]); | |
} else if (isPlainObject(storedProperty)) { | |
if (!isPlainObject(historyModel[property])) historyModel[property] = {}; | |
mergeStates(storedProperty, historyModel[property]); | |
} else { | |
historyModel[property] = storedProperty; | |
} | |
} | |
} | |
}; | |
window[dataLayerName].push = function() { | |
try { | |
// Build the history array from local storage | |
window._dataLayerHistory = JSON.parse( | |
window.localStorage.getItem('_dataLayerHistory') || | |
'{"timeout": null, "history": [], "model": {}}' | |
); | |
// Initial settings | |
var timeNow = new Date().getTime(), | |
states = [].slice.call(arguments, 0), | |
results = oldPush.apply(window[dataLayerName], states), | |
oDataLayer = window[dataLayerName], | |
dHistory = window._dataLayerHistory, | |
oDataModel = window.google_tag_manager[{{Container ID}}][dataLayerName].get({split: function() { return []; }}); | |
// Method to reset the history array to the current page state only | |
dHistory.reset = function() { | |
dHistory.timeout = null; | |
dHistory.history = backfillHistory(); | |
dHistory.model = {}; | |
mergeStates(oDataModel, dHistory.model); | |
window.localStorage.setItem('_dataLayerHistory', JSON.stringify(dHistory)); | |
}; | |
// From https://bit.ly/2A2ZcCG | |
dHistory.model.get = function(key) { | |
var target = dHistory.model; | |
var split = key.split('.'); | |
for (var i = 0; i < split.length; i++) { | |
if (target[split[i]] === undefined) return undefined; | |
target = target[split[i]]; | |
} | |
return target; | |
}; | |
// Add history if this is the initialization event itself | |
if (initialLoad) { | |
dHistory.history = dHistory.history.concat(backfillHistory()); | |
initialLoad = false; | |
} | |
// If timeout is reached, reset the history array | |
if (dHistory.hasOwnProperty('timeout') && dHistory.timeout < timeNow) { | |
dHistory.reset(); | |
} | |
// Push latest item from dataLayer into the history array | |
dHistory.history.push(oDataLayer[oDataLayer.length-1]); | |
// Merge GTM's data model with the history model | |
mergeStates(oDataModel, dHistory.model); | |
// Update the timeout | |
dHistory.timeout = timeNow + timeout; | |
// Write the new history into localStorage | |
window.localStorage.setItem('_dataLayerHistory', JSON.stringify(dHistory)); | |
return results; | |
} catch(e) { | |
console.log('Problem interacting with dataLayer history: ' + e); | |
var states = [].slice.call(arguments, 0), | |
results = oldPush.apply(window[dataLayerName], states); | |
return results; | |
} | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment