Anti-patterns
Lista consolidada do que NÃO fazer no setup de marketing. Cada item bate com erro real visto em produção da Cactus ou de plataformas similares.
Atribuição
1. UTM em link interno
❌ Header tem <a href="/?utm_source=header_btn">Início</a>.
Por quê é ruim: sobrescreve atribuição real do user. Canal "header_btn" infla até virar #1 em todos os relatórios; canais reais (Meta, Google) somem.
✅ Use data-* attributes pra rastrear UI ou eventos GTM custom (select_item).
2. Esquecer set completo de UTMs
❌ Link de campanha só com utm_campaign=cyber-monday.
Por quê é ruim: last-touch herda utm_source da campanha anterior. User que veio do Google primeiro e clicou em link de e-mail depois conta como conversão do Google (porque source não foi sobrescrito).
✅ Sempre passe os 4 canonical (utm_source, utm_campaign, utm_medium, utm_content) em todo link.
3. Mudar pra first-touch sem alinhar com BI
❌ Decidir unilateralmente "vamos preservar primeiro touch".
Por quê é ruim: todos os dashboards estão calibrados em last-touch. Mudança silenciosa quebra histórico de comparação.
✅ Discussão coordenada com BI antes. Se mudar, é deliberado e documentado.
Pixels e plataformas
4. Pixel duplicado (GTM tag + SDK próprio)
❌ Adicionar Meta Pixel via tag GTM custom e o front já carrega via useAnalytics.
Por quê é ruim: cada evento dispara 2x. Audiences inflam, conversion duplica, ROAS quebra.
✅ Olhe app/utils/metrics/* antes de adicionar pixel via GTM.
5. Tag GTM disparando Purchase em deposit_initiated
❌ Custom Event pix_generated → tag Purchase Meta.
Por quê é ruim: depósito gerado mas não confirmado dispara Purchase. Inflate brutal.
✅ Tag Purchase só no pix_confirmado_ftd (BFF confirmou).
6. Não passar transactionId na tag de conversion
❌ Conversion tag Google Ads sem transactionId.
Por quê é ruim: refresh da página dispara nova conversão. Mesma compra conta 2-3x.
✅ Sempre passa transactionId: {{DLV - transactionId}} — Google Ads deduplica por isso.
7. Mudar gtmId/pixelId em prod sem testar
❌ Update direto no backoffice → "deploy" instant.
Por quê é ruim: tag mal configurada dispara evento errado. Polui dashboards. Difícil de reverter.
✅ Testa no GTM Preview Mode primeiro. Validar com Pixel Helper/Tag Assistant.
Privacy / Consent
8. Ativar cookieConsentCosmeticOnly sem aprovação compliance
❌ Setar cookieConsentCosmeticOnly: true numa brand BR sem aprovação documentada.
Por quê é ruim: risco regulatório alto. ANPD pode autuar.
✅ Aprovação conjunta marketing + compliance + DPO documentada antes.
9. Default GCM granted
❌ Subir GCM defaults com analytics_storage: 'granted' (sem user consent).
Por quê é ruim: quebra GCM v2 compliance. Google rejeita o setup.
✅ Defaults sempre denied (exceto security_storage: granted). Update após user aceitar.
10. Não testar fluxo "Recusar"
❌ Lançar tag GTM nova sem testar com user que recusou consent.
Por quê é ruim: tag pode estar dependendo de cookie que GCM bloqueou. Falha silenciosa em ~30% dos users (taxa típica de recusa).
✅ Testa explícitamente com cookies_consent setado pra "recusar tudo".
Cookies
11. Cookie name com cactus ou bluetec
❌ cookieName: "rmkcactus" no remarketing.
Por quê é ruim: vaza plataforma white-label pro cliente final. Front rejeita em runtime e desativa o flag.
✅ rmk<brand> brand-aware (rmkvera, rmk7k, rmkst77).
12. Tornar cookie_tracking HttpOnly
❌ Setar HttpOnly: true no cookie de tracking.
Por quê é ruim: client não consegue ler. Submit de signup/deposit vai sem UTMs.
✅ Mantém HttpOnly: false. Atribuição precisa client + server consumir.
13. Sanitizar lastclick (Clever)
❌ Aplicar mesmo blocklist do cookie_tracking no lastclick.
Por quê é ruim: Clever pode usar formatos com strings que o blocklist mangia (document, appendChild, {macro}). Sanitização mutila IDs e quebra atribuição.
✅ lastclick é opaco — sem sanitização. Mesmo padrão do legado Vue.
14. Mudar SameSite do lastclick
❌ SameSite: "Lax" no lastclick.
Por quê é ruim: Clever entrega tráfego cross-site (iframe/popup/pixel chain). Browsers rejeitam Set-Cookie cross-site sem SameSite=None; Secure. Quebra ~99% do tráfego Clever.
✅ SameSite: "None"; Secure: true — confirmado com time Clever em maio/2026.
15. Renomear cookie em produção sem migration
❌ Mudar cookie_tracking pra tracking_cookie sem migration one-shot.
Por quê é ruim: existing users perdem atribuição. Cookie velho fica órfão.
✅ Migration: lê cookie legado → grava no novo nome → deleta legado. Padrão em app/utils/consent.ts:LEGACY_CONSENT_COOKIE_NAMES.
16. TTL absurdo
❌ trackingCookieTtlHours: 99999 (~11 anos).
Por quê é ruim: atribuição vaza entre campanhas. User que clicou em ad de 2 anos atrás conta como conversão do canal de 2 anos atrás.
✅ Janelas razoáveis: 24h-30 dias. Default 7 dias é equilibrado.
Headers / Payload
17. Adicionar UTM em header HTTP
❌ Custom header X-UTM-Source em toda request.
Por quê é ruim: headers têm limite de tamanho (~8KB). UTMs custom (utm_oferta, utm_term, etc) estouram. Body suporta.
✅ UTMs viajam só no body de signup/deposit.
18. Adicionar src ao deposit
❌ Deposit payload com src: "fb_ads".
Por quê é ruim: quebra paridade com legado Vue. BFF valida payload e pode rejeitar.
✅ src só em signup. Deposit é subset. (Lista exata em UTMs)
19. Adicionar affiliation_code/subid/app_source ao deposit
❌ Deposit payload com affiliation_code.
Por quê é ruim: mesma razão — paridade legado. Atribuição de depósito é resolvida pelo BFF via user.recommended_by, não pelo cookie.
✅ Deposit subset. Signup tem todos esses campos.
Modo App / TWA
20. Disparar pixel client em modo app
❌ Não desativar Meta Pixel quando ?app=true.
Por quê é ruim: apps inflam métricas web. Atribuição mobile é S2S via AppsFlyer.
✅ shouldLoadTrackers = !isAppMode && !isBot. Honra esse gate.
21. Mover AppsFlyer S2S pra dentro do gate de trackers
❌ if (!shouldLoadTrackers) return; appsFlyer.sendFTD(...).
Por quê é ruim: scopes inversos. App: gate=false (early return) → S2S nunca roda. Web: appsFlyer.ready=false → nem chama. Resultado: S2S nunca dispara. Bug histórico (maio/2026).
✅ AppsFlyer antes do gate. SDK decide internamente se está em app.
22. Modificar assetlinks.json
❌ Update direto em overrides/<brand>/public/.well-known/assetlinks.json.
Por quê é ruim: chaves criptográficas atreladas ao APK no Play Store. Typo quebra TWA em prod.
✅ Coordena com time mobile. Atualiza só quando há fingerprint novo do APK.
Debug / Prod
23. Tentar ?EnableDebug=1 em prod
❌ Esperar que toggle visual de debug funcione em prod.
Por quê é ruim: foi removido em maio/2026 por vazamento de cookies sensíveis (especificamente cf-worker-key em response).
✅ Use wrangler tail ou Cloudflare Dashboard pra logs server-side.
24. Reportar bug sem X-LOG-INFO
❌ "Tá quebrado, dá uma olhada".
Por quê é ruim: dev sem X-LOG-INFO não consegue correlacionar request específica do user a logs server-side.
✅ Sempre incluir X-LOG-INFO da request afetada (Network tab) ao reportar.
Audiência / Remarketing
25. Persistir viewed_game_<slug> granular sem cap-prioritário
❌ Marcar tag por jogo individual no rmkvera_aud sem proteger funnel tags.
Por quê é ruim: cassino tem 2k-5k games. Cap de 40 tags hit rapidamente. Eviction tira ftd_completed (super valioso) pra dar lugar a viewed_game_random.
✅ Granularidade provider-level (viewed_provider_pgsoft) ou dataLayer-only (sem persistir cookie). Detalhes em Remarketing.
26. Confiar no external_id antes de BFF aceitar
❌ Setar sendToBff: true no remarketing config sem coordenar com back.
Por quê é ruim: front envia external_id no payload, BFF ignora (não mapeou o campo). Tracking morto.
✅ Sempre alinha com BFF antes. Liga sendToBff: true só após backend support confirmado.
Geral
27. Pedir captura de campo novo só no front
❌ "Adiciona um tcclid no cookie, marketing pediu."
Por quê é ruim: front captura, mas BFF não processa. Dashboard de BI nunca vê o campo. Tracking morto.
✅ Sempre alinha com BFF primeiro. Front + back juntos.
28. Configurar feature flag em app/config/features/features.ts (default base) sem propagar pros overrides
❌ Adicionar remarketingId: { enabled: true } no default base e esquecer das brands com override.
Por quê é ruim: brand override é file-replacement (não deep-merge). Brands com override ficam com undefined, não herdam o default.
✅ Adicionar campo no tipo + default + propagar pra todos overrides existentes (ou documentar explicitamente que override é opt-in).
29. Esquecer que cada brand tem analytics config diferente
❌ Testar campanha em vera, deduzir que vai funcionar em 7k.
Por quê é ruim: override de brand pode mudar pixel ID, GTM ID, Kwai, Webtrends, etc. Funcionar em uma ≠ funcionar em outra.
✅ Testa explicitamente em cada brand alvo.
30. Carregar pixels eagerly (sem scheduleThirdParty)
❌ Tirar pixel do scheduleThirdParty "pra carregar mais rápido".
Por quê é ruim: quebra LCP. Lighthouse score cai. PageSpeed Insights vermelho.
✅ Pixels low-priority sempre via scheduleThirdParty. Honra LCP + 1ª interação + 25s pra Lighthouse bypass.