BigQuery: Evolución de la atribución y su impacto en la analítica digital

Introducción

Con el lanzamiento de Google Analytics 4 (GA4), la forma en que las empresas analizan y gestionan los datos de usuarios ha dado un giro significativo. A diferencia de su predecesor, Universal Analytics, GA4 ofrece una estructura centrada en eventos, lo que permite una mayor flexibilidad y precisión en el análisis de datos. Sin embargo, esta nueva arquitectura también ha traído consigo una mayor complejidad, especialmente cuando se trata de manejar grandes volúmenes de datos. Es aquí donde BigQuery entra en juego, proporcionando a los usuarios de GA4 una plataforma robusta y escalable para almacenar, consultar y analizar estos datos a gran escala.

Uno de los mayores desafíos desde el inicio de GA4, ha sido cuadrar los datos obtenidos en BigQuery con los reportes de la interfaz de Google. Muchos analistas han encontrado discrepancias entre las cifras reportadas en ambas plataformas debido a diferencias en los modelos de atribución, el tratamiento de eventos y la aplicación de filtros predeterminados en la interfaz de GA4.

BigQuery y GA4

Durante mucho tiempo, la exportación directa de datos de GA4 a BigQuery ha carecido de herramientas avanzadas para medir la atribución de conversiones y la evaluación precisa de las fuentes de tráfico. Sin embargo, con el tiempo, Google ha ido incorporando poco a poco nuevas dimensiones y estructuras de datos en la exportación de GA4 a BigQuery, permitiendo una mejor interpretación del recorrido del usuario.

Estos cambios han venido acompañados de desafíos y quebraderos de cabeza, como errores en la atribución del tráfico de pago y la necesidad de implementar soluciones personalizadas en BigQuery para corregir sesgos en los datos.

Aunque finalmente, Google ha incorporado una serie de nuevos parámetros que parecen dar solución a estos problemas de atribución, este cambio no es retroactivo en el tiempo, por lo que para analizar el histórico, tendremos que seguir recurriendo a estas soluciones personalizadas y poder así tomar decisiones basadas en datos confiables.

En este artículo, exploraremos la evolución de la atribución en BigQuery, los principales problemas que han surgido y las estrategias para resolverlos mediante consultas avanzadas.

Modelos de atribución, dimensiones y métricas de adquisición en GA4 y su evolución en BigQuery

Antes de profundizar en la evolución de la atribución en BigQuery, es fundamental aclarar algunos conceptos clave que servirán de base para comprender mejor el análisis presentado en este artículo.

Modelos de atribución

Aunque el artículo está orientado al modelo de atribución basado en el último clic para canales de pago y orgánicos, en GA4 podemos encontrar tres modelos de atribución bastante básicos:

Último clic (Canales de pago y orgánicos)

Obvia el tráfico directo y asigna el 100% de la atribución al último clic.

modelo último click

Último clic (Canales de pago de Google)

Obvia todos los canales que no sean de Google Ads y asigna 100% al último clic.

LastClick canales de pago de Google

Basado en datos (Canales de pago y orgánicos)

Actualmente es el “recomendado” por Google y se basa en Inteligencia Artificial, más concretamente en el Machine Learning.

Nota:

Los cambios en el modelo de atribución de los informes se aplican a los datos pasados y futuros.

Dimensiones de adquisición

En Google Analytics 4 (GA4), existen dos tipos de dimensiones de atribución relacionadas con la fuente, medio y campaña de la sesión:

  • Fuente, medio y campaña de la sesión estándar.
  • Fuente, medio y campaña manual de la sesión.
Diferencias clave entre ambas
Dimensiones de identificación de tráfico

La diferencia clave radica en cómo se asignan los valores de fuente, medio y campaña de la sesión. Mientras que GA4 puede modificar estos valores utilizando la atribución basada en clics previos, el gclid o modelos predictivos, las dimensiones de fuente, medio y campaña manual de la sesión reflejan únicamente los valores de los parámetros UTM presentes en la URL, sin alteraciones.

Debido a que cada conjunto de dimensiones procesa el tráfico de manera distinta, es natural que existan discrepancias entre ambas.

