Do not speak Spanish? Read this post in English.

Martes, 09 d octubre d 2012.

Implementación avanzada de Custom Tags en Google Tag Manager

El otro día os presentaba un resumen sobre las posibilidades de Google Tag Manager, una novedosa herramineta que va por buen camino pero de la que os comentaba que hay cosas que por defecto son un poco limitadas. Los tags, tal y como son presentados son elementos estáticos que se sirven mediante una lógica muy conseguida pero no "pueden" adaptarse a las peculariedades de las webs y permanecen como meros tags estáticos.

Según mi modo de verlo tenemos dos formas de usar la herramienta: Como simple lanzador de tags estáticos - o como plataforma Javascript que se dedique a provocar distintos comportamientos en distintas situaciones. La primera está perfectamente resuelta con las opciones que nos dan, pero la segunda, si bien resulta posible, requiere de conocer un poco mejor el código con el que se mueve la herramienta...

A eso vamos hoy, a ver algunos ejemplos de implementación avanzada que llevo unos días probando y que espero que os ahorren alguna horilla de pruebas o al menos os den alguna idea de lo que puede y lo que no puede hacerse con GTM.

El Código de Google Tag Manager

Veamos antes de nada el código que nos da Google Tag Manager para añadir a nuestras webs. Para generarlo solo debemos crear un container nuevo y ver el código que nos indican que copiemos en nuestra web. No te asustes por emepezar a ver código en pantalla, que no vamos a trabajar demasiado con él.

Os lo muestro un poco más tabulado que como se nos presenta por defecto:

<!-- Google Tag Manager -->
<noscript>
<iframe src="//www.googletagmanager.com/ns.html?id=GTM-AAAA" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>
(function(w,d,s,l,i){
w[l]=w[l]||[];
w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});
var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';
j.async=true;j.src='//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-AAAA');
</script>
<!-- End Google Tag Manager -->

Es un código denso, -como todos los de Google- pero tan corto, que -si sabes javascript- puede leerse con un mínimo esfuerzo: Básicamente empieza por una llamada a un iframe, de esas que hacen lo que pueden para trabajar sin Javascript y un script javascript que inicia una serie de variables y termina cargando el script de googletagmanager.com/gtm.js

Lo más interesante es ver como el código genera una variable global (asociada al objeto 'window'): dataLayer. Las variables globales son datos que se crean con Javascript para que estén disponibles en cualquier parte y momento de nuestros códigos y eventos. Esta variable se inicia ya por si sola con el valor del tiempo en milisegundos en el que el navegador lee el tag de GTM lo que supone para Google una forma sencilla por la que medir el tiempo entre la carga de página y distintos eventos que queramos provocar. Aunque eso significa que ese tiempo también podemos aprovecharlo nosotros (lo veremos más tarde).

dataLayer se nos presenta como un contenedor de datos, que GTM destina a portar eventos hacia la lógica de Google Tag Manager: Es la variable que este evalúa para saber si cumplimos ciertos criterios o no y por lo tanto podemos provocar la aparición de nuestros tags en función de lo que añadamos a la misma.

Con un par de pruebas, descubrimos que la variable dataLayer, al ser global, puede ser leída sin problemas en nuestros "custom tags" de Google Tag Manager, con lo que no se trata solo de una portadora de condiciones hacia el validador de GTM sino de una fuente de datos totalmente válida en nuestros tags. Esto no tiene en realidad tanto misterio; básicamente todas las variables globales de javascript podrán ser leidas por los tags de Google Tag Manager, pero por ser ordenados y no saturar nuestro código de variables globales, lo suyo es que usemos siempre la variable dataLayer como transportadora de estos datos ya sea hacia el validador de GTM o hacia nuestros propios datos. Así que en conclusión, pongámonos una norma desde el principio: todo lo que queramos enviar hacia los tags de GTM lo meteremos en dataLayer.

Enviando Valores a Google Tag Manager

Así pues para poder implementar nuestro código haciendo llegar variables extra de nuestro servidor a nuestros tags podemos añadir simplemente nuevos elementos a dataLayer y después leerlos sin problemas.

En cualquier lugar añadimos

dataLayer.miPropiedad = 'miValor'; 

Y en nuestros tags podremos llamar a dataLayer.miPropiedad para recoger ese valor. Esto Puede sernos de utilidad para algunas implementaciones que necesitan de estos datos: id's de conversión, marcas especiales de la web, etc.

Por ejemplo. Imaginemos que queremos definir nuestro ID de cuenta de analytics como variable e implementar un código de tag en GTM que lo recoja y lo aplique:

1) Definiríamos, después de incluir el tag de GTM este valor en datalayer:

dataLayer.googleAnalyticsId = 'UA-1234567-8';

Luego crearíamos un custom tag para nuestro container en GTM con el siguiente contenido:

