-
-
Save sahava/baee63650eed471a2d1eac5825037a05 to your computer and use it in GitHub Desktop.
(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 oldPush = window[dataLayerName].push, | |
containerId = {{Container ID}}; | |
// 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; | |
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; | |
} | |
} | |
} | |
}; | |
var getODataModel = function() { | |
return window.google_tag_manager[containerId].dataLayer.get({split: function() { return []; }}); | |
}; | |
// **Initialize upon first load** | |
// Build the history array from local storage | |
var dHistory = window._dataLayerHistory = JSON.parse( | |
window.localStorage.getItem('_dataLayerHistory') || '{}' | |
); | |
// Method to reset the history array to the current page state only | |
dHistory.reset = function() { | |
dHistory.timeout = new Date().getTime() + timeout; | |
dHistory.history = backfillHistory(); | |
for (var prop in dHistory.model) { | |
if (dHistory.model.hasOwnProperty(prop) && prop !== 'get') { | |
delete dHistory.model[prop]; | |
} | |
} | |
mergeStates(getODataModel(), dHistory.model); | |
window.localStorage.setItem('_dataLayerHistory', JSON.stringify(dHistory)); | |
}; | |
// If initial load | |
if (!dHistory.timeout) { | |
dHistory.timeout = new Date().getTime() + timeout; | |
dHistory.history = []; | |
dHistory.model = {}; | |
} | |
dHistory.history = dHistory.history.concat(backfillHistory()); | |
mergeStates(getODataModel(), dHistory.model); | |
// If timeout is reached, reset the history array | |
if (dHistory.hasOwnProperty('timeout') && dHistory.timeout < (new Date().getTime())) { | |
dHistory.reset(); | |
} | |
// 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; | |
}; | |
// Write the new history into localStorage | |
window.localStorage.setItem('_dataLayerHistory', JSON.stringify(dHistory)); | |
window[dataLayerName].push = function() { | |
try { | |
// Initial settings | |
var states = [].slice.call(arguments, 0), | |
timeNow = new Date().getTime(), | |
results = oldPush.apply(window[dataLayerName], states), | |
oDataLayer = window[dataLayerName], | |
oDataModel = getODataModel(); | |
// If timeout is reached, reset the history array | |
if (dHistory.hasOwnProperty('timeout') && dHistory.timeout < (new Date().getTime())) { | |
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; | |
} | |
}; | |
})(); |
Thank you very much, but how to use it?
There is an article explaining this step-by-step here: https://www.simoahava.com/analytics/persist-datalayer-across-pages/
I am not able to retrieve data of a previous page if I push the data to the dataLayer via form submit event.
This is what I am getting:
VM585:4 Problem interacting with dataLayer history: TypeError: Converting circular structure to JSON
--> starting at object with constructor 'HTMLFormElement'
| property 'jQuery351089137954889473742' -> object with constructor 'Object'
| property '.wForm' -> object with constructor 'Object'
| property 'form' -> object with constructor 'S.fn.init'
--- property '0' closes the circle
Hi everyone,
Is there a possibility that if the website uses a pop-up form, the persistent data layer will not work? Because I can see the value of the variable before the page reloads. Once it reloads, the value is no longer there.
Thank you very much, but how to use it?