La interfaz de GA4 está diseñada para responder preguntas que Google anticipó. En el momento en que necesitás una pregunta propia —una definición de sesión distinta, un funnel que cruza eventos con datos del CRM, una cohorte que la UI no arma— chocás contra un límite que no se resuelve con más reportes exploratorios.

La exportación a BigQuery es la salida. Te da los eventos crudos, fila por fila, en tu propio warehouse, y a partir de ahí SQL responde lo que quieras preguntar.

Antes de nada, la advertencia más importante.

No es retroactiva

Cuando conectás una propiedad de GA4 con BigQuery, la exportación arranca ese día. No hay configuración, ni ticket de soporte, ni plan pago que complete los meses anteriores. Los datos que no exportaste no existen en ningún lugar al que la exportación pueda llegar: GA4 no guarda las filas crudas de forma que se puedan reproducir.

Por eso la recomendación es activarla el día uno de cualquier propiedad, aunque nadie planee consultarla en un año. Es gratis dentro de los límites del sandbox de BigQuery y el dato no vale nada hasta que existe.

Si llegaste tarde: se puede traer historia agregada vía la Data API de GA4 y cargarla en una tabla aparte. Sirve para comparaciones año contra año de métricas de alto nivel, pero es otra cosa, no la exportación. Viene agregada, sin nivel de evento, con el long tail colapsado en (other) por los límites de cardinalidad y con filas ocultas por thresholding si tenés Google Signals activo. Los números no van a cuadrar con los de la exportación para el mismo período, ni siquiera en principio. Etiquetá la costura y seguí adelante.

Cómo se activa

Admin → Vínculos de productos → Vínculos con BigQuery. Dos decisiones:

  • Exportación diaria. Una tabla por día, events_YYYYMMDD, que aparece a la mañana siguiente. Es la que querés siempre.
  • Exportación en streaming. Escribe en events_intraday_ de forma continua. Útil si necesitás datos del día en curso; tiene costo de streaming y la tabla se reemplaza por la diaria cuando el día cierra. Consultala a propósito o vas a duplicar el día de hoy.

Dos días después, verificá que esté corriendo. Una propiedad vinculada con un problema de facturación o de permisos no produce nada en silencio, y la gente se entera meses más tarde.

El esquema, que es donde todos tropiezan

Las tablas de eventos están anidadas. event_params es un registro repetido: cada fila tiene una key y un struct value con los campos string_value, int_value, float_value y double_value, de los cuales sólo uno viene poblado. Sacar un parámetro implica desanidar:

SELECT
  event_date,
  event_name,
  (SELECT value.string_value FROM UNNEST(event_params)
    WHERE key = 'page_location') AS page_location,
  (SELECT value.int_value FROM UNNEST(event_params)
    WHERE key = 'ga_session_id') AS session_id
FROM `proyecto.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260101' AND '20260131'

user_properties, items y los campos de fuente de tráfico siguen el mismo patrón de registro repetido.

Tres cosas más que sorprenden:

  • La sesión no es una columna. Una sesión es user_pseudo_id más el parámetro ga_session_id. Contar sesiones implica construirlas.
  • No hay un campo único de “source/medium” por sesión. La atribución de tráfico en la exportación no es el mismo objeto que reporta la UI de GA4, y reproducir los números de la interfaz desde los eventos crudos es un proyecto, no una consulta.
  • user_id sólo está si lo mandás. Sin él, cruzar con el CRM depende de que hayas guardado algún identificador propio en un parámetro.

Controlar el costo

El sandbox de BigQuery alcanza para propiedades chicas. Más allá de eso, tres hábitos:

Filtrá siempre por _TABLE_SUFFIX. Un SELECT sobre events_* sin filtro de fecha escanea toda la historia. Es la forma más rápida de gastar el presupuesto del mes en una consulta exploratoria.

Nunca uses SELECT *. BigQuery cobra por bytes escaneados por columna. Pedí las columnas que necesitás.

Construí tablas intermedias. En lugar de desanidar eventos crudos en cada consulta, armá una tabla de sesiones y una de conversiones, particionadas por fecha, y consultá contra esas. Es más barato, más rápido y —sobre todo— hace que la definición de “sesión” viva en un solo lugar.

Para qué sirve realmente

Las cosas que justifican el trabajo:

  • Conectar medios con facturación real. Cruzar eventos de GA4 con pedidos o deals del CRM responde qué canal trae clientes que pagan, no cuál genera formularios. Es el antídoto contra el problema de la atribución last-touch.
  • Definiciones propias. Tu definición de “usuario activo”, tu ventana de sesión, tu funnel.
  • Análisis de cohortes y retención serio, más allá de lo que la UI permite.
  • Auditar la medición. Contar cuántas veces dispara cada evento por sesión encuentra duplicaciones que en la interfaz son invisibles y que están corrompiendo tu bidding.
  • Alimentar un dashboard que no dependa de GA4. Ver cómo armar un dashboard que se use.

Por dónde empezar

  1. Activá la exportación hoy, en todas las propiedades, incluidas las de staging.
  2. Verificá a los dos días que las tablas existan.
  3. Escribí una consulta que cuente eventos por nombre y por día. Es la que detecta lo que está roto.
  4. Armá una tabla de sesiones particionada por fecha y usala como base de todo lo demás.
  5. Recién después conectá el CRM.

Si estás decidiendo qué tipo de propiedad deberías estar corriendo, GA4 vs Firebase cubre la diferencia. Y si el problema es que la medición en sí no es confiable, server-side tracking suele ser el paso anterior.

Si heredaste una propiedad sin exportación y con una fecha de entrega encima, es el tipo de cosa que desenredo en la primera semana de una auditoría.