Una compra, seis filas: CROSS JOIN UNNEST(event_params) antes de contar en el export de GA4
Desanidar event_params con un CROSS JOIN convierte cada evento en una fila por parámetro, y COUNT y SUM se multiplican. Cómo leer parámetros sin duplicar eventos.
- En el export de GA4 cada evento es una fila, y sus parámetros van en un array: event_params.
- Un CROSS JOIN UNNEST(event_params) abre ese array: la compra se convierte en una fila por parámetro.
- Si cuentas después del join, cuentas filas de parámetros: una compra sale seis veces.
- La causa: el UNNEST multiplica las filas por el número de parámetros de cada evento.
- La solución: sacar cada parámetro con una subconsulta. Queda una fila por evento.
- Compruébalo: el recuento coincide con el número de eventos distintos y con GA4.
En el export de GA4 cada evento es una fila, y sus parámetros no son columnas: son un array llamado event_params, con un registro por parámetro (key y un value con string_value, int_value y double_value). Para usar un parámetro hay que abrir ese array con UNNEST. Cómo lo abres decide si tus recuentos son correctos.
Cómo es un recuento multiplicado
Una consulta para contar las compras de un día y sumar los ingresos, escrita con CROSS JOIN UNNEST(event_params) para llegar a value:
COUNT(*)da varias veces el número de compras del informe de GA4: en el ejemplo, seis veces.- Los ingresos sumados desde otra columna del evento (o desde un parámetro leído en un segundo join) se multiplican por el mismo factor.
- El factor no es fijo: depende de cuántos parámetros lleva cada evento, así que cambia de un evento a otro y de un día a otro.
- Los eventos con
event_paramsvacío desaparecen del resultado.
Por qué UNNEST multiplica las filas
Es el comportamiento normal de SQL, no una rareza de GA4. CROSS JOIN UNNEST(array) devuelve una fila por cada elemento del array, repitiendo en cada una el resto de columnas del evento. Un purchase con seis parámetros (page_location, ga_session_id, value, currency, transaction_id, engagement_time_msec) se convierte en seis filas.
A partir de ahí, todo lo que calcules sobre el resultado del join cuenta filas de parámetros, no eventos:
COUNT(*)después del join cuenta parámetros.SUMde columnas del evento (por ejemploecommerce.purchase_revenue) suma el mismo valor una vez por parámetro.- Un segundo
UNNESTpara leer otro parámetro vuelve a multiplicar: filas × filas. - Un
WHERE key = 'value'después del join lo deja en una fila por evento, pero solo para esa clave; en cuanto necesitas dos parámetros, el problema vuelve.
Y como es un CROSS JOIN, un evento con el array vacío no tiene fila con la que unirse y se pierde.
Cómo encontrar un recuento multiplicado
- Busca en tus consultas y vistas
CROSS JOIN UNNEST(event_params)o la forma con coma,FROM events_*, UNNEST(event_params). - Compara
COUNT(*)con el número de eventos distintos en la misma consulta. Si no coinciden, se están multiplicando filas. - Compara el número de eventos
purchasey los ingresos con el informe de GA4 del mismo día cerrado. Una diferencia de varias veces, y no de unos pocos puntos, apunta a esto.
Cómo leer parámetros sin duplicar eventos
El patrón del recetario de consultas de GA4 de Google es una subconsulta escalar por parámetro: lee un valor del array y deja una fila por evento.
SELECT
COUNT(*) AS purchases,
SUM((SELECT COALESCE(value.double_value, value.int_value)
FROM UNNEST(event_params) WHERE key = 'value')) AS revenue,
(SELECT value.string_value
FROM UNNEST(event_params) WHERE key = 'currency') AS currency
FROM `analytics_123.events_20261028`
WHERE event_name = 'purchase'
GROUP BY currency
- Una subconsulta por cada parámetro que necesites: no hay nada que multiplicar porque la fila del evento nunca se repite.
- Lee el campo adecuado al tipo: un número puede llegar en
int_valueo endouble_valuesegún cómo se haya enviado, así que usaCOALESCEcon los dos si no estás seguro. - Si de verdad necesitas una fila por parámetro (para listar cuáles lleva un evento, por ejemplo), usa
LEFT JOIN UNNEST(event_params)para no perder eventos, y no cuentes eventos sobre ese resultado.
Documentación: esquema del export a BigQuery y consultas básicas de GA4 en BigQuery (en inglés).
Cómo comprobar que cada evento cuenta una vez
COUNT(*)es igual al número de eventos distintos de la consulta.- El número de compras y los ingresos de un día cerrado se acercan al informe de GA4 (algo de diferencia es normal; los siguientes artículos explican por qué).
- Añadir otro parámetro a la consulta no cambia el recuento.
Los parámetros, los IDs y las cifras del ejemplo son ilustrativos.