GA4 + BigQuery: primeiros SQLs úteis para marketing

Export GA4 ligado no BigQuery sem SQL útil é custo de storage com zero retorno analítico. Os primeiros SQLs que importam para marketing não são joins exóticos — são unnest de parâmetros, funis de conversão, receita confiável e atribuição de campanha reproduzível. Com queries base documentadas, o time deixa de depender de explorations amostradas e passa a responder perguntas que a UI do GA4 não entrega ou entrega distorcido.
Como entender a estrutura events_* no BigQuery?
Tabelas diárias `events_YYYYMMDD` (e intraday) com colunas aninhadas: event_params (key/value), user_properties, items, ecommerce, device, geo. Cada linha é um evento. user_pseudo_id identifica dispositivo; user_id quando logado. event_timestamp em microssegundos UTC.
Primeiro passo: SELECT count(*), event_name FROM events_* GROUP BY 2 ORDER BY 1 DESC — mapa de volume por evento. Depois valide parâmetros críticos com unnest. Sem inventário de eventos, SQL vira tentativa e erro caro.
Como extrair parâmetros com UNNEST?
Padrão: `(SELECT value.string_value FROM UNNEST(event_params) WHERE key = ‘campaign’) AS campaign`. Para doubles/int: value.double_value, value.int_value. Múltiplos parâmetros: subselects ou UNNEST + PIVOT manual com MAX IF.
Crie views staging `stg_ga4_events` que flattenam parâmetros frequentes (page_location, campaign, source, medium, transaction_id, value). Marketing consulta view — não repete unnest em todo relatório.
- View staging com parâmetros flattenados
- Tipagem correta string vs double vs int
- Timezone de negócio aplicado em camada mart
- Filtro bot/internal traffic replicado do GA4
- Documentação de chaves event_params por evento
Quais SQLs de funil marketing usar primeiro?
Funil session-based: ordene eventos por user_pseudo_id + session, use window functions ou lógica de “primeiro evento A depois B na mesma sessão”. GA4 export não traz session_id pronto em todas análises — muitas vezes derive de ga_session_id param ou modelagem própria.
Query útil: taxa de sessões com view_item → add_to_cart → begin_checkout → purchase por dia e canal. Compare com UI; divergência pequena é ok, grande indica bug de evento ou definição de sessão.
| Pergunta | Eventos | Granularidade | Nota |
|---|---|---|---|
| CVR checkout | begin_checkout → purchase | Sessão/dia | Validar transaction_id único |
| Receita por canal | purchase + traffic source | Dia | Usar first user source ou session |
| Performance criativo | click + purchase join UTM | Campanha | Cuidado com cardinality |
| Abandono carrinho | add_to_cart sem purchase | Usuário 7d | Janela explícita |
| Landing → lead | page_view + generate_lead | Landing group | Bucketizar URL |
Como calcular receita e evitar double count?
Receita: SUM ecommerce.purchase_revenue) ou param value em purchase, filtrando event_name = ‘purchase’. Dedup por transaction_id: ROW_NUMBER() PARTITION BY transaction_id ORDER BY event_timestamp = 1.
Inclua refunds se evento refund existir. Alinhe moeda — multi-currency exige taxa de câmbio em mart financeiro. Compare total BQ vs ERP semanalmente; SQL correto com dados sujos ainda mente.
Atribuição básica: first touch vs last non-direct?
Use traffic_source fields (source, medium, campaign) no evento ou collected_traffic_source. First user: campos `*_first_user_*`. Last non-direct exige lógica: ignore (direct)/(none) ao pegar último hit antes da conversão — implementável em SQL com window functions por user_pseudo_id.
Documente modelo no README do dataset. Stakeholders frequentemente pedem “o GA4 default” — reproduza explicitamente ou explique diferença. Não misture modelos no mesmo dashboard.
Performance e custo: boas práticas de query?
Sempre filtre `_TABLE_SUFFIX` ou partition date. Evite SELECT * em tabelas brutas. Agende queries pesadas; materialize marts diários (sessions, purchases, channel_daily). Use clustering/partitioning em tabelas derivadas.
Limite scans com views aprovadas para self-service. Analista livre no raw event é receita de fatura BigQuery surpresa.
- Partition filter obrigatório em queries ad hoc
- Marts diários para dashboards Looker/Sheets
- Scheduled queries para refresh automático
- Monitoring de bytes processed por query
- Proibir self-service no events_* raw
Como entregar SQLs que marketing realmente opera?
Pacote mínimo: (1) view eventos flatten; (2) mart daily_revenue_by_channel; (3) mart funnel_checkout; (4) query template de campanha com filtros parametrizados. Conecte Looker/Sheets/Data Studio com essas views — não com SQL de 200 linhas copiado.
Treine marketing a usar filtros de data e canal, não a editar unnest. Documentação em português com screenshot do resultado esperado. SQL que só o engenheiro roda não é entrega — é dependência.
Checklist prático
- Export GA4→BQ validado com contagem eventos vs UI
- View staging com parâmetros críticos flattenados
- Mart daily revenue com dedup transaction_id
- Funil checkout session-based documentado
- Modelo de atribuição SQL explicitado
- Partition filter e cost monitoring ativos
- Dashboard conectado a marts, não raw events
- Régua semanal BQ vs ERP/financeiro
Erros comuns
- SELECT * em 90 dias de events_* no Looker
- Somar purchase sem dedup transaction_id
- Ignorar timezone UTC vs America/Sao_Paulo
- Unnest diferente em cada dashboard
- Funil sem definir sessão explicitamente
- Entregar SQL sem view/mart reutilizável
Export GA4 ligado mas ninguém usa?
A DataScroll entrega SQLs e modelos no BigQuery que marketing e dados conseguem operar no dia a dia.