<!-- Google Analytics Tracking -->

<script type="text/javascript">  

var _gaq = _gaq || [];  
_gaq.push(['_setAccount', dataLayer.googleAnalyticsId ]);
_gaq.push(['_trackPageview']);

(function() {var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = 'http://www.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);  })();

</script>

Es sencillo. Solo tenemos que hacer un código de custom Tag que vaya recogiendo todas las variables que queramos crear y actue en consecuencia. Aquí solo daros un consejo. No os fiéis de lo que se implemente en la web ya que contar con que existe una variable puede hacer que todo el tag deje de funcionar. Por lo tanto, preocupémonos de validar siempre en nuestros tags los datos de dataLayer antes de usarlos.

Un ejemplo práctico: supongamos que hemos pedido a los programadores que nos creen en dataLayer un valor que nos permite guardar si el usuario está o no identificado con su cuenta de la web. Los programadores nos prometen que todas las páginas pasan a contener uno de estos dos códigos:

dataLayer.logged = true;

o

dataLayer.logged = false;

Pero nosotros decidimos no fiarnos así que validamos este valor antes de incluirlo como variable personalizada de analytics. Así que nuestro custom tag en GTM acaba teniendo esta forma:

var _gaq = _gaq || [];  
_gaq.push(['_setAccount', dataLayer.googleAnalyticsId ]);

if ( typeof dataLayer.logged == 'undefined' )
// validamos si existe la variable, si no existe marcamos not-set
{
  _gaq.push(['_setCustomVar', 1, 'User', 'not-set', 3]);
}
else if ( dataLayer.logged == true)
// si existe miramos si está a true y marcamos como identificado
{
  _gaq.push(['_setCustomVar', 1, 'User', 'identificado', 3]);
}
else 
// y si no lo está, marcamos como no identificado
{
  _gaq.push(['_setCustomVar', 1, 'User', 'no-identificado', 3]);
}

_gaq.push(['_trackPageview']);

Luego la sorpresa, como no, vendrá cuando encontremos páginas con un "not-set" como valor. Pero para mi esta separación que hemos hecho con GTM es una ventaja. Anteriormente si los programadores olvidaban algo era muy difícil darse cuenta, ahora como establecemos este paso intermedio podemos validar si nos faltan datos para enviar a Analytics la información correcta.

Bueno, y en definitiva, hemos visto como dataLayer nos va a permitir definir valores y como aprovecharlos luego en nuestros tags. He puesto el ejemplo de Google Analytics, pero con cualquier tipo de tags este proceso sería también posible.

La pregunta: si hago todo esto igualmente estoy cambiando mi web... ¿para que sirve entonces GTM?

Una cosa es obvia: obligar a cambiar nuestra web enviando datos por javascript a GTM puede volverlo un poco inútil: Estamos usando una herramienta que en teoría nos permite no tocar nuestra web para poder realizar las acciones de marketing y lo que hacemos es cambiar la web para pasarle datos a GTM... Algo falla, ¿no?

Pues no.

Lo primero es no ser cabezotas. Que en ocasiones tengamos que tocar nuestra web no quita que una vez tocada GTM nos ayudará a hacer pequeños cambios en los tags sin volver a entrar en el código de la web, así que sigue siendo bastante útil.

Por ejemplo: podemos indicar en nuestra web "dataLayer.idConversion = 125" cuando exista una nueva conversión (la 125, se supone) y esto nos permitirá en un futuro implementar el código de eCommerce de Analytics, algunos de afiliados, emailing, etc. Así que reaprovecharemos con una sola acción en la página las variables para todos nuestros pixeles/tags/códigos -o como quieras llamarlos-. Seamos claros, lo que no hace GTM es magia, no puede inventarse tus id's de conversión ni los nombres de tus eventos, eso tiene que darselo la web.

Lo segundo es ser un poco inteligentes a la hora de hacer nuestras webs y también a la hora de implementar nuestros custom tags. Sabemos que hay datos que podemos querer usar para analítica web en un momento u otro, por lo que... ¿porque no exigir que todos los datos posibles estén presentes en las webs aunque aun no los vayamos a usar?

Por un lado tenemos al HTML, que nos permite indicar entre sus tripas, distintos valores que podremos recoger luego con Javascript: textos de los breadcrumbs para saber en que sección está el usuario, atributos data donde "esconder" id´s o clasificaciones que podamos necesitar, clases especiales para el "body" de la página, etc.

Ejemplos (basados en jquery):

- Recogiendo con la sección en la que estamos de un breadcrumb:

<ul class="breadcrumb">
  <li class="step1"><a href="/">Home</a></li>
  <li class="step2"><a href="/electrodomesticos">Electrodomésticos</a></li>
  <li class="step3"><a href="/electrodomesticos/lavadoras">Lavadoras</a></li>
  var seccion=$('ul.breadcrumb li.step2 a').html();

- Recogiendo valoroes de un atributo data:

<div id="thanks" data-id="1234">
  <p>Gracias por solicitar información sobre nuestro producto Jaime.</p>
  <p>En breve, uno de nuestros expertos se pondrá en contacto contigo.</p>  
</div>
  var idLead=$('#thanks').data('id');

Además del propio HTML ahora se nos da la variable dataLayer donde guardar cualquier dato de BBDD que podamos necesitar. El problema es que usarla requiere de una etiqueta script y eso es sucio y obvio.

Para mi siempre será mejor esconder los datos en el HTML: por un lado porque a veces ya están ahí y no hace falta pedir nada para rescatarlos (caso breadcrumb), por otro porque quedan más limpios y ocultos (caso id).

Pero por otro lado, usar dataLayer también significa que quien use GTM lo tiene más fácil: no hace falta saber mucho javascript para poder crear los tags con dataLayer. Así que dependerá también de las posibilidades de quien lo implemente.

Planifica: Con una buena planificación previa sobre una web, deberíamos ser capaces de realizar los cambios en la misma una única vez y a partir de ahí conseguir que con GTM, por avanzada que sea la implementación que hagamos, nunca tengamos que molestar al equipo de desarrollo.

Por ejemplo:

Si sabemos que existe una página de gracias tras una conversión. Pidamos siempre todos los datos posibles sobre esta conversión: id, producto, categoría del producto, tipo de usuario, tests activos, etc.

Puede que al principio no usemos ninguno pues solo queramos marcar la conversión por Objetivos de Google Analytics, pero es preferible pedirlo todo de una vez y no volver a molestar al equipo de desarrollo. Esta en nuestra mano hacerles la vida más fácil.

En resumen: Con este tipo de añadidos podemos nutrir a nuestros tags de toda una colección de datos tan rica que las implementaciones avanzadas de analytics y demás herraminetas de Analítica pasarán a hacerse en GTM. Pero eso no quita, que sigue siendo bastante probable que al empezar a trabajar con una nueva web, necesitemos pedirles unos cuantos añadidos en forma de variables de dataLayer o datos encubiertos en el HTML. Aunque, sin duda, será algo mucho más simple que las documentaciones que pasamos a los clientes a día de hoy...

Implementación en pixeles no asincronos

Otro de los problemas que plantea GTM es que se lanza en asíncrono, mientras que hay herramientas que necesitan recoger datos al inicio de la carga de página y no les vale con cargarlos unos milisegundos más tarde.

Precisamente, uno de los valores que nos solicitan algunas herramientas para poder trabajar es la captura del tiempo en el momento de carga de la página. Esta captura parecería que con GTM no puede hacerse pues al lanzarse en asíncrono no puede gestionarse. Pero por suerte, en dataLayer disponemos justo de ese valor y por lo tanto podemos usarlo. Es tan simple como esto:

var tiempoInicioDeCarga = dataLayer[0]['gtm.start'];

Por lo tanto, píxeles como el de ClickTale, por el que me preguntaba "Jose Manuel" en los comentarios del post Anterior pueden ser resueltos con el uso de esta variable.

Seguidamente os muestro un ejemplo de como quedaría el código de clickTale en un único tag de GTM:


<!-- ClickTale Top part -->
<script type="text/javascript">
var WRInitTime=dataLayer[0]['gtm.start'];
</script>
<!-- ClickTale end of Top part -->

<!-- ClickTale Bottom part -->
<div id="ClickTaleDiv" style="display: none;"></div>
<script type="text/javascript">
if(document.location.protocol!='https:')
document.write(unescape("%3Cscript src='http://s.clicktale.net/WRd.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
if(typeof ClickTale=='function') ClickTale(project id,recording ratio %,"partition #");
</script>
<!-- ClickTale end of Bottom part -->

</script>

Realizando mediciones concretas y preparando el A/B Testing con GTM

También os comentaba el otro día que el A/B testing con GTM era posible. Para ello os voy a presentar un código que ya creado y empaquedado. Este código se aprovecha de la variable de tiempo que crea GTM en dataLayer y gracias a ella podremos hacer un A/B testing y de paso capturar el tiempo transcurrido cuando queramos. Os paso copio el código bastante comprimido, no os preocupéis demasiado si no lo entendéis, la idea es que simplemente podáis usarlo con un corta y pega:

<script>(function(w,d) { 

var activeTests = [ 'A', 'B' ]; // <-- define aquí los nombres de test que quieras activar

// No alterar este código
w.startTime = w.dataLayer[0]['gtm.start'];
cs=document.cookie.split(";");
for (var i=0;i<cs.length;i++) if ( cs[i].substr(0,cs[i].indexOf("=")).replace(/^\s+|\s+$/g,"") == 'abtestingvalue' ) { w.abVal = cs[i].substr(cs[i].indexOf("=")+1); break;  }
if (!w.abVal || w.abVal == 'undefined' || typeof w.abVal == 'undefined'){w.abVal = activeTests[ w.startTime % activeTests.length ];  d.cookie='abtestingvalue='+w.abVal+';expires=;path=/';}
var getTime = function () { return new Date().getTime() - w.startTime; }
var testVersion = function ( t, cb ) { if (w.abVal==t) cb.call(); }
// Fin-No alterar este código

// y a partir código propio...


})(window,document);
</script>

Este código, simplemente decide en que versión del test A/B nos encontramos (y lo almacena en cookie para que un mismo usuario al recargar la página no vaya viendo alternativamente las distintas versiones). A partir de ahí, pone a nuestra disposición dos funciones con las que trabajar nuestra implementación de testing:

  • getTime(): Nos permite saber cuanto tiempo ha pasado desde la carga de la página, ya que teníamos ese valor es una pena no usarlo.
  • testVersion( test, func ): Nos va a permitir definir que pasa si estamos cada uno de los tests en los que nos encontramos. Aquí hay que entender que la primera línea define los nombres de los tests disponibles y que luego usaremos para ir lanzando testVersion.
  • Seguidamente podéis ver un ejemplo de como implementarlo para ver una serie de alertas en la página dependiendo del test en el que nos encontremos. En este ejemplo los nombres puestos a los tests son "testA" y "testB" por lo que luego en testVersion los llamamos con esos nombres...

    <script>(function(w,d) { 
    
    var activeTests = [ 'testA', 'testB' ]; // <-- define los test que quieras activar
    
    // No alterar este código
    w.startTime = w.dataLayer[0]['gtm.start'];
    cs=document.cookie.split(";");
    for (var i=0;i<cs.length;i++) if ( cs[i].substr(0,cs[i].indexOf("=")).replace(/^\s+|\s+$/g,"") == 'abtestingvalue' ) { w.abVal = cs[i].substr(cs[i].indexOf("=")+1); break;  }
    if (!w.abVal || w.abVal == 'undefined' || typeof w.abVal == 'undefined'){w.abVal = activeTests[ w.startTime % activeTests.length ];  d.cookie='abtestingvalue='+w.abVal+';expires=;path=/';}
    var getTime = function () { return new Date().getTime() - w.startTime; }
    var testVersion = function ( t, cb ) { if (w.abVal==t) cb.call(); }
    // Fin-No alterar este código
    
    // A partir código propio...
    
    // Saber el tiempo transcurrido...
    alert('El tiempo transcurrido desde el inicio de la carga es: '+ getTime() + ' milisegundos'); 
    
    // Declarar que pasa con los tests A/B
    testVersion( 'testA', function () {
      alert('Estamos en el test A, ahora vamos a cambiar cosas de la web con Javascript');
      //Otro ejemplo: $('h1').html('Texto del H1 para el test A');
    });
    
    testVersion( 'testB', function () {
      alert('Estamos en el test B, ahora vamos a cambiar cosas de la web con Javascript');
      //Otro ejemplo: $('h1').html('Texto del H1 para el test B');
    });
    
    })(window,document);
    </script>
    

    Este código provocará los cambios, pero no guardará nada en nuestras herramientas de analítica. Es labor nuestra, en cada caso decidir que guardamos y cómo lo hacemos. Yo lo dejo a vuestro criterio...

    El problema como antes es que hay que lidiar con javascript (jquery, mootools, prototype, etc...) para provocar los cambios en la web. Pero si quieres algo de ayuda te dejo un "truco".

    - Usa la versión de prueba de Optimizely, haz los cambios que quieras y luego mira el código de javascript de la pestaña de abajo. Te habrá generado el mismo los cambios a realizar.

    - Otra opción aún más sencilla quizás es usar directamente Optimizely e ir implementándolo sólo donde lo necesites gracias a GTM. Puede ser un tandem realmente potente, pero claro, hay que pagar optimizely y no a todo el mundo le gusta pagar, incluso cuando el producto es bueno.

    Conclusión

    Hemos visto distintas oportunidades que tenemos para hacer más dinámico y potente el uso de GTM, pero ahora le toca a cada uno sacarle partido. Oportunidades hay muchas, pero cada uno tiene que encontrar la metodología que mejor se adapta a sus necesidades, conocimientos y costumbres.

    ¿hay alguna cosa que quieras probar?

Temas Relacionados: analitica web jquery tutoriales

Autor:

Un Comentario para “Implementación avanzada de Custom Tags en Google Tag Manager”

  1. Jose Manuel dice:

    Muchas gracias por tu aclaración, tu ayuda y compartir tus conocimientos.
    Un saludo.

Anímate y deja tu comentario

Esto son experimentos, no preguntes ;) prueba metadescription Prueba title