Sat. Dec 14th, 2024

Persistir capa de datos en Google Tag Supervisor


(Actualización del 19 de noviembre de 2018: ver Este artículo para una solución más elegante.)

Si conoces tu javascriptsabes que todas las variables, funciones, objetos, recursos y datos del documento se reescriben con cada carga de página. En otras palabras, cada actualización de página crea la página desde cero, y el estado del documento antes de la actualización de la página queda a la deriva en el océano del olvido.

Administrador de etiquetas de Google‘s dataLayer también es una de esas entidades. Se reescribe con cada carga de página, por lo que no es posible tener una variable dataLayer persistir de una página a otra sin utilizar cookies o, como voy a mostrar en esta guía, la API de almacenamiento net HTML5. Para la analítica net, esto es un poco vergonzoso. Nos obliga a pensar en cosas en el ámbito de una sola página, cuando rara vez algo que valga la pena mencionar tiene una vida tan corta.

Antes de comenzar, echa un vistazo en lo que Shay Sharon escribió expertamente hace dos años sobre la capa de datos persistente. En su solución, las cookies se utilizan para transportar la capa de datos a través de las actualizaciones de la página. Es un buen parche y realiza la tarea admirablemente. Sin embargo, lo que pasa con las cookies es que se pueden eliminar (y normalmente lo hacen). Además, la longitud de la cadena de cookies es limitada (aunque 4 KB sigue siendo suficiente) y siempre existe el hecho de que las cookies se resuelven con cada carga de página (ya que son parte del objeto del documento).

Los datos en el almacenamiento del navegador, por otro lado, son bastante difíciles de eliminar a nivel granular, tienen una cuota enorme y solo se recuperan y almacenan bajo demanda. Además, usando localStorage (más sobre esto pronto), tienes los datos almacenados indefinidamente, por lo que nivel de usuario El almacenamiento es muy fácil de implementar.

(ACTUALIZAR: Recuerde que el almacenamiento native del navegador debe tratarse de la misma manera que las cookies al observar las leyes de cookies de tu país. Gracias a Martijn Visser por señalar esto (es de los Países Bajos y tienen la interpretación más estricta de la ley de cookies).

En esta guía, le brindaré una especie de API para guardar, cargar, reemplazar y eliminar elementos del almacenamiento native. Utilizo una caducidad de 30 minutos para los datos en localStorage para imitar el almacenamiento de duración de la sesión.


incógnita


El boletín a fuego lento

Suscríbete al Boletín a fuego lento para recibir las últimas noticias y contenido de Simo Ahava en su bandeja de entrada de correo electrónico.

Presentamos el almacenamiento native

localStorage almacena datos indefinidamente en el compartimento de almacenamiento propio de su navegador. Tiene un límite de tamaño mayor al necesario (alrededor de 5 MB) y los datos se manejan de manera más segura que con las cookies. Verá, las cookies se escriben en el documento cada vez que carga una página, y esto introduce riesgos potenciales de seguridad.

Artículos en localStoragepor otro lado, se recuperan sólo cuando se llama. De esta manera, todos los datos que almacene se recogerán a pedido y todo lo que necesita hacer es asegurarse de que su secuencia de comandos maneje los datos correctamente (que es lo que haré por usted en esta guía).

En localStoragelos datos se escriben como pares clave-valor, pero a diferencia de dataLayer, tanto la clave como el valor deben ser de tipo String. Esto significa que para guardar cosas de dataLayer, que puede contener cualquier tipo de valores, para localStoragees necesario realizar alguna serialización de objetos y conversión de tipos (Objeto => Cadena). De manera comparable, debe ocurrir lo contrario al cargar datos desde localStorage y empujándolo a dataLayer.

La API de capa de datos persistente

Sin más preámbulos, permítanme presentarles la API Persistent dataLayer. Copie el siguiente código en una etiqueta HTML personalizada y siga leyendo.

<script>
  (perform() {
    // Declare some utility variables
    var retrievedDL = '',
        getDL = {},
        saveDL = {},
        persistEvent = /^persist(Save|Exchange)/,
        timeNow = new Date().getTime(),
        timeStorage = '',
        persistTime = 1000*60*30; // Expiration in milliseconds; set to null to by no means expire
    
    // Solely works if browser helps Storage API
    if(typeof(Storage)!=='undefined') {
        
      retrievedDL = localStorage.getItem('persistDL');
      timeStorage = localStorage.getItem('persistTime');
      
      // Append present dL with objects from storage
      var loadDL = perform() {
        if(retrievedDL) {
          dataLayer.push(JSON.parse(retrievedDL));
          // dataLayer.push({'occasion': 'DLLoaded'});
        }
      }
      
      // Save specified object in storage
      var storeDL = perform() {
        for (var i = 0; i < dataLayer.size; i++) {
          if (persistEvent.check(dataLayer(i).occasion)) {
            saveDL = dataLayer(i);
            delete saveDL.occasion;
            getDL = JSON.parse(retrievedDL) || {};
            for (var key in saveDL) {
              if (saveDL.hasOwnProperty(key)) {
                getDL(key) = saveDL(key);
              }
            }
            localStorage.setItem('persistDL', JSON.stringify(getDL));
          }
        }
      }
      var deleteDL = perform() {
        localStorage.removeItem('persistDL');
      }
      change ({{occasion}}) {
        case 'gtm.js':
          if (retrievedDL && timeStorage) {
            if (persistTime && timeNow > Quantity(timeStorage) + persistTime) {
              deleteDL();
            } else {
              loadDL();
            }
          }
          break;
        // Delete dataLayer variables
        case 'persistDelete':
          deleteDL();
          break;
        // Exchange dataLayer variables
        case 'persistReplace':
          retrievedDL = null;
        // Save dataLayer variables
        case 'persistSave':
          storeDL();
          break;
      }
      
      localStorage.setItem('persistTime', JSON.stringify(timeNow));
    }
  })();
script>

La etiqueta necesitará la siguiente regla de activación:

{{evento}} coincide con RegEx ^(gtm.js|persist(Guardar|Reemplazar|Eliminar))

Aquí hay un resumen de cómo funciona la API, antes de entrar en aspectos técnicos:

  1. Con cada carga de páginavariables de capa de datos almacenadas en localStorage se recuperan y se insertan en dataLayer.

  2. Al empujar un objeto con ‘evento’: ‘persistSave’todas las variables en el mismo push (por ejemplo, ‘pageCount’ y ‘writer’ en dataLayer.push({'occasion': 'persistSave', 'pageCount': '5', 'writer': 'Simo-Ahava'});) se guardan en localStorage. Si ya existe una variable con el mismo nombre en localStoragese actualiza con el nuevo valor.

  3. Al empujar un objeto con ‘evento’: ‘persistDelete’todas las variables de capa de datos en localStorage se eliminan.

  4. Al empujar un objeto con ‘evento’: ‘persistReplace’todas las variables dataLayer existentes en localstorage se eliminan y todas las variables del dataLayer.push() son salvos.

Así que recuerda los siguientes comandos:

dataLayer.push({'var1': 'value1', 'var2': 'value2', **'occasion': 'persistSave'**}); almacena ‘var1’ y ‘var2’ (con valores) en localStorage.

dataLayer.push({'var1': 'value1', 'var2': 'value2', **'occasion': 'persistDelete'**}); elimina todas las variables de capa de datos guardadas en localStorage; no almacena nada.

dataLayer.push({'var1': 'value1', 'var2': 'value2', **'occasion': 'persistReplace'**}); elimina todas las variables de capa de datos guardadas en localStorage; almacena ‘var1’ y ‘var2’ (con valores) en localStorage.

Algunos detalles adicionales:

  • Con cada carga de página, las variables se cargan desde localStorage y enviado a dataLayer. Aunque la etiqueta se activa {{evento}} es igual a gtm.jshay un ligero retraso al procesar datos a través de la API de almacenamiento. Esto significa que normalmente las variables aparecen en dataLayer después gtm.dom pero antes gtm.carga.

  • Cada interacción con localStoragerestablece el temporizador de vencimiento de 30 minutos. Si se carga una página de modo que la última interacción fue hace más de 30 minutos, todas las variables de capa de datos guardadas en localStorage se eliminan.

  • Antes de guardar los datos, las variables de dataLayer se serializan en una cadena. Al cargar desde localStoragese analizan desde JSON a sus tipos originales. Por lo tanto, las matrices, los objetos y los valores primitivos se restauran a sus tipos originales antes de regresar a la capa de datos.

Cosas técnicas

Repasemos el código (casi) línea por línea.

La función está envuelta en una IIFE (expresión de función invocada inmediatamente). Esto se debe a que quiero evitar el uso del alcance world cuando utilizo tantas variables diferentes. Determinar el alcance de las variables de esta función garantiza que no me meto con las variables globales de alguna otra biblioteca, por ejemplo.

var retrievedDL = '',
getDL = {},
saveDL = {},
persistEvent = /^persist(Save|Exchange)/,
timeNow = new Date().getTime(),
timeStorage = '',
persistTime = 1000*60*30; // Expiration in milliseconds; set to null to by no means expire

Aquí presento un montón de variables de utilidad. Si desea que el almacenamiento persista para siempre, configure persistTime = null;.

if(typeof(Storage)!=='undefined') {
  retrievedDL = localStorage.getItem('persistDL');
  timeStorage = localStorage.getItem('persistTime');
  ...
}

Ejecute la API solo si el navegador admite almacenamiento net HTML5. Básicamente es solo un problema con las versiones de IE anteriores a la 8. No vi ninguna razón para proporcionarles una alternativa, ya que si todavía estás usando IE7 o anterior, mereces una experiencia de navegación horrible.

Consulte la excelente publicación de Shay Sharon a la que me vinculé al principio para obtener una solución de cookies para la capa de datos persistente. Eso debería funcionar con tu navegador desactualizado y de mala calidad.

var loadDL = perform() {
  if(retrievedDL) {
    dataLayer.push(JSON.parse(retrievedDL));
    // dataLayer.push({'occasion': 'DLLoaded'});
  }
}
...
case 'gtm.js':
  if(retrievedDL && timeStorage) {
    if(persistTime && timeNow > Quantity(timeStorage)+persistTime) {
      deleteDL();
    } else {
      loadDL();
    }
  }
  break;

Con cada carga de página, analice las variables de capa de datos en localStorage volver a sus tipos originales y enviarlos a dataLayer como un solo objeto. Si desea configurar un evento desencadenante para activar sus etiquetas después de que las variables se hayan cargado desde localStoragedescomente la línea con ‘evento’: ‘DLLoaded’. De esta manera puedes hacer que tus etiquetas dependientes se activen {{evento}} es igual a DLLoaded para garantizar que tengan acceso a las variables almacenadas.

Además, si las variables almacenadas caducan (el valor predeterminado es 30 minutos desde la última interacción), no se cargan datos y las variables se eliminan de localStorage. Si has configurado persistTime = null;los datos almacenados no caducan y las variables se almacenan hasta que se eliminan manualmente.

cuando un dataLayer.push(); se hace de manera que el objeto que se empuja contenga la propiedad ‘evento’: ‘persistSave’, la función storeDL() se ejecuta.

Primero, la función elimina la propiedad ‘evento’ del objeto que se insertó en dataLayer. Esto se hace porque no desea almacenar el evento desencadenante en sí localStorage. (Otra posibilidad es simplemente omitir la propiedad ‘evento’ al almacenar propiedades en localStorage.)

A continuación, cada propiedad de este objeto dataLayer se inserta en el objeto que se encontró en localStorage. Por lo tanto, todas las variables que ya estaban almacenadas se actualizan con nuevos valores y se agregan nuevas variables.

Finalmente, el objeto, ahora serializado en una cadena de claves y valores, se almacena en localStorageesperando ser cargado con una nueva actualización de página.

Si el ‘evento’ fue ‘persistReplace’, entonces este es el storeDL() también se ejecuta, pero todas las variables de dataLayer almacenadas se reemplazan con las nuevas variables.

var deleteDL = perform() {
  localStorage.removeItem('persistDL');
}
...
case 'persistDelete':
  deleteDL();
  break;

Si el evento desencadenante fue ‘persistDelete’, todas las variables de capa de datos en localStorage se eliminan.

localStorage.setItem('persistTime', JSON.stringify(timeNow));

Finalmente, cada vez que se ejecuta el script, la hora precise se guarda como una marca de tiempo en localStorage.

Conclusiones

He notado que muchas personas anhelan una capa de datos persistente. Estoy bastante seguro de que esta publicación quedará obsoleta tan pronto como el equipo de GTM decida implementar dicha característica en el producto en sí, pero hasta entonces, esto debería serle de gran utilidad.

Y al menos, ¡al menos tienes que aprender sobre otra API de JavaScript realmente interesante!

¿Tiene sugerencias para la API? ¿O tal vez tiene un caso de uso interesante para variables persistentes que quizás desee compartir con otros?

Related Post

Leave a Reply

Your email address will not be published. Required fields are marked *