Экспорт GA4 в BigQuery: анализ сырых маркетинговых данных
Продвинутое4 минРедакция Innovialabs
Коротко
Экспорт GA4 в BigQuery выгружает каждое событие сайта в отдельную строку, без семплирования и порогов интерфейса. Связь настраивается за несколько минут в админке GA4, а основные навыки — это UNNEST для параметров событий и фильтр по датам таблиц, чтобы запросы не стоили дорого.
Зачем выгружать GA4 в BigQuery
Интерфейс GA4 показывает агрегированные отчёты с ограничениями: пороги данных, лимиты на кардинальность, сложные исследования. Экспорт в BigQuery даёт сырые события — каждое событие отдельной строкой со всеми параметрами. Это нужно, когда вы хотите:
- построить собственные воронки и атрибуцию;
- объединить данные сайта с CRM, расходами на рекламу и офлайн-продажами;
- хранить историю дольше, чем позволяет срок хранения в GA4;
- строить дашборды в Looker Studio или BI без ограничений API.
Как связать GA4 с BigQuery
- Создайте проект в Google Cloud и включите BigQuery API. Для начала подойдёт песочница BigQuery без привязки карты, но таблицы в ней удаляются автоматически, а потоковый экспорт недоступен.
- В GA4 откройте Администратор → Связи с продуктами → Связи с BigQuery и создайте связь. Нужны права редактора в GA4 и владельца в проекте GCP.
- Выберите регион хранения данных — изменить его потом нельзя.
- Выберите тип экспорта:
- Ежедневный — таблица
events_YYYYMMDDраз в сутки. - Потоковый —
events_intraday_YYYYMMDDв течение дня, платный.
- Ежедневный — таблица
- При необходимости исключите лишние события, чтобы уменьшить объём.
Данные появляются со следующего дня; исторических данных до момента связи экспорт не содержит. Поэтому подключайте его как можно раньше, даже если анализировать будете позже.
Схема таблицы событий
Одна строка — одно событие. Ключевые поля:
| Поле | Что в нём |
|---|---|
event_date, event_timestamp | дата и время в микросекундах |
event_name | page_view, purchase и т. д. |
event_params | повторяющийся массив ключ–значение |
user_pseudo_id | идентификатор устройства/браузера |
user_id | ваш ID пользователя, если передаёте |
traffic_source | источник первого визита пользователя |
collected_traffic_source | UTM и click ID, пойманные на этом событии |
device, geo | устройство и география |
ecommerce, items | данные электронной торговли |
Главная особенность — event_params. Значение параметра лежит в одном из полей value.string_value, value.int_value, value.double_value, и достать его можно только через UNNEST.
Пример: сессии по дням
Сессия в экспорте — это пара user_pseudo_id и параметра ga_session_id.
SELECT
event_date,
COUNT(DISTINCT CONCAT(user_pseudo_id, CAST(
(SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id')
AS STRING))) AS sessions
FROM `my-project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20261001' AND '20261007'
GROUP BY event_date
ORDER BY event_date;
Пример: сессии по источникам
В новых выгрузках есть поле session_traffic_source_last_click с источником сессии по последнему клику. Для старых данных источник сессии восстанавливают из collected_traffic_source первого события сессии.
SELECT
session_traffic_source_last_click.manual_campaign.source AS source,
session_traffic_source_last_click.manual_campaign.medium AS medium,
COUNT(DISTINCT CONCAT(user_pseudo_id, CAST(
(SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id')
AS STRING))) AS sessions
FROM `my-project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20261001' AND '20261007'
GROUP BY source, medium
ORDER BY sessions DESC;
Пример: воронка покупки
Простая «открытая» воронка — сколько пользователей совершили каждый шаг за период:
SELECT
COUNT(DISTINCT IF(event_name = 'view_item', user_pseudo_id, NULL)) AS view_item,
COUNT(DISTINCT IF(event_name = 'add_to_cart', user_pseudo_id, NULL)) AS add_to_cart,
COUNT(DISTINCT IF(event_name = 'begin_checkout', user_pseudo_id, NULL)) AS begin_checkout,
COUNT(DISTINCT IF(event_name = 'purchase', user_pseudo_id, NULL)) AS purchase
FROM `my-project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20261001' AND '20261031';
Если важен порядок шагов, сравнивайте event_timestamp каждого шага внутри пользователя или сессии.
Как контролировать стоимость
В модели on-demand BigQuery берёт плату за объём просканированных данных, а не за число строк в результате. Правила:
- Всегда фильтруйте
_TABLE_SUFFIX— без него запрос читает всю историю. - Не пишите
SELECT *: BigQuery колоночный, платите только за выбранные столбцы. - Смотрите оценку объёма в редакторе до запуска.
- Задайте лимит максимально оплачиваемых байт для запросов и бюджет с оповещениями в Cloud Billing.
- Для дашбордов создавайте агрегированные таблицы по расписанию, а не гоняйте BI по сырым событиям.
Почему цифры не совпадают с интерфейсом GA4
Расхождения нормальны: в интерфейсе применяются пороги данных, моделирование и приближённый подсчёт уникальных значений, а в экспорте их нет. Также экспорт не содержит смоделированных данных Consent Mode. Сравнивайте тренды, а не точные значения.