Primero la mala noticia, porque todo lo demás se desprende de ahí: la exportación de GA4 a BigQuery no es retroactiva. Cuando vinculá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.

Sorprende a alguien todas las semanas, y es el argumento más fuerte a favor de vincular BigQuery el día uno de cualquier propiedad, aunque nadie planee consultarla en un año. La exportación es gratis dentro de los límites del sandbox de BigQuery y el dato no vale nada hasta que existe.

Si te acabás de enterar, acá va qué podés y qué no podés hacer al respecto.

Por qué no existe un backfill real

La exportación diaria escribe una tabla por día —events_YYYYMMDD— con cada evento que GA4 recolectó, a nivel evento, con el payload completo de parámetros. Esa granularidad existe sólo porque el pipeline de exportación la escribió en el momento de la recolección. La interfaz de GA4 no retiene filas a nivel evento de una forma que se pueda reproducir: guarda datos de reporte agregados y procesados.

O sea que no hay nada de dónde hacer el backfill. Las filas crudas nunca se guardaron en un lugar al que la exportación pueda llegar.

Qué sí podés recuperar

Histórico a nivel evento, no. Histórico agregado, sí, vía la Data API de GA4, cargándolo en BigQuery como tabla propia. Vale la pena hacerlo — sólo hay que ser preciso sobre qué es.

El enfoque:

  1. Consultá la Data API de GA4 por las dimensiones y métricas que necesites, día por día.
  2. Escribí el resultado en una tabla aparte de BigQuery —algo como ga4_api_historico— y deliberadamente no mezclada dentro del dataset de events_*.
  3. Unila con la exportación real sólo en una vista de reporting, con una columna que marque el origen.

La versión scripteada de esto es un camino bastante transitado; hay varios conectores open-source y las librerías cliente de googleanalyticsdata manejan la paginación y los reintentos por vos. Presupuestá un día, no una semana.

Los cuatro límites que duelen

Es agregado, no a nivel evento. Obtenés sesiones por fuente/medio por día. No podés reconstruir el camino de un usuario, recalcular una definición de sesión propia, ni aplicar otro modelo de atribución después del hecho. Cualquier análisis que necesite la secuencia cruda no es recuperable.

Los límites de cardinalidad colapsan el long tail. Cuando una dimensión supera los límites de cardinalidad de GA4, los valores se agrupan en (other). En dimensiones de alta cardinalidad —ruta de página, nombre de ítem, término de búsqueda— eso puede tragarse una parte relevante de tu histórico, y se aplica antes de que vos veas el dato.

El thresholding esconde filas. Con Google Signals activo y pocos registros, GA4 retiene datos por privacidad. Tu extracción por API va a estar silenciosamente incompleta y los totales no van a cuadrar. Apagar Google Signals para la identidad de reporte puede reducirlo, pero no revela retroactivamente lo que ya fue retenido.

Muestreo en consultas complejas. Rangos de fechas largos con varias dimensiones pueden devolver resultados muestreados. Revisá la metadata de muestreo en la respuesta en lugar de asumir.

La conclusión práctica: los números del backfill por API no van a cuadrar con los de la exportación para el mismo período, ni siquiera en principio. No armes un proceso de conciliación que asuma que deberían. Etiquetá la costura y seguí.

La diferencia de esquema que rompe los joins

Acá es donde se tuercen casi todos los proyectos de backfill. Las dos fuentes no son sólo distintas en granularidad: tienen forma distinta.

Las tablas events_* de la exportación 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,
  (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. La Data API no devuelve nada de esto: devuelve filas planas de dimensiones y métricas.

Tres cosas más que agarran desprevenido:

  • events_intraday_ es una tabla aparte con la misma forma, presente sólo si tenés la exportación en streaming, y la reemplaza la tabla diaria cuando el día cierra. Consultala a propósito o vas a contar hoy dos veces.
  • 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 único campo de “source/medium” por sesión. La atribución de tráfico en la exportación no es el mismo objeto que reporta la interfaz de GA4, y reproducir los números de la UI desde los eventos crudos es un proyecto, no una consulta.

Frená el reloj y después decidí

Hagas lo que hagas con el histórico, hacé esto hoy, en este orden:

  1. Vinculá BigQuery ahora. Admin → Vínculos de productos → BigQuery. Como mínimo la exportación diaria; sumá streaming si querés intradía. Cada día que esperás es un día que falta para siempre.
  2. Activá la exportación en todas las propiedades, incluidas las de staging y las de poco tráfico. El almacenamiento es barato; el hueco no se recupera.
  3. Verificá dos días después que esté corriendo. Una propiedad vinculada con un problema de facturación o permisos no produce nada en silencio, y la gente se entera meses más tarde.
  4. Recién ahí decidí si el backfill agregado vale el día de trabajo. Muchas veces sí, para comparaciones año contra año de un puñado de métricas de alto nivel. Rara vez vale la pena intentar reconstruir algo granular.

Cuando el hueco importa de verdad

Si necesitás histórico real a nivel evento de un período que la exportación no cubre, las respuestas honestas son limitadas:

  • Tus logs de servidor, si los eventos que te importan también pegan en tu backend. Para ecommerce, la data de pedidos en la base transaccional suele ser mejor registro del que la analítica fue nunca.
  • Tu CRM, para generación de leads. El histórico de cerrado-ganado vive ahí y es más confiable que GA4 para preguntas de facturación.
  • Un setup warehouse-first de acá en adelante, para que no vuelva a pasar: recolección que escribe primero en tu propio almacén y reenvía a la analítica después, en lugar de al revés. Es la misma arquitectura que server-side tracking.

Para todo lo demás, aceptá la costura. Una discontinuidad claramente etiquetada en un dashboard es muchísimo mejor que un número conciliado construido sobre dos definiciones incompatibles.

Más sobre montar la exportación bien, incluido particionado y control de costo, en exportar GA4 a BigQuery. Y si todavía estás decidiendo qué tipo de propiedad deberías correr, GA4 vs Firebase cubre la diferencia.

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.