Sin embargo, al comparar globalmente las dimensiones de fuente y medio, resulta llamativa la cantidad de tráfico de pago clasificado erróneamente como tráfico orgánico en las dimensiones de fuente y medio manual de la sesión.

Fuente y media en GA4

El problema surge cuando un usuario accede a una página a través de un anuncio de búsqueda de pago en Google y la URL incluye el parámetro gclid. Sin embargo, a pesar de esta indicación, GA4 atribuye erróneamente el evento como tráfico orgánico o directo en lugar de reconocerlo como tráfico de pago.

A pesar de que este error es conocido desde hace tiempo, Google no ha tomado medidas para corregirlo. Afortunadamente, existen soluciones alternativas que podemos aplicar y que veremos más adelante.

Evolución de la atribución en BigQuery

Con el tiempo, Google ha ido incorporando nuevas dimensiones para mejorar la transparencia y precisión de la atribución del origen del tráfico y las conversiones. Se pueden analizar en tres niveles principales:

1. Nivel de usuario (traffic_source)

Contiene información sobre la fuente de tráfico con la que se adquirió al usuario por primera vez, es decir, los valores de traffic_source no cambian si el usuario interactúa con otras campañas. Esta información no se rellena en tablas intradía y está disponible desde 2021.

Origen de tráfico
Información detallada de los campos:
  • traffic_source.name: El nombre de la campaña de marketing con la que se adquirió al usuario.
  • traffic_source.medium: El nombre del medio con el que se adquirió al usuario.
  • traffic_source.source: El nombre de la fuente con la que se adquirió al usuario. Este campo no se rellena en tablas intradías
Ejemplo de consulta:
Select
  traffic_source.source,
  traffic_source.medium,
  traffic_source.name,
  count(distinct(user_pseudo_id)) as users
from
  `tu_proyecto.tu_dataset.events_*`
group by
  all

Aunque no es una dimensión que se utilice con frecuencia, las comparaciones con los informes de la interfaz de GA4 siempre han mostrado coherencia, lo que refuerza la fiabilidad de sus datos.

2. Nivel de evento (collected_traffic_source)

Aunque los parámetros de fuentes de tráfico siempre han estado disponibles dentro de event_params, desde mayo de 2023, Google introdujo nuevos campos que simplifican las consultas y mejoran el rendimiento, al eliminar la necesidad de desanidar estructuras.

Por ello, para obtener datos posteriores a mayo de 2023, es recomendable utilizar el campo collected_traffic_source para simplificar tus consultas y mejorar el rendimiento. En cualquiera de los casos, el valor recogido por ambas opciones es idéntico.

Estos campos serán utilizados para el cálculo de las dimensiones fuente, medio y campaña manual de la sesión.

Collected Traffic Source
Información detallada de los campos:
  • collected_traffic_source.manual_campaign_name: El nombre de la campaña manual que se ha recogido con el evento.
  • collected_traffic_source.manual_source: La fuente de la campaña manual que se ha recogido con el evento.
  • collected_traffic_source.manual_medium: El medio de la campaña manual que se ha recogido con el evento.
  • collected_traffic_source.gclid: El identificador de clic de Google que se ha recogido con el evento.
Ejemplo de consulta para fechas anteriores a mayo de 2023:
select
  (select value.string_value from unnest (event_params) where key = 'source') as event_source,
  (select value.string_value from unnest (event_params) where key = 'medium') as event_medium ,
  (select value.string_value from unnest (event_params) where key = 'campaign') as event_campaign_name,
  (select value.string_value from unnest (event_params) where key =  'gclid') as gclid,
  count(distinct concat(user_pseudo_id,(select value.int_value from unnest (event_params) where key = 'ga_session_id'))) as sessions
from 
  `tu_proyecto.tu_dataset.events_*`
group by 
  all
Ejemplo de consulta para fechas posteriores a mayo de 2023:
select
  collected_traffic_source.manual_campaign_name as event_campaign_name,
  collected_traffic_source.manual_source as event_source,
  collected_traffic_source.manual_medium as event_medium,
  collected_traffic_source.gclid as gclid,
  count(distinct concat(user_pseudo_id,(select value.int_value from unnest (event_params) where key = 'ga_session_id'))) as sessions
