ACTUALIZACIÓN 4 de junio de 2020:En lugar de copiar el código HTML personalizado del artículo, cárguelo desde el Gist de GitHub en cambio.
Hace cuatro años escribí un artículo sobre Cómo conservar los GTM dataLayer
De página en página. Desafortunadamente, la solución fue un poco torpe, requiriendo que usted proporcione información específica. Comandos para las interacciones, lo que lo hizo realmente difícil de manejar a largo plazo. Administrador de etiquetas de Google Todavía no nos ofrece una forma nativa de persistir. dataLayer
matriz o su modelo de datos internos de una página a otra, así que pensé que ya period hora de volver a tratar esta thought.
Esta vez no habrá una API interactuar con ellos. En cambio, la solución simplemente almacenará el contenido del dataLayer
matriz Y el modelo de datos interno de página a página, hasta que el usuario no haya interactuado con GTM dataLayer
por un período de tiempo determinado.
incógnita
El boletín informativo de Simmer
Suscríbete a la Boletín informativo de Simmer ¡Para recibir las últimas noticias y contenidos de Simo Ahava en tu bandeja de entrada de correo electrónico!
Configurandolo
Para configurarlo, debes crear una etiqueta HTML personalizada, en la que copiarás el siguiente código. Si lo deseas, también puedes copiar el código de Esta esencia.
ACTUALIZACIÓN 4 de junio de 2020: Por favor copie el código del esencia Enlace anterior en lugar de desde el artículo siguiente. La esencia se mantiene actualizada y tiene correcciones de estabilidad que ayudan a resolver algunos problemas que los usuarios han tenido con la solución.
El código de etiqueta HTML personalizado
<script>
(perform() {
// Set the timeout for when the dataLayer historical past needs to be purged. The default is half-hour.
// The timeout must be in milliseconds.
var timeout = 30*60*1000;
// Change dataLayerName provided that you've got outlined one other named for the dataLayer array in your
// GTM container snippet.
var dataLayerName = 'dataLayer';
// Do not change something beneath.
// Preliminary settings
var initialLoad = true,
oldPush = window(dataLayerName).push;
// Methodology to repeat gadgets from dataLayer from earlier than the GTM container snippet was loaded.
var backfillHistory = perform() {
var tempHistory = (),
i = 0,
len = window(dataLayerName).size - 1;
for (; i < len; i++) {
tempHistory.push(window(dataLayerName)(i));
}
return tempHistory;
};
// Methodology to verify if object is a plain object.
// From https://bit.ly/2A3Fuqe
var isPlainObject = perform(worth) {
if (!worth || typeof worth !== 'object' || // Nulls, dates, and so on.
worth.nodeType || // DOM nodes.
worth === worth.window) { // Window objects.
return false;
}
strive {
if (worth.constructor && !worth.hasOwnProperty('constructor') &&
!worth.constructor.prototype.hasOwnProperty('isPrototypeOf')) {
return false;
}
} catch (e) {
return false;
}
var key;
for (key in worth) {}
return key === undefined || worth.hasOwnProperty(key);
};
// Methodology to merge the saved knowledge mannequin and the historical past mannequin collectively.
// From https://bit.ly/2FrPQWL
var mergeStates = perform(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 = perform() {
strive {
// Construct the historical past array from native storage
window._dataLayerHistory = JSON.parse(
window.localStorage.getItem('_dataLayerHistory') ||
'{"timeout": null, "historical past": (), "mannequin": {}}'
);
// Preliminary settings
var timeNow = new Date().getTime(),
states = ().slice.name(arguments, 0),
outcomes = oldPush.apply(window(dataLayerName), states),
oDataLayer = window(dataLayerName),
dHistory = window._dataLayerHistory,
oDataModel = window.google_tag_manager({{Container ID}}).dataLayer.get({break up: perform() { return (); }});
// Methodology to reset the historical past array to the present web page state solely
dHistory.reset = perform() {
dHistory.timeout = null;
dHistory.historical past = backfillHistory();
dHistory.mannequin = {};
mergeStates(oDataModel, dHistory.mannequin);
window.localStorage.setItem('_dataLayerHistory', JSON.stringify(dHistory));
};
// From https://bit.ly/2A2ZcCG
dHistory.mannequin.get = perform(key) {
var goal = dHistory.mannequin;
var break up = key.break up('.');
for (var i = 0; i < break up.size; i++) {
if (goal(break up(i)) === undefined) return undefined;
goal = goal(break up(i));
}
return goal;
};
// Add historical past if that is the initialization occasion itself
if (initialLoad) {
dHistory.historical past = dHistory.historical past.concat(backfillHistory());
initialLoad = false;
}
// If timeout is reached, reset the historical past array
if (dHistory.hasOwnProperty('timeout') && dHistory.timeout < timeNow) {
dHistory.reset();
}
// Push newest merchandise from dataLayer into the historical past array
dHistory.historical past.push(oDataLayer(oDataLayer.length-1));
// Merge GTM's knowledge mannequin with the historical past mannequin
mergeStates(oDataModel, dHistory.mannequin);
// Replace the timeout
dHistory.timeout = timeNow + timeout;
// Write the brand new historical past into localStorage
window.localStorage.setItem('_dataLayerHistory', JSON.stringify(dHistory));
return outcomes;
} catch(e) {
console.log('Downside interacting with dataLayer historical past: ' + e);
var states = ().slice.name(arguments, 0),
outcomes = oldPush.apply(window(dataLayerName), states);
return outcomes;
}
};
})();
script>
Al comienzo del fragmento, hay dos variables cuyos valores debes modificar.
var timeout = 30*60*1000;
La línea anterior establece la se acabó el tiempo para el almacenamiento native. Esto significa que una vez que el usuario no haya interactuado con dataLayer
Mientras se establezca el tiempo de espera, el historial se restablecerá para comenzar desde la página precise. El valor predeterminado es 30 minutosy si desea modificarlo asegúrese de configurar el tiempo de espera en milisegundoscomo en el valor predeterminado.
var dataLayerName="dataLayer";
La línea de arriba es el nombre de la dataLayer
matriz que utiliza Google Tag Supervisor y, de forma predeterminada, el fragmento de contenedor sin modificar. Si ha cambiado el dataLayer
nombre en el fragmento del contenedor, asegúrese de que se actualice aquí también.
Otras configuraciones de etiquetas
Además de copiar y pegar el código anterior, configure el Prioridad de etiquetas valor para 9999
o cualquier número que sea mayor que cualquier otra Prioridad de etiqueta para las etiquetas que se activan en el disparador Todas las páginas.
Desencadenar
Establezca esta etiqueta HTML personalizada para que se energetic en el Todas las páginas Activador. Quiere que sea la primera etiqueta que se energetic en la página. Naturalmente, si tiene etiquetas que se activan en un evento que se envía a dataLayer
Antes del fragmento de contenedor de Google Tag Supervisor, debe asegurarse de que esta etiqueta se energetic en eso disparador en su lugar.
Cómo funciona
Siempre que se introduce algo dataLayer
también se introduce en una nueva matriz bajo window._dataLayerHistory
Este es un objeto world y puedes acceder a él desde cualquier lugar de la página, incluidas las etiquetas HTML personalizadas y las variables JavaScript personalizadas de GTM.
Además de agregarse a esta matriz de historial, esta matriz también se escribe de manera consistente en el window.localStorage
estructura, que persiste en todas las páginas hasta que el usuario resolve borrar el almacenamiento de su navegador.
En resumen, hay una nueva window._dataLayerHistory
objeto que contiene información sobre todos los elementos introducidos dataLayer
en todas las páginas y puedes acceder a este objeto desde cualquier contexto de JavaScript en la página.
La matriz de historia
La matriz en sí, que representa la historia de la window.dataLayer
matriz, se puede encontrar en window._dataLayerHistory.historical past
.
Cuando la etiqueta HTML personalizada se carga por primera vez en cualquier página, esta matriz de historial se carga primero. rellenado con elementos de la actualidad window.dataLayer
que se enviaron antes de que se activara la etiqueta HTML personalizada. Esto es necesario porque la etiqueta HTML personalizada crea su propia .push()
oyente sólo cuando se dispara, momento en el que el window.dataLayer
La matriz ya contendrá elementos.
Una cosa peculiar que podrías notar es que si hay un window.dataLayer.push()
llamada que se lleva a cabo en un secuencia de etiquetasel objeto introducido en la matriz de historial no contendrá el gtm.uniqueEventId
Clave. Lamentablemente, no hay mucho que pueda hacer al respecto, pero no debería ser un gran problema.
El modelo de datos
Si no estás familiarizado con Modelo de datos de GTMes esencialmente una tabla de búsqueda en la que GTM copia y fusiona los pares clave-valor que ingresas en la dataLayer
formación.
Es importante comprender esta distinción, porque GTM utiliza el modelo de datos interno para Variables de la capa de datos.
El modelo de datos también se conserva de página a página en window._dataLayerHistory.mannequin
Este objeto tiene una get()
método que puede utilizar para obtener valores del modelo de datos, tal como lo hace la interfaz nativa de GTM:
window._dataLayerHistory.mannequin.get('someOldVariableFromAPreviousPage');
Esto podría ser útil. Por ejemplo, si su sitio escribe en dataLayer
algo como {userLoggedIn: true}
cuando el usuario inicia sesión en el sitio, pero solo lo hace cuando el usuario inicia sesión, puede obtener este valor en páginas posteriores consultando el objeto de historial:
window._dataLayerHistory.mannequin.get('userLoggedIn');
El modelo histórico aplica el mismo tipo de fusión recursiva que GTM hace con su modelo de datos interno. Esto podría generar resultados inesperados con objetos y matrices, así que asegúrese de leer sobre fusión recursiva Antes de continuar.
Reiniciar
También puedes restablecer el historial ejecutando este comando:
window._dataLayerHistory.reset();
Esto anula el tiempo de espera y restablece la matriz de historial y el modelo de historial a los estados de la página precise, eliminando así cualquier historial de ambos. También restablece el objeto almacenado en el almacenamiento del navegador a este estado de restablecimiento.
Aplicaciones
Hay muchas cosas que puedes hacer con un persistente dataLayer
y modelo de datos. A continuación se muestran algunos ejemplos.
Obtener el número de páginas cargadas
Para identificar cuántas páginas ha visitado el usuario, puede tener una variable JavaScript personalizada que haga esto:
perform() {
return window._dataLayerHistory.historical past.filter(perform(obj) { return obj.occasion === 'gtm.js'; }).size;
}
Esto devuelve el número de veces que el gtm.js
El evento ha sido pospuesto dataLayer
y puede utilizar esto como un proxy razonablemente bueno para determinar cuántas páginas ha visitado el usuario. Tenga en cuenta que si utiliza cualquiera de los dos gtag.js o Google OptimizeEs posible que esta variable no devuelva un resultado preciso.
Revisar todo dataLayer
Historial de alguna clave o valor
Aquí hay una extensión de Esta solución Escribí para el window.dataLayer
matriz (es decir, la dataLayer
del precise página solamente). Con esto, puedes buscar en todo el historial de la dataLayer
matriz para un par clave-valor determinado. Así es como se ve la variable de JavaScript personalizada modificada:
perform() {
// Modify the searchObject beneath.
//
// Add every key-value pair you need to search for straight into the searchObject object. Use
// strings for keys.
//
// The variable will search for any key-value pair you specify, and return true if any one in every of them
// is discovered. In case you use dot notation, the variable will attempt to discover a key with this title first,
// after which it is going to parse the nested construction on the lookout for a match.
var searchObject = {
'person.consentGiven': 'false'
};
var dataLayerName = '_dataLayerHistory';
// Do not edit something beneath this line.
var getValueForObjectString = perform(obj, key) {
return key.break up(".").scale back(perform(o, x) , obj);
};
return window(dataLayerName).historical past.filter(perform(obj) {
var discovered = false;
var prop;
for (prop in searchObject) {
if (obj(prop) == searchObject(prop) || getValueForObjectString(obj, prop) == searchObject(prop)) {
discovered = true;
}
}
return discovered;
}).size > 0;
}
Resumen
Puede utilizar este script para conservar el dataLayer
matriz, así como el modelo de datos interno de Google Tag Supervisor, de una página a la siguiente.
No es infalible. Por ejemplo, no entiende matrices de comandos o funciones de comandoy no entiende ningún handbook .set()
comandos que ejecuta contra el modelo de datos interno de GTM. (Nota: si alguno de los términos de este párrafo le resulta desconocido, lea mi artículo sobre Modelo de datos internos de GTM).
Como siempre, se trató más de una demostración técnica que de una solución llave en mano. Háganme saber en los comentarios si conocen algún uso para este tipo de solución. Además, si tienen sugerencias de mejora, ¡háganmelo saber también!