Guia de Data Layer (Camada de Dados) para Devs: O Que o Marketing Precisa de Você
Contrato mínimo de dataLayer para GA4/GTM: snake_case, tipagem, ecommerce null em SPA e purchase sem duplicar — sem DOM scraping.
Contexto
Marketing pede: "coloca a tag no botão de comprar". Engenharia responde com um listener no DOM. No próximo redesign, a classe muda, o botão vira componente e o funil some do GA4.
O Data Layer existe para acabar com essa conversa. É o contrato entre o app e as tags: a aplicação publica eventos de negócio (add_to_cart, purchase); o GTM escuta e dispara GA4, Ads, Meta. Sem raspar HTML. Sem depender de CSS.
Enhanced Measurement cobre pageview, scroll e outbound click. Não cobre ecommerce. Catálogo, carrinho e checkout exigem instrumentação manual — e é aí que o time de eng entra.
Problema
Sinais de que o contrato está quebrado:
| Sintoma | Causa típica |
|---|---|
| Receita GA4 longe do OMS | price/value como string ("49,90") ou purchase duplicado |
| Funil ecommerce vazio | Evento addToCart / Add_To_Cart em vez de add_to_cart |
| Produto "fantasma" no relatório | SPA sem limpar ecommerce entre pushes |
| Conversão sem origem | Tag dispara antes de session_start / consentimento |
Auditorias de mercado apontam arquiteturas de data layer incompletas na maioria dos e-commerces — e falhas de receita são o sintoma mais caro. O objetivo deste guia é o mínimo viável que marketing precisa de você, em linguagem de engenharia.
O que é o Data Layer
window.dataLayer é um array global. Cada push enfileira um objeto. O Tag Manager lê essa fila e reage a event e parâmetros.
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'generate_lead',
form_id: 'contato-home'
});
Analogia útil: o app cozinha; o dataLayer é a comanda padronizada. O GTM é o auditor que lê a comanda — não entra na cozinha para adivinhar o prato pelo cheiro (DOM scraping).
O que o marketing precisa de você
Tradução direta de pedido de negócio → entregável técnico:
| Necessidade do marketing | Requisito técnico | Entregável |
|---|---|---|
| Receita confiável | transaction_id único + value/currency numéricos |
Purchase com dedupe (sessionStorage) |
| Funil completo | Eventos padrão do esquema GA4 | view_item → add_to_cart → begin_checkout → purchase |
| SPA sem lixo | Limpar estado ecommerce | dataLayer.push({ ecommerce: null }) antes de cada evento |
| Conformidade LGPD | Consent default antes do GTM | Snippet Consent Mode v2 no topo do <head> |
| Estabilidade no deploy | Payload validado | Teste E2E que inspeciona window.dataLayer |
Se o pedido chegar como "trackeia o clique do CTA azul", devolve o contrato: nome do evento + parâmetros tipados + onde dispara. Sem isso, você está aceitando dívida de analytics.
Nomenclatura e tipagem
O GA4 e o GTM são case-sensitive. add_to_cart ≠ addToCart. Variáveis monetárias são Number, quantidade é Integer — sem símbolo de moeda, sem vírgula de milhar.
| Correto | Errado | Efeito |
|---|---|---|
add_to_cart |
addToCart / Add_To_Cart |
Trigger GTM não dispara; evento vira “custom” fora do funil |
price: 49.90 |
price: "49,90 R$" |
Value zero ou descartado |
quantity: 1 |
quantity: "1" |
Agregações quebram |
snake_case |
kebab-case / espaços | Chaves ilegíveis no GTM e no BigQuery |
Eventos ecommerce essenciais
| Evento GA4 | Quando disparar | Obrigatório no evento |
|---|---|---|
view_item_list |
Lista/grade de produtos | items |
select_item |
Clique no produto da lista | items |
view_item |
Página de detalhe | items |
add_to_cart |
Adicionou ao carrinho | items |
begin_checkout |
Início do checkout | items |
add_shipping_info |
Frete escolhido | items |
add_payment_info |
Pagamento escolhido | items |
purchase |
Pedido confirmado | transaction_id, value, currency, items |
Cada item no array items (até 200) precisa, no mínimo, de item_id ou item_name, mais price e quantity quando houver valor. Use também item_brand, item_category, item_variant se marketing for segmentar catálogo.
Para validar se a taxonomia da conta está íntegra depois do push:
Como auditar a qualidade dos seus dados no GA4 em 5 passos
SPA e estado
Em React, Next, Vue ou Angular, a navegação não recarrega o documento. O dataLayer persiste na sessão. Se você empilhar ecommerce sem limpar, o GTM mistura itens do evento anterior com o atual.
Padrão obrigatório:
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push({
event: 'add_to_cart',
ecommerce: {
currency: 'BRL',
value: 59.98,
items: [{
item_id: 'PROD-771',
item_name: 'Tênis Corrida',
price: 29.99,
quantity: 2
}]
}
});
Faça o ecommerce: null imediatamente antes de cada evento de comércio — não só no purchase.
Purchase sem duplicar
Refresh na thank-you page ou reabertura do link de confirmação dispara purchase de novo. O GA4 deduplica por transaction_id, mas a aplicação ainda deve bloquear reemissão:
- Gere
transaction_idúnico no backend. - Envie no payload junto com
value(Number) ecurrency(BRL). - Grave flag em
sessionStorageapós o primeiro push bem-sucedido; se a flag existir, não empurre de novo.
Quando GA4 e faturamento ainda divergirem depois disso, o problema pode ser gap estrutural (consentimento, blockers) — não só tipagem:
Por que seu GA4 e seu CRM Nunca Batem? (E Como Resolver)
Meta de reconciliação saudável: receita GA4 entre 90% e 110% do OMS no mesmo período (após latência de 24–48h).
Consentimento e PII
Consent Mode v2 precisa declarar os quatro sinais antes do container GTM carregar. Sem isso, tags disparam com estado indefinido e o dataLayer “bonito” não salva a medição.
Detalhe da ordem e dos sinais:
Consent Mode v2 sem quebrar métricas no GA4
Nunca coloque e-mail ou telefone em texto claro no dataLayer. Para Enhanced Conversions, normalize e hasheie no servidor — e lembre: hash sozinho não vira anonimato mágico.
Guia de anonimização e privacidade em analytics
Checklist de QA
| # | Verificação | Feito quando... |
|---|---|---|
| 1 | Nomenclatura | Todos os eventos ecommerce em snake_case do esquema GA4 |
| 2 | Tipagem | price/value Number; quantity Integer; sem máscara de moeda |
| 3 | SPA | ecommerce: null antes de cada push ecommerce |
| 4 | Purchase | transaction_id único + bloqueio de reemissão |
| 5 | Consent | Default no <head> antes do GTM |
| 6 | CI mínimo | Teste E2E lê window.dataLayer após clique crítico |
Exemplo mínimo de asserção (Playwright): após clicar em “Adicionar ao carrinho”, page.evaluate(() => window.dataLayer) e expect(...).toMatchObject({ event: 'add_to_cart', ecommerce: { currency: 'BRL', ... } }). Não precisa de suíte gigante no dia 1 — precisa de um teste no caminho que gera receita.
Próximo passo
Data Layer não é “mais um script de marketing”. É interface pública do seu frontend para o restante do stack de medição. Se o contrato estiver claro — nomes, tipos, limpeza de estado, purchase único —, o GTM deixa de ser gambiarra e vira configuração.
Use a tabela marketing ↔ engenharia como especificação de PR. Se o site ainda depende de clique em CSS para gerar conversão, o movimento seguinte é desenhar a arquitetura de eventos App/Web: mapa de eventos, payloads e ownership entre produto e eng — antes do próximo redesign quebrar o funil de novo.