from 
  `tu_proyecto.tu_dataset.events_*`
group by 
  all

Hasta la aparición de los nuevos campos específicos a nivel de sesión, que veremos a continuación, la única manera de medir la atribución de las sesiones de GA4 en BigQuery ha sido mediante estos parámetros de evento, utilizando consultas en SQL más avanzadas.

Estas consultas extraen los valores de fuente y medio a partir de los parámetros del evento, los ordenan según su secuencia de ejecución y asignan el primer valor no nulo a las columnas manual_source_session y manual_medium_session, respectivamente.

Además, garantiza que si manual_source_session y manual_medium_session son nulos, se usen los valores predeterminados (not set) y (not set) como Google indica en sus informes de fuente y medio manual de la sesión.

De este modo, se busca replicar el modelo de atribución de GA4 de Último clic (Canales de pago y orgánicos), que asigna el 100% de la conversión a la última interacción del usuario, ignorando el tráfico directo.

Ejemplo de consulta:
with base as 
(
select
  concat(user_pseudo_id,(select value.int_value from unnest (event_params) where key = 'ga_session_id')) as session_id,
  array_agg((select value.string_value from unnest (event_params) where key = 'source') ignore nulls order by event_timestamp ASC) [safe_offset(0)] as manual_source_session,
  array_agg((select value.string_value from unnest (event_params) where key = 'medium') ignore nulls order by event_timestamp ASC) [safe_offset(0)] as manual_medium_session
from
  `tu_proyecto.tu_dataset.events_*`
group by
  all
)
select
  concat(coalesce(manual_source_session,'(not set)'),' / ',coalesce(manual_medium_session,'(not set)')) as manual_source_medium_session,
  count(distinct(session_id)) as sessions
from
  base
group by
  all

Los resultados de estas consultas son comparables con los datos de los informes de GA4 para las dimensiones de fuente, medio y campaña manual de la sesión.

Sin embargo, como mencionamos anteriormente, no reflejan con precisión el tráfico de pago. Más adelante en el artículo, exploraremos cómo corregir este problema.

3. Nivel de sesión (session_traffic_source_last_click)

En julio de 2024, se agregó un nuevo registro al esquema de BigQuery de GA4: session_traffic_source_last_click Este registro contiene por primera vez, información sobre el origen del tráfico con alcance de sesión y utiliza la misma atribución del último clic no directo que se encuentra en la interfaz de usuario de GA4.

O como lo indica Google en las notas de la versión GA4:

«Hemos agregado un nuevo registro a la exportación de eventos de BigQuery de GA4 que contiene la información de contexto de campañas manuales y de Google Ads para cada sesión presente en la exportación. Esta información se repite para cada evento de una sesión para permitir un análisis de canal rápido y sencillo en BigQuery de cualquier evento dentro de una sesión. Los datos exportados son los mismos que los que se usan en los informes de comportamiento de GA4.»

Bigquery. Estructura de tablas
Bigquery. Estructura de tablas

El registro session_traffic_source_last_click apareció inicialmente con dos subregistros: manual_campaign y google_ads_campaign. Sin embargo, fue en octubre cuando se introdujeron el resto de los subregistros. En este artículo, nos centraremos exclusivamente en dos de ellos: manual_campaign y cross_channel_campaign.

manual_campaign

Este primer subregistro contiene valores similares a los valores recogidos en collected_traffic_source. La diferencia es que estos nuevos parámetros tienen un alcance de sesión y utilizan el modelo de atribución de último clic no directo, mientras que los de collected_traffic_source tienen un alcance de evento y no se aplica ningún modelo de atribución.

Información detallada de los campos:
  • session_traffic_source_last_click.manual_campaign.source: La fuente específica de la plataforma de la última campaña manual en la que se hizo clic.
  • session_traffic_source_last_click.manual_campaign.medium: El medio de la última campaña manual en la que se hizo clic.
  • session_traffic_source_last_click.manual_campaign.campaign_name: El nombre de la última campaña manual en la que se hizo clic.
Ejemplo de consulta:
select
  session_traffic_source_last_click.manual_campaign.source as manual_source_session,
  session_traffic_source_last_click.manual_campaign.medium as manual_medium_session,
  session_traffic_source_last_click.manual_campaign.campaign_name as manual_campaign_name_session,
  count(distinct concat(user_pseudo_id,(select value.int_value from unnest (event_params) where key = 'ga_session_id'))) as sessions
from 
  `tu_proyecto.tu_dataset.events_*`
group by 
  all

Los resultados obtenidos son equivalentes a los informes de GA4 sobre fuente, medio y campaña manual de la sesión, que como ya se mencionó, no reflejan con precisión el tráfico de pago, lo cual se abordará más adelante.

cross_channel_campaign

La reciente incorporación del subregistro cross_channel_campaign en octubre de 2024 supone un avance clave en el análisis de atribución de GA4 a través de BigQuery, algo que se llevaba mucho tiempo esperando.

Por fin, Google ha integrado estos campos, facilitando por primera vez la agrupación de canales y alineando los datos obtenidos en BigQuery con los informes de GA4 sin necesidad de consultas adicionales.

Esta actualización aporta claridad al panorama de trabajar con datos de atribución en BigQuery, reflejando con precisión fuente, medio y campaña de la sesión.

Información detallada de los campos:
  • session_traffic_source_last_click. cross_channel_campaign.source: La fuente específica de la plataforma de la última campaña multicanal en la que se hizo clic.
  • session_traffic_source_last_click.cross_channel_campaign.medium: El medio de la última campaña multicanal en la que se hizo clic.
  • session_traffic_source_last_click.cross_channel_campaign.campaign_name: El nombre de la última campaña multicanal en la que se hizo clic.
  • session_traffic_source_last_click.cross_channel_campaign.default_channel_group: El canal predeterminado de la última campaña multicanal en la que se hizo clic.
  • session_traffic_source_last_click.cross_channel_campaign.primary_channel_group: El canal principal de la última campaña multicanal en la que se hizo clic.
Ejemplo de consulta:
select
  session_traffic_source_last_click.cross_channel_campaign.source as session_source,
  session_traffic_source_last_click.cross_channel_campaign.medium as session_medium,
  session_traffic_source_last_click.cross_channel_campaign.campaign_name as session_campaign_name,
  count(distinct concat(user_pseudo_id,(select value.int_value from unnest (event_params) where key = 'ga_session_id'))) as sessions
from 
  `tu_proyecto.tu_dataset.events_*`
group by
  all

Los resultados obtenidos son equivalentes a los informes de GA4 sobre fuente, medio y campaña de la sesión.

BigQuery: Consultas sobre el tráfico de pago en GA4

Uno de los errores más frustrantes en GA4, especialmente para quienes trabajan con la exportación de datos en BigQuery, es la atribución incorrecta del tráfico de pago.

Para dar solución a esta casuística tenemos dos opciones:

La primera y más sencilla se trata de sobrescribir los campos de adquisición de tráfico «source/medium», asignando ‘google / cpc’ a las sesiones en las que el parámetro gclid está presente.

Ejemplo de consulta para fechas anteriores a julio de 2024:
with session_sources as (
  select 
    event_date,
    concat(user_pseudo_id,(select value.int_value from unnest(event_params) where key = 'ga_session_id')) as session_id,
    array_agg((select value.string_value from unnest(event_params) where key = 'source') ignore nulls order by event_timestamp asc)[safe_offset(0)] as manual_source_session,
    array_agg((select value.string_value from unnest(event_params) where key = 'medium') ignore nulls order by event_timestamp asc)[safe_offset(0)] as manual_medium_session
  from 
    `tu_proyecto.tu_dataset.events_*`
  group by 
    all
  ),
session_gclid as (
  select 
    event_date,
    concat(user_pseudo_id,(select value.int_value from unnest(event_params) where key = 'ga_session_id')) as session_id,
  from 
    `tu_proyecto.tu_dataset.events_*`
  where 
    collected_traffic_source.gclid is not null
  group by 
    all
  )
select 
  ss.event_date,
  case when sg.session_id is not null then 'google / cpc' 
  else concat(coalesce(ss.manual_source_session, '(not set)'), ' / ', coalesce(ss.manual_medium_session, '(not set)')) 
  end as manual_source_medium_session,
  count(distinct ss.session_id) as sessions
from 
  session_sources ss
left join session_gclid sg 
on ss.session_id = sg.session_id and ss.event_date = sg.event_date
group by 
  all
Ejemplo de consulta para fechas anteriores a octubre de 2024:
with session_sources as (
  select 
    event_date,
    concat(user_pseudo_id,(select value.int_value from unnest(event_params) where key = 'ga_session_id')) as session_id,
    session_traffic_source_last_click.manual_campaign.source as manual_source_session,
    session_traffic_source_last_click.manual_campaign.medium as manual_medium_session 
 from `tu_proyecto.tu_dataset.events_*`
 group by 
   all
  ),
session_gclid as (
  select 
    event_date,
    concat(user_pseudo_id,(select value.int_value from unnest(event_params) where key = 'ga_session_id')) as session_id,
  from `tu_proyecto.tu_dataset.events_*`
  where 
    collected_traffic_source.gclid is not null
  group by 
    all
  )
select 
  ss.event_date,
  case when sg.session_id is not null then 'google / cpc' 
  else concat(coalesce(ss.manual_source_session, '(not set)'), ' / ', coalesce(ss.manual_medium_session, '(not set)')) 
  end as manual_source_medium_session,
  count(distinct ss.session_id) as sessions
from 
  session_sources ss
left join session_gclid sg 
on ss.session_id = sg.session_id and ss.event_date = sg.event_date
group by 
  all

Para informes agregados, esta solución puede ser muy útil. Sin embargo, muchos profesionales de marketing necesitan un nivel de detalle más preciso, especialmente a nivel de campaña.

Una segunda alternativa y más compleja para reparar la atribución de las campañas del tráfico de pago sería:

  • Extraer de GA4 el parámetro gclid de cada sesión en la que esté disponible.
  • Habilitar la transferencia de datos de Google Ads a BigQuery.
  • Extraer de las tablas de Google Ads el parámetro gclid.
  • Unir los datos de GA4 con los datos de campaña Google Ads en BigQuery mediante el parámetro gclid.
  • Recuperar el nombre de la campaña para cada sesión de las tablas de Google Ads.

Conclusión

La evolución de la atribución en GA4 y BigQuery ha permitido avanzar significativamente en la precisión del análisis de datos. Gracias a la última actualización, con la incorporación de nuevos registros y subregistros, muchos de los problemas históricos de atribución parecen haberse corregido, especialmente los relacionados con el tráfico de pago y la necesidad de crear reglas y campos calculados para las agrupaciones de canales. Esto ha mejorado considerablemente la coherencia entre los datos exportados a BigQuery y los informes de GA4.

Para garantizar un análisis preciso y contar con un histórico fiable, será necesario recurrir a las soluciones personalizadas según la fecha de los datos. Esto no solo optimizará las decisiones estratégicas, sino que también mejora el rendimiento de las futuras campañas publicitarias.

Si bien las consultas propuestas en el artículo y las comparativas entre los datos de BigQuery y los informes de GA4 han mostrado resultados similares y consistentes, no son exactamente idénticos debido a las diferencias inherentes en el tratamiento y la atribución de los datos.

Por lo tanto, aunque la aproximación es sólida, es posible que se requieran ajustes personalizados según el contexto específico de cada empresa o campaña, dada la complejidad de los datos y la evolución continua de las herramientas.

Alvaro Rodríguez Herranz
Alvaro Rodríguez Herranz

Economista reconvertido en analista digital. Hace ya 4 años que la analítica web llamó a mi puerta y, desde entonces, he explorado la parte técnica, de negocio y BigQuery, donde me encanta bucear en los datos. Me especializo en la integración, extracción, transformación y análisis de datos, convirtiendo información compleja en reportes claros y visuales que ofrecen una visión 360° del negocio. Me divierto descubriendo poltergeists en los datos y optimizando procesos.

Deja un comentario