Usar la API de gtag.js en Google Tag Manager (GTM) y Tealium iQ para exponer valores de GA4 en el data layer

Hace algún tiempo trabajé en un proyecto en el que era necesario exponer unos parámetros de GA4 (client_id, session_id) en el data layer de una página web. El planteamiento inicial era sencillo: lanzar una llamada a la API de la librería gtag.js solicitando estos valores y llevarlos después a la capa de datos. En seguida me di de bruces con varios frentes que tuve que ir abordando uno a uno. Por una parte que la API GTAG() no siempre está expuesta en el navegador, incluso cuando está descargada la librería gtag.js. Y por otra, hay que saber cómo coordinar la llamada a GTAG(), ya que como buena API que es, tarda en devolver los resultados solicitados. Se me ocurrió que sería buena idea escribir este post a modo de guía por si te ves en la misma situación algún día. Ojalá te sirva de ayuda.

Qué es gtag.js y qué es la API GTAG()

gtag.js es la librería javascript que habilita las herramientas de analítica y marketing de Google. Implementando gtag.js en tu site, puedes usar plataformas como Google Analytics (Universal Analytics y GA4), Google Ads o Campaign Manager. Hasta hace unos años, cada una de estas herramientas usaba su propia librería (analytics.js para Google Analytics, conversion.js para Google Ads…), pero su funcionalidad está ahora unificada en torno a gtag.js Basta con con que implementes esta librería una única vez para empezar a usar todas.

Puedes implementar gtag.js en tu página web añadiendo su snippet en el código fuente del site. Fíjate, el siguiente código (sacado de la documentación de oficial de Google), serviría para implementar GA4 en tu site añadiendo gtag.js en tu source code.

<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=ID_FLUJO_DATOS_GA4"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments)};
  gtag('js', new Date());

  gtag('config', 'ID_FLUJO_DATOS_G4');
</script>

En tanto en cuanto herramientas como GA4 o Google Ads hace uso de gtag.js, implementado estas plataformas a través de un tag manager como GTM o Tealium iQ estarás implementado la librería en tu site también. El gran Julius Fedorovicious de analyticsmania.com lo resume muy bien en su post GTAG vs. Google Tag Manager’: “Google Tag Manager te permite gestionar códigos, y gtag.js es uno de estos códigos”.

En esta captura de pantalla se ve cómo el hit de GA4 lanzando en este site está ejecutándose desde Google Tag Manager...
...y en esta otra se ve cómo gtag se descarga en este site desde el dominio www.googletagmanager.com

gtag.js expone una API para que interactúes con ella (con la propia librería gtag.js). Para llamar a esta API hay que invocar la función gtag(), que se establece como un método global en tu web, en el objeto Window. Por este motivo verás que hay veces que me refiero a la API GTAG().

La API GTAG() se establece como un método global, es decir, como un método del objeto Window.

A través de esta API puedes dar diferentes instrucciones a la librería gtag.js, desde establecer parámetros de configuración o de consentimiento a enviar eventos. Todo esto está perfectamente descrito en la documentación de Google al respecto, en donde verás que puedes usar los siguientes comandos con esta API:

  • config (para configurar conexiones con herramientas de Google)
  • get (para solicitar valores a la API)
  • set (para establecer valores que puedan ser usados en sucesivas llamadas de tracking)
  • event (para generar eventos)
  • consent (para establecer parámetros de consentimiento)

La API GTAG() se establece como un método global del objeto Window de forma automática si implementas la librería gtag.js en código fuente (tal y como te ilustró un poco más arriba). Ahora bien, es importante que sepas que Google Tag Manager (GTM) no inicializa esta API (tampoco Tealium iQ). Por sorprendente que parezca, tampoco lo hacen los tags de GA4 (o Universal Analytics) que ejecutes desde este TMS. Esto es algo que me ha pillado con la guardia baja, no te lo negaré.

Hice una auditoría de sites con una implementación de GA4 (y por lo tanto con gtag.js) acometida desde GTM y vi que algunos contaban con el método global GTAG () y otros no. Haciendo averiguaciones propias y preguntando a colegas de profesión en Measure Slack (si no eres miembro de esta comunidad, ya estás tardando) finalmente entendí por qué sucedía esto. Tal cual te digo, no es Google Tag Manager per sé quien inicializa GTAG(), sino ciertos templates que llaman a esta API, como por ejemplo el tag de Simo de Consent Mode. Como verás un poco más adelante, es nuy importante tener esto claro.

Llamar a la API de gtag.js desde Tealium iQ para exponer parámetros de GA4 en el objeto utag_data

Como te decía al comienzo de este post, hace algún tiempo estuve trabajando en un proyecto en el que era necesario exponer el client_id y el session_id de GA4 en el data layer de una página web. En este proyecto en concreto se trabajaba con Tealium iQ como TMS, por lo que el requerimiento exacto era exponer esta información en el objeto utag_data. A priori parecía sencillo: bastaría con implementar un script en una extensión de tipo Javascript para llamar a GTAG() con el comando get, pero en seguida me topé con el primer desafío: la API GTAG() es eso, una API, y como tal tarda un cierto tiempo en devolver los valores que le pides (suponiendo que estés haciendo uso del comando get). Siendo así, es necesario que manejes esta latencia de alguna forma u otra para evitar errores.

Una opción (si estás trabajando con Tealium) es asumir este retardo y configurar una extensión con scope ‘After tags’, así te aseguras que el tag de GA4 ya se haya ejecutado cuando esta extensión se ejecute. Pero incluso en estas circunstancias corres el riesgo de que GTAG () tarde en devolver el valor que solicitas. Bajo mi punto de vista la mejor forma de manejar esto es con una promesa. De esta forma puedes desarrollar una lógica a sabiendas de que, aunque la API GTAG() tarde en devolver el valor que solicitas, al final lo hará (¡esa es la promesa!)

Fíjate en el siguiente código. Verás que maneja la llamada a GTAG() con un javascript promise, y que por lo tanto ejecuta la lógica resultante (añadir los parámetros de GA4 al objeto utag_data) cuando la API ya los ha devuelto. Yo lo implementaría, tal y como te digo un poco más arriba, en una extensión de tipo Javascript (o Advanced Javascript) con scope ‘After tags’.:

//Array holding GA4 params to be exposed in utag_data object
let ga4Params = ['client_id','session_id'];
//Running a forEach loop on ga4Params loop
ga4Params.forEach(function(item){
    //Creating a promise that will handle the gtag() call
    let gtagPromise = new Promise(function(resolvedCall, rejectedCall) {
	//Gtag() API call
	   gtag('get','G-your-ga4-ID', item, function(returnedValue){
           resolvedCall(returnedValue); // when call is resolved
           rejectedCall('No clientId available');  // when call is rejected
        })  
    })
    //When the promise is resolved...
    gtagPromise.then(function(returnedValue){
        utag_data[item] = returnedValue
    })
})

¿Cómo llamar a GTAG() desde Google Tag Manager (GTM)?

Llegados a este punto debes saber que el gran Simo Ahava ya desarrolló un Custom Template para llamar a la API GTAG() desde GTM y enviar al dataLayer el client_id, el session_id o el gclid. Usando esta etiqueta tedrías el asunto resuelto. Pero si quieres ir un paso más allá e intentar desarrollar tú mismo la lógica de esta implementación en GTM (cosa que te animo que hagas si realmente quieres aprender), tienes que tener en cuenta dos cosas:

La primera: teniendo en cuenta que ni Google Tag Manager ni los tags de GA4 inicializan la API de gtag.js, ¿tiene tu site este método expuesto en el objeto Window ya? En caso de que no sea así, tienes dos opciones: implementar desde GTM una etiqueta que llame a GTAG() o inicializar tú mismo la API en código fuente con la siguiente línea de código:

<script>
function gtag(){window.dataLayer.push(arguments);}
</script>	
Esta captura de pantalla ilustra cómo la inicialización de gtag() como método global del objeto Window está acometida en código fuente en este site.
Y esta otra ilustra cómo GTAG() es ahora un método global, es decir, un método del objeto Window.
La segunda: no es buena idea llamar a GTAG() desde un CHTML Tag en Google Tag Manager. La documentación de GTM te anima a que no lo hagas, y si lo haces este es el mensaje de alerta que verás:
Mi CHTML Tag me muestra este mensaje en el momento en que detecta que estoy intentando llamar a la API de gtag.js.

Siendo así, lo correcto en este caso es desarrollar un Custom Template (aunque ya tienes el que ha desarrollado Simo) en Google Tag Manager. Si sigues esta senda, la etiqueta que desarrollaras probablemente se encargaría de inicializar GTAG() como un método global, por lo que no tendrías que añadirlo al objeto Window con la línea de código que te he compartido un poco más arriba. 

Otra opción sería implementar la llamada a GTAG() en código fuente. Aunque, todo sea dicho, si trabajas con GTM lo lógico es rehuir de este planteamiento. Pero, eh, yo me he liado la manta a la cabeza para escribir este post y he optado por esta vía. Fíjate en el código que he usado para ello, verás que es igual que el que te propongo un poco más arriba para Tealium iQ. Eso sí, en este caso la promesa empuja al dataLayer de GTM (no referencia al objeto utag_data) los valores que devuelve la API de gtag.js. 

<script>
//Creating two variables to end up holding cookies in an array
let cookieHolder = document.cookie;
let cookieArray = cookieHolder.split(';');
//creating an array with ga4 params to query the GTAG() API with
let ga4Params = ['client_id','session_id'];
//For loop to loop the cookieArray variable in search of the _ga cookie
for(var i = 0; i < cookieArray.length; i++){
    //If _ga cookie is present in cookieArray (and hence analytics consent has been given) fire following logic
    if(cookieArray[i].includes("_ga=")){
        
        ga4Params.forEach(function(item){
            //Initialize empty ga4Object
            let ga4Object = {};
            let gtagPromise = new Promise(function(resolvedCall, rejectedCall) {
            //Gtag() API call
               gtag('get','G-your-ga4-ID', item, function(returnedValue){
                resolvedCall(returnedValue); // when call is resolved
                rejectedCall('No clientId available');  //when call is rejected 
                })  
            })
        
            gtagPromise.then(function(returnedValue){
                ga4Object[item] = returnedValue;
                //Push the ga4Object to the dataLayer
                dataLayer.push(ga4Object);
            })

        })
        //Exit For Loop
        break;
    }
} 
</script>
En esta captura de pantalla se ve claramente la llamada a GTAG() implementada en el código fuente de esta página web. La he implementado en el footer, para asegurarme que gtag.js como el método global GTAG() se han inicializado.
Y en esta otra se aprecia cómo, en efecto, los parámetros de client_id. session_id se han empujado al dataLayer de GTM después de llamar a la API de gtag.js.

Controla el momento en el que llamas a GTAG()

Si GTAG() está inicializado como un método global del objeto Window, la API siempre devolverá un valor si así se lo pides. Esto supone que si ejecutas esta llamada antes de tiempo corres el riesgo de exponer en el data layer un client_id, por ejemplo, que no se corresponda con el que cliente_id real que genere GA4 al ejecutarse.

Fíjate, en la siguiente captura de pantalla puedes ver cómo llamo a GTAG() antes de dar mi consentimiento a ser trazado en mi site (y por lo tanto antes de que GA4 se ejecute):

La API de gtag.js devuelve un valor para el parámetro client_id de GA4 antes de que acepte ser trazado.

Y en la siguiente puedes observar cómo difiere el valor del client_id que muestro en la anterior captura con el valor real del parámetro client_id de GA4. Fíjate en los siguientes tres aspectos: 

  1. El valor original que devolvió GTAG() para el client_id de GA4 (antes de que yo aceptara ser trazado)
  2. El valor que devuelve GTAG() para ese mismo parámetro una vez he dado mi consentimiento para ser trazado.
  3. Cómo este último valor sí se corresponde con el client_id real de GA4. 

Reflexiones finales

Este oficio no tiene fin. ¡No lo tiene! Lo que en un principio era un requisito sencillo de un proyecto (exponer unos parámetros de GA4 en una data layer) terminó por convertirse en un trabajo de desarrollo de analítica puro y duro que pasaba por manejar la respuesta de una API a través de una promesa javascript. Así mismo, lo que en un principio planteé como un sencillo post explicando el ejercicio adaptado a Tealium iQ y a Google Tag Manager (GTM), se convirtió en un estudio de la librería gtag.js y de su API. Pero todo sea dicho, cosas como éstas hacen que me encante mi trabajo.

La verdad es que hay formas más sencillas de capturar el client_id, como por ejemplo leyendo el contenido de la cookie _ga. También podrías obviar este planteamiento e irte a BigQuery en busca de estos parámetros. Siempre hay mil caminos diferentes, es la imaginación al poder. Pero yo creo que merece la pena entender las cosas. En este caso la librería gtag.js, su API y cómo se integran tanto con Tealium y su objeto utag_data como con Google Tag Manager y su dataLayer. Así que ahí queda. Como siempre te digo, ojalá te ayude en tus implementaciones. ¡Hasta la próxima!

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