Trabajar con un dataLayer alojado en servidor (server-hosted) en Google Tag Manager (GTM)

Lo reconozco: soy un gran fan de los tag managers. Cuanto más trabajo con ellos, más potencial veo que tienen. La cantidad de tareas que uno puede acometer a través de un gestor de etiquetas (TMS por su siglas en inglés – Tag Management System) es increíble. Desde trabajar con el DOM para implementar ‘tracking’ vía JavaSript en una página, hasta escuchar eventos generados en una app móvil. Un TMS es como una navaja suiza.

Cada gestor de etiquetas tiene sus fortalezas y debilidades, y hay una funcionalidad en particular de Tealium iQ que en seguida me llamó la atención: los hosted data layers (algo así como data layer alojado en servidor). Te permite subir a la CDN de Tealium un archivo .json con los valores que necesitas en la capa de datos de una página (quizá incluso necesites toda la capa de datos). A partir de ahí, Tealium iQ se encarga de implementar -o actualizar- el data layer en tu página (el data layer de Tealium iQ se conoce como objeto utag_data o Universal Data Object – UDO).

Siempre he estado muy centrado en implementaciones y desarrollos vía Google Tag Manager, y esta es una funcionalidad que no está disponible en GTM. Así las cosas, pensé que sería una buena opción poder importar -o actualizar- tu propio dataLayer desde un servidor si por el motivo que sea no cuentas con soporte de tu equipo de Desarrollo para implementar una capa de datos en tu ‘site’ (yo mismo me he visto muchas veces en situaciones así).

Hay muchas formas de enfrentarse a una situación así. Una opción es generar tu propio dataLayer desde GTM ejecutando un dataLayer.push() en el evento gtm.js, por ejemplo. Quería, sin embargo, probar la opción de poder trabajar en Google Tag Manager con un hosted data layer como en Tealium iQ.

Te planteo dos posibles opciones para esto, ambas muy influenciadas por el desarrollo de Peter Meyer detallado en su post ‘GTM Server-Side Client Fetching Current Weather Conditions From An OpenWeather API’. Lo primero que debes hacer es subir a un servidor (a tu servidor) un archivo .json con la configuración del dataLayer con el que quieres trabajar. Este es el archivo que yo he usado para las explicaciones de este post:

{
	"pageType": "blog post",
	"category": "tag managers",
	"userStat": "returning user",
	"event":"dataLayerLoaded"
}

A continuación puedes:

  1. Enviar un request por http desde el contenedor de GTM que hayas implementado en tu site para traer este .json desde el servidor
  2. Enviar un request por http a tu contenedor de GTM server-side y gestionar el request a tu servidor desde aquí

Enviar un request por http desde tu contenedor web de Google Tag Manager (GTM) a tu servidor

Esta es la más sencilla de ambas opciones: sólo tienes que trabajar en el request que se envía de cliente (tu navegador web) a servidor. Como te decía antes, lo que quieres es ‘coger’ un archivo que tienes alojado en un servidor, por lo que bastará con que configures un request de tipo GET. Hay muchas formas de hacer esto, así que puedes ignorar lo que te planteo a continuación o modificarlo para adaptarlos a tus necesidades. Sea como sea, lo que necesitas es:

-Enviar un request por http de tipo GET a tu servidor para traer de vuelta al el .json con la configuración del dataLayer

-Transformar el contenido del archivo .json en un objeto JavaScripty empujarlo al dataLayer

Para ello he desarrollado el siguiente script a implementar en GTM (a través de un Custom HTML Tag – no olvides asignar un trigger para que se ejecute):

<script>
(function () {

    var httpRequest = new XMLHttpRequest();
    //If the request is sent to a different hostname, uncomment the following line
    //httpRequest.withCredentials = true;    
    httpRequest.open('GET','https://yourendpoint.com',true);
    httpRequest.addEventListener('readystatechange',function(e){
        //If response is correct and JSON file is found...
        if(this.readyState === 4 && this.status === 200 && this.responseText){

          var importedDataLayer = JSON.parse(this.responseText);
          var dataLayer = window.dataLayer || [];
          dataLayer.push(importedDataLayer);
        }
        //...otherwise
        else if(this.readyState === 4 && !(this.status === 200 && this.responseText)){
        
          var importedDataLayer = {'event':'no dataLayer found!'};
          var dataLayer = window.dataLayer || [];
          dataLayer.push(importedDataLayer);

        }
    })
    
    httpRequest.send();

})();
</script>
El CHTML Tag que lanza la petición por http se ejecuta en el evento gtm.js
El contenido del archivo .json se transforma en un objeto JavaScript y se empuja al dataLayer

Fíjate que el código se encarga de gestionar los posibles errores que pueda haber en la respuesta del servidor al navegador. Si esto sucediera, incluyo un objeto muy básico para poder ‘debuguear’ la implementación.

En función de las páginas en las que aterricen tus usuarios, puede que necesites diferentes dataLayers o diferentes valores dentro de dataLayers ya implementados. Si este es tu caso, puedes subir diferentes archivos .json a tu servidor y ‘llamar’ al que necesites a través del script que te muestro arriba. Sólo tendrás que actualizar el end-point al que se lanza el request y ajustar el trigger del Custom HTML Tag a cada página.

Seguro que sería más óptimo actualizar los valores del dataLayer en el back-end (en el servidor), así no tendrías que trabajar con diferentes end-points. Pero ese un tema completamente diferente.

Enviar un request por http a Google Tag Manager (GTM )server-side

Esta segunda opción es más compleja (entra en juego un nuevo componente  propio de los contenedores de Google Tag Manager de tipo servidor: el cliente ). Tienes que enviar un request por http de tipo GET desde tu navegador a tu end-point de GTM server-side. Una vez aquí, un cliente ‘reclamará’ el request y lo enviará al servidor en el que estés alojando tu archivo .json (tu dataLayer, vaya)

¿Y por qué podría interesarte este segundo enfoque si más complejo? Si el servidor en el que has alojado tu archivo .json tiene un dominio diferente al de tu ‘site’, tendrás que empezar a manejar alertas de tipo CORS en tu navegador. Si este es tu caso, GTM server-side puede de ser gran ayuda, ya que puedes cambiar su dominio para que sea igual que el de tu ‘site’. Así las cosas, todo pasaría por un entorno ‘first-party’. Te recomiendo que veas el siguiente vídeo, explica muy bien esto: ‘CORS in 100 seconds’, by Fireship.

Si decides optar por la vía de server-side Google Tag Manager, tendrás que trabajar en dos fases:

  1. En primer lugar tendrás que usar el Custom HTML Tag detallado antes para enviar el request inicial por http desde tu navegador a tu end-point de GTM server-side. Es muy importante que actualices el script con la url de este end-point y con la ruta que estará esperando el cliente que interceptará esta llamada.
  2. En segundo lugar, en tu contenedor de Google Tag Manager server-side tendrás que trabajar con un cliente que ‘intercepte’ esta llamada y la derive al servidor en el que hayas alojado el archivo .json con la configuración del dataLayer que necesitas.

Si quieres puedes usar el ‘client template’ que he desarrollado a tal efecto. A continuación te detallo el código (ten en cuenta que GTM server-side sólo permite trabajar con la versión sandbox de JavaScript de Google Tag Manager)

//API's needed by this client
const claimRequest = require('claimRequest');
const getRequestHeader = require('getRequestHeader');
const getRequestPath = require('getRequestPath');
const sendHttpGet = require('sendHttpGet');
const setResponseBody = require('setResponseBody');
const setResponseHeader = require('setResponseHeader');
const setResponseStatus = require('setResponseStatus');
const returnResponse = require('returnResponse');

//Code starts here: first step is to check if the request's header origin is included in the 'Alowed hostnames' field. If 'yes', admitedRequest is set to 'true'.

let admitedRequest;
let httpsProtocol = 'https://';
let hostNames = data.hostNames.toLowerCase().split(',');

hostNames.forEach((value,index,array)=>{
  
  array[index]= httpsProtocol + value;
  
});

hostNames.forEach((value)=>{
  
  if(getRequestHeader("origin") === value){
    
    admitedRequest = true;
  } 
});

//If admitedRequest = 'true' and the request path is included in the dataLayerEndPoint field, claim request!
if(getRequestPath() === data.requestPath && admitedRequest === true){

  claimRequest();
  
  sendHttpGet(data.dataLayerEndPoint, (statusCode, headers, body) => {
    
    var responseBody;
    
    //If status code is 200 and there is a body in the response
    if(statusCode >= 200 && statusCode < 300){
      
      responseBody = body;
      setResponseStatus(200);
    }
    
    //Is status code is 500 or higher
    else{
      responseBody = "{}";
      setResponseStatus(500);
    }
    
   
    setResponseHeader("content-type", "application/json");
    setResponseHeader("access-control-allow-credentials", "true");
    setResponseHeader("access-control-allow-origin", getRequestHeader("origin"));
    setResponseBody(responseBody);
    returnResponse();
  }, {timeout: 500});

}
Una vez has creado tu ‘client template’ con el anterior código, estos son los campos que tendrás que configurar:
  • Allowed hostnames. Una lista de los dominios (no incluyas el protocolo https://) que el cliente podrá ‘reclamar’. Un ejemplo: midominio.com
  • La ruta (el path) que el cliente de GTM server-side está esperando para ‘reclamar’ el request. Otro ejemplo: ‘/dataLayer’
  • End point where your dataLayer is hosted: url del end point en el que hayas alojado el archivo .json (aquí sí debes incluir el protocolo https://). Por ejemplo: midominio.com/archivos/dataLayer.json
GTM server-side en funcionamiento. El cliente reclama el request por http entrante y lo envía al end-point final. El navegador del usuario termina recibiendo una respuesta con status 200 con el contenido del dataLayer en el body de dicha respuesta.
El contenido del archivo .json se convierte en un objeto JavaScript y se empuja al dataLayer, tal cual se puede ver en el preview mode del contenedor web de GTM.

Reflexiones finales

Bajo mi punto de vista trabajar con un dataLayer correctamente implementado es fundamental. Es una de las mejoras formas de recolectar datos de buena calidad. Aún así, he trabajado en muchos proyectos en los que los que simplemente no había tiempo ni recursos para ello.

Si es tu caso, espero que este desarrollo te sirva de ayuda. Una vez lo hayas puesto en marcha verás que puedes seguir la senda del hosted data layer de Tealium iQ en Google Tag Manager.

pornance.net
www.fuck-videos.net
zettaporn.com