Analytics

Conserver la couche de données de Google Tag Manager sur les pages

MISE À JOUR 4 juin 2020: Au lieu de copier le code HTML personnalisé de l’article, veuillez le charger à partir du GitHub Gist à la place.

Il y a quatre ans, j’ai écrit un article sur la façon de persister GTM dataLayer de page en page. Malheureusement, la solution était un peu maladroite, vous obligeant à donner des précisions commandes pour les interactions, ce qui le rendait vraiment peu maniable à long terme. Google Tag Manager ne nous offre toujours pas de moyen natif de conserver le dataLayer array ou son modèle de données interne d’une page à l’autre, j’ai donc pensé qu’il était temps de revoir cette idée.

Persist dataLayer

Cette fois, il n’y aura pas de API pour interagir avec. Au lieu de cela, la solution stockera simplement le contenu du dataLayer tableau ET le modèle de données interne de page en page, jusqu’à ce que l’utilisateur n’ait pas interagi avec les GTM dataLayer pendant un laps de temps donné.

Le mettre en place

Pour le configurer, vous devez créer une balise HTML personnalisée, dans laquelle vous copierez le code suivant. Si vous le souhaitez, vous pouvez également copier le code de cet essentiel.

MISE À JOUR 4 juin 2020: Veuillez copier le code du essentiel lien ci-dessus plutôt que de l’article ci-dessous. L’essentiel est tenu à jour et contient des correctifs de stabilité qui aident à résoudre certains problèmes rencontrés par les utilisateurs avec la solution.

Le code de la balise HTML personnalisée

<script>   (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}}].dataLayer.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;       }     };   })(); </script>

Au tout début de l’extrait de code, il y a deux variables dont vous devez modifier les valeurs.

var timeout = 30*60*1000;

La ligne ci-dessus établit le temps libre pour le stockage local. Cela signifie qu’une fois que l’utilisateur n’a pas interagi avec dataLayer aussi longtemps que vous définissez le délai d’attente, l’historique sera réinitialisé pour démarrer à partir de la page actuelle. La valeur par défaut est 30 minuteset si vous souhaitez le modifier, assurez-vous de définir le délai d’attente dans millisecondescomme dans la valeur par défaut.

var dataLayerName="dataLayer";

La ligne au-dessus est le nom du dataLayer tableau utilisé par Google Tag Manager, et il utilise par défaut l’extrait de conteneur non modifié. Si vous avez modifié le dataLayer nom dans l’extrait de conteneur, assurez-vous qu’il est également mis à jour ici.

Autres paramètres de balise

En plus de copier-coller le code ci-dessus, définissez le Priorité des balises valeur à 9999 ou tout nombre supérieur à toute autre priorité de balise pour les balises déclenchées sur le déclencheur Toutes les pages.

priorité des balises

Déclencheur

Définissez cette balise HTML personnalisée pour qu’elle se déclenche sur Toutes les pages déclencheur. Vous voulez que ce soit la première balise qui se déclenche sur la page. Naturellement, si vous avez des balises qui se déclenchent sur un événement qui est poussé dans dataLayer avant l’extrait de conteneur Google Tag Manager, vous devez vous assurer que cette balise se déclenche sur que déclencher à la place.

Toutes les pages déclenchent

Comment ça fonctionne

Chaque fois que quelque chose est poussé dans dataLayeril est également poussé dans un nouveau tableau sous window._dataLayerHistory. Il s’agit d’un objet global auquel vous pouvez accéder depuis n’importe où sur la page, y compris les balises HTML personnalisées de GTM et les variables JavaScript personnalisées.

En plus d’être ajouté à ce tableau d’historique, ce tableau est également écrit de manière cohérente dans le window.localStorage structure, qui persiste d’une page à l’autre jusqu’à ce que l’utilisateur décide d’effacer l’espace de stockage de son navigateur.

stockage local du navigateur

Bref, il y a un nouveau window._dataLayerHistory objet qui contient des informations sur tous les éléments poussés dans dataLayer à travers les pages, et vous pouvez accéder à cet objet à partir de n’importe quel contexte JavaScript sur la page.

historique de la couche de données

Le tableau historique

Le tableau lui-même, représentant l’histoire de la window.dataLayer tableau, peut être trouvé à window._dataLayerHistory.history.

Lorsque la balise HTML personnalisée est chargée pour la première fois sur une page, ce tableau d’historique est d’abord remblayé avec des éléments du courant window.dataLayer qui ont été poussés avant le déclenchement de la balise HTML personnalisée. Cela est nécessaire, car la balise HTML personnalisée crée sa propre .push() auditeur uniquement lorsqu’il se déclenche, auquel cas le window.dataLayer tableau contiendra déjà des éléments.

Une chose bizarre que vous remarquerez peut-être, c’est que s’il y a un window.dataLayer.push() appel ayant lieu dans une séquence de balises, l’objet poussé dans le tableau de l’historique ne contiendra pas le gtm.uniqueEventId clé. Je ne peux pas faire grand-chose à ce sujet, malheureusement, mais cela ne devrait pas être un gros problème.

Le modèle de données

Si vous n’êtes pas familier avec le modèle de données de GTM, il s’agit essentiellement d’une table de recherche dans laquelle GTM copie et fusionne les paires clé-valeur que vous insérez dans le dataLayer déployer.

Il est important de comprendre cette distinction, car GTM utilise le modèle de données interne pour Variables de la couche de données.

modèle de données

Le modèle de données est également conservé de page en page dans window._dataLayerHistory.model. Cet objet a un get() méthode que vous pouvez utiliser pour récupérer les valeurs du modèle de données, tout comme le fait l’interface native de GTM :

window._dataLayerHistory.model.get('someOldVariableFromAPreviousPage');

Cela pourrait être utile. Par exemple, si votre site écrit sur dataLayer quelque chose comme {userLoggedIn: true} lorsque l’utilisateur se connecte au site, mais il ne le fait que lorsque l’utilisateur se connecte réellement, vous pouvez récupérer cette valeur sur des pages ultérieures en interrogeant l’objet historique :

window._dataLayerHistory.model.get('userLoggedIn');

Le modèle historique applique le même type de fusion récursive que GTM fait avec son modèle de données interne. Cela peut conduire à des résultats inattendus avec des objets et des tableaux, alors assurez-vous de lire sur la fusion récursive avant de continuer.

Réinitialiser

Vous pouvez également réinitialiser l’historique en exécutant cette commande :

window._dataLayerHistory.reset();

Cela annule le délai d’attente et réinitialise le tableau d’historique et le modèle d’historique aux états de la page actuelle, supprimant ainsi tout historique des deux. Il réinitialise également l’objet stocké dans le stockage du navigateur à cet état de réinitialisation.

Applications

Il y a beaucoup de choses que vous pourriez faire avec un persistant dataLayer et modèle de données. Voici quelques exemples.

Obtenir le nombre de pages chargées

Pour identifier le nombre de pages visitées par l’utilisateur, vous pouvez avoir une variable JavaScript personnalisée qui fait ceci :

function() {   return window._dataLayerHistory.history.filter(function(obj) { return obj.event === 'gtm.js'; }).length; } 

Cela renvoie le nombre de fois que le gtm.js l’événement a été poussé dans dataLayer, et vous pouvez l’utiliser comme un proxy raisonnablement bon pour déterminer le nombre de pages que l’utilisateur a visitées. Notez que si vous utilisez gtag.js ou Google Optimize, cette variable peut ne pas renvoyer un résultat précis.

Vérifiez l’ensemble dataLayer historique pour une clé ou une valeur

Voici une extension de cette solution que j’ai écrite pour le window.dataLayer tableau (c’est-à-dire le dataLayer du courant pages uniquement). Avec cela, vous pouvez rechercher l’histoire entière de la dataLayer tableau pour une paire clé-valeur donnée. Voici à quoi ressemble la variable JavaScript personnalisée modifiée :

function() {   // Modify the searchObject below.   //   // Add each key-value pair you want to look for directly into the searchObject object. Use   // strings for keys.    //   // The variable will look for any key-value pair you specify, and return true if any one of them   // is found. If you use dot notation, the variable will try to find a key with this name first,   // after which it will parse the nested structure looking for a match.   var searchObject = {     'user.consentGiven': 'false'   };      var dataLayerName = '_dataLayerHistory';      // Don't edit anything below this line.   var getValueForObjectString = function(obj, key) {     return key.split(".").reduce(function(o, x) {         return (typeof o == "undefined" || o === null) ? o : o[x];     }, obj);   };      return window[dataLayerName].history.filter(function(obj) {     var found = false;     var prop;          for (prop in searchObject) {       if (obj[prop] == searchObject[prop] || getValueForObjectString(obj, prop) == searchObject[prop]) {         found = true;       }     }     return found;   }).length > 0; } 

Résumé

Vous pouvez utiliser ce script pour conserver le dataLayer array ainsi que le modèle de données interne de Google Tag Manager d’une page à l’autre.

Ce n’est pas infaillible. Par exemple, il ne comprend pas tableaux de commandes ou alors fonctions de commandeet il ne comprend aucun manuel .set() commandes que vous exécutez sur le propre modèle de données interne de GTM. (Notez que si l’un des termes de ce paragraphe vous était étranger, veuillez lire mon article sur le modèle de données interne de GTM).

Comme toujours, il s’agissait plus d’une démonstration technique que d’une solution clé en main. S’il vous plaît laissez-moi savoir dans les commentaires si vous avez des utilisations pour ce type de solution. De plus, si vous avez des suggestions d’amélioration, faites-le moi savoir aussi !

Source : www.simoahava.com

Articles similaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Bouton retour en haut de la page
Index