Menuabrir

Este módulo depende de

2
  • marketingPlugin dentro do Hub framework de marketing
  • attributionsync_attribution_campaigns cria campaigns por novo source GA4

Módulos que dependem deste

0

Nenhum módulo depende deste hoje.

Analytics (GA4)

Status: 🟢 Estável (Hub.3 deployado) Code: backend/app/modules/marketing/plugins/ga4 UI: frontend/src/app/(admin)/[slug]/admin/marketing (seção GA4) Última revisão deste doc: 2026-05-13 por Felipe + Claude Dependências fortes: marketing (Hub framework), attribution (campaign bridge), tenant_router


1. Identidade

O que faz (uma frase)

Plugin GA4 do Mandir Hub — observa propriedade Google Analytics 4 do tenant, persiste agregado diário, breakdown por source/medium/campaign e eventos em tabelas L0, e expõe 4 tools pro Conselho consumir sem hitar a API.

Por que existe (negócio)

GA4 é a fonte canônica de tráfego do site. Sem este módulo:

  • Felipe abre painel GA4 toda vez que quer entender quanto tráfego vem do YouTube.
  • Conselho não consegue cruzar tráfego com revenue.

Hub.3 traz o histórico no DB + tools no Conselho. CEO pergunta "quanto tráfego do Instagram converteu?" → Conselheiro chama read_ga4_top_sources + read_ga4_conversion_funnel → resposta com números.

Status atual

  • Hub.3 deployado em 2026-05-13 (commit dentro da sessão hub234, alembic 0103).
  • Service Account ativo: mais-consciente-analytics no projeto GCP mais-consciente-mandir.

2. Cases de uso reais

Case 1: CEO pergunta "como está GA4 últimos 30 dias?"

Fluxo: CEO chama read_ga4_traffic_summary(window_days=30) + read_ga4_top_sources + read_ga4_event_breakdown em paralelo → cross_module devolve dados de ga4_* → CEO sintetiza: "840 sessões, 757 users, 3.2% conversion, top source = direct (35%)".

Case 2: Detecção de queda

Beat task marketing.run_observe(provider=ga4) roda diariamente → se sessions_today < 0.5 × avg_7d → emit anomaly event → intelligence sub-agent anomaly cria intelligence_insight(severity=warning).


3. Oportunidades de negócio

  • Multi-property dashboard: clientes que têm 5 sites separados precisam consolidar GA4 — produto pra agências.
  • GA4 → CRM attribution: match de session_id com CRM contact (depois que GA4 implementar Identity Mapping). Cross-channel attribution premium.
  • Anomaly alerts standalone: queda inesperada → notifica WhatsApp → produto reativo.

Riscos: GA4 Data API tem 24h delay (inevitável). Quota 1MM requests/dia/property — alto pra single-tenant; pode ser problema multi-tenant 100+.


4. Arquitetura interna

Arquivos

ArquivoPropósito
__init__.pyImports + register_plugin(GA4Plugin())
plugin.pyClasse GA4Plugin. Implementa observe() (resto no-op)
client.pyWrapper BetaAnalyticsDataClient (Service Account auth)
models.py4 tabelas L0
sync.pysync_property_snapshot, sync_traffic_summary, sync_top_sources, sync_events
attribution_bridge.pysync_attribution_campaigns cria attribution_campaign(kind=ad_paid, provider=ga4)

Tasks

Sem Celery tasks dedicadas — observe acionado por marketing.run_observe(provider=ga4).


5. Tabelas (4)

ga4_property

Snapshot da propriedade.

Coluna chaveNotas
tenant_id
property_idGA4 numeric ID
measurement_idG-XXXXX (web stream)
labelHumano-readable

ga4_metric_daily

Agregado diário.

Coluna chaveNotas
property_id / dateGranularity por dia
sessions / active_users / new_users / page_views / conversionsINT
total_revenueDECIMAL
engagement_rate / avg_session_duration_sFLOAT

ga4_source_daily

Breakdown source/medium/campaign × date.

Coluna chaveNotas
property_id / date
source / medium / campaign / channel_groupDimensions
sessions / active_users / conversions / revenueMétricas

ga4_event_daily

Eventos por dia × property.

Coluna chaveNotas
event_name / event_count / event_value

Relacionamentos cross-módulo

DireçãoOutro móduloComo
↘ Escreveattributionsync_attribution_campaigns cria attribution_campaign por novo campaign GA4
↘ Toolscouncil4 tools: read_ga4_traffic_summary, read_ga4_top_sources, read_ga4_conversion_funnel, read_ga4_event_breakdown

6. API / Endpoints

GA4 não tem endpoints REST direto — observa via marketing.run_observe. UI consome via:

MétodoRotaO que faz
GET/api/marketing/ga4/summarySessions, users, pageviews, revenue, engagement_rate (window_days)
GET/api/marketing/ga4/sourcesBreakdown source/medium/campaign
GET/api/marketing/ga4/eventsEvent names com counts

7. Configuração

Credencial

CampoValor
providerga4
account_external_idproperty_id (ex: 290167437)
auth_kindservice_account
secret_envelope{service_account: {...JSON parseado...}}
metadata{measurement_id: "G-XXXXX", service_account_email: "..."}
scope["https://www.googleapis.com/auth/analytics.readonly"]

Service Account JSON setup

  1. GCP Console → IAM → Service Accounts → criar mais-consciente-analytics.
  2. Download JSON key.
  3. GA4 Console → Admin → Property Access Management → adicionar email da SA com role Viewer.
  4. UI Mandir /admin/marketing/credentials → paste JSON → backend valida service_account field e cifra envelope.

Importante: Service Account JSON ≠ OAuth Client JSON. Memória [[oauth-client-vs-service-account-json]]:

  • SA tem "type":"service_account" no topo.
  • OAuth Client tem {"installed":{...}}.
  • Validar no paste antes de mandar pro backend.

8. Operações

Como conectar property nova

  1. Criar SA no GCP (uma vez por projeto).
  2. Adicionar SA email como Viewer no GA4.
  3. UI Mandir → "Conectar GA4" → paste JSON + property_id + measurement_id.
  4. Trigger sync inicial.

Troubleshooting

Sintoma: Sync retorna permission_denied

Causa: SA email não foi adicionada na property. Fix: GA4 Console → Property Access Management → adicionar.

Sintoma: (not set) em dimensões

Causa: GA4 não conseguiu inferir source/medium (tráfego direto sem UTM). Tratamento: (not set) → NULL no DB.


9. Métricas + observabilidade

Logger keyQuando emite
marketing.ga4.sync.startObserve iniciou
marketing.ga4.sync.doneOK + rows_ingested
marketing.ga4.sync.failedErro
marketing.ga4.attribution_bridge.createdNovo campaign auto-criado

10. Limitações e débitos técnicos

#Item
124h delay nativo — GA4 Data API não dá real-time
2Sem identity mapping cross-CRM — GA4 user_id ≠ crm_contact.id
3Quota 1MM/dia/property — multi-tenant 100+ pode estourar
4(not set) virou NULL — perde info "direto sem UTM" vs "erro"
5partial=True se qualquer step falha
6Sem refresh incremental delta — sempre re-fetch window completo

11. Histórico

  • 2026-05-13 — Hub.3 deployado. Sessão [[sessao-2026-05-13-hub234]].