Pular para o conteúdo principal

Remarketing — Sistema first-party

A plataforma Cactus tem um sistema first-party de remarketing baseado em UUID estável + audience tags do funil. Esta página explica o que é, como funciona, como ativar pra brand nova e quais são as opções futuras de granularidade.

O que é

Uma identidade first-party persistente (UUID v4) salva em cookie próprio do domínio da brand (rmk7k, rmkbpb, rmkst77, etc). Funciona como external_id pra:

  • Meta Conversions API (CAPI) — server-side
  • Google Enhanced Conversions — server-side
  • TikTok Events API — server-side
  • GTM custom tags — qualquer tag pode ler window.__rmk.id
  • dataLayer eventsrmk_ready, rmk_audience_tag

E carrega audience tags do funil (cookie sibling rmk7k_aud):

  • viewed_casino, viewed_live_casino, viewed_game_detail
  • viewed_sports, viewed_promotions
  • clicked_register, registered, abandoned_register
  • viewed_deposit_modal, abandoned_deposit
  • ftd_completed, multi_deposit

cookie_tracking é snapshot de atribuição com janela finita (30 dias default) — ele precisa decair pra que o last-touch continue recente. O cookie de remarketing é ID estável por browser (365 dias sliding) pra cross-session matching.

Mixar os dois num cookie só daria atribuição com TTL de 1 ano (errado) OU remarketing ID com TTL de 30 dias (errado também). Dois conceitos, dois cookies.

Arquitetura

Cookies

rmk7k (UUID estável)

{
"id": "8f2c1a4b-3d3e-4b6c-9c1f-2d6c1f2d6c1f",
"ts": 1731000000000,
"src": "google"
}
AtributoValor
TTL365 dias sliding (renova a cada visita)
Domain.7k.bet.br (cross-subdomain)
SameSiteNone em HTTPS
HttpOnlynão (CAPI/Pixel client-side leem)

rmk7k_aud (audience tags)

{
"tags": {
"viewed_casino": 1731000200000,
"viewed_sports": 1731000400000,
"clicked_register": 1731000600000,
"ftd_completed": 1731002000000
},
"updated": 1731002000000
}
AtributoValor
TTL90 dias sliding
Cap40 tags totais (eviction de oldest quando estoura)
Categoria LGPDOutros / marketing

Tags são set-once — re-tagging não atualiza timestamp (evita cookie churn).

Audience tags ativos

Source of truth: lista canônica em Catálogo de eventos. Esta seção é uma cópia resumida — quando divergir, o catálogo vence.

Tags emitidas automaticamente via pushMetricEvent (que delega pra matriz em app/analytics/destinations.ts → canal audience_cookie):

Path-based (via useLocation())

TagDisparada quando user entra em
viewed_casinoqualquer rota sob casino (lobby, categoria, providers list/detail)
viewed_live_casinocasino.live (ex: /cassino/ao-vivo)
viewed_game_detailcasino.play (ex: /cassino/jogar/playtech/abc)
viewed_sportsqualquer rota sob sports (ex: /esportes/futebol/brasil)
viewed_promotionsqualquer rota sob promotions

Brand-aware via Route Registry — funciona automaticamente em cada brand independente do path (/cassino, /casino, /games, etc) graças ao isRouteActive() do ~/utils/routes.

TagDisparada quando
clicked_registeropenAuthModal("register")
registeredmodal de register fecha + isAuthenticated === true
abandoned_registermodal de register fecha + isAuthenticated === false
viewed_deposit_modalopenPaymentModal("deposit")
abandoned_depositmodal de deposit fecha (sempre — set-once)

FTD-based (via useAnalytics)

TagDisparada quando
ftd_completedtrackDepositConfirmed({ isFirstDeposit: true })
multi_deposittrackDepositConfirmed({ isFirstDeposit: false })

abandoned_deposit + ftd_completed podem coexistir no mesmo user — analytics consumer decide como pesar (tipicamente ftd_completed suprime audiences que incluem abandoned_deposit).

MVP novo (Etapa A do brainstorm — adicionado em 2026-05)

TagDisparada quando
played_democlique no botão "Demo" no GameIframe (intent forte de "cadastre e ganhe")
started_registeruser digitou email/document no RegisterModal (engajamento real, mais forte que clicked_register)
viewed_app_install_bannerbanner PWA/APK aparece na tela (surface: footer/topbar/sidebar/floating)
scrolled_to_payment_sealsviewport hit nos seals do footer após scroll (sinal de avaliação de credibilidade)

Surfaces de exposição

1. window.__rmk (script custom global)

window.__rmk = {
id: "8f2c1a4b-...",
ts: 1731000000000,
src: "google", // optional
tags: ["viewed_casino", "ftd_completed"],
cookieName: "rmk7k"
}

Qualquer script (parceiro CRM, Hotjar dashboard, etc) lê via window.__rmk?.id.

2. dataLayer events (GTM)

dataLayer.push({
event: "rmk_ready",
external_id: "8f2c1a4b-...",
rmk_first_seen: 1731000000000,
rmk_first_source: "google",
rmk_tags: ["viewed_casino"],
rmk_cookie_name: "rmk7k"
});

dataLayer.push({
event: "rmk_audience_tag",
external_id: "8f2c1a4b-...",
rmk_tag: "ftd_completed",
rmk_audience_count: 5
});

GTM dispara qualquer tag (Meta CAPI, Google Ads Enhanced Conversions, TikTok Events API) usando external_id como identidade primária.

document.cookie mostra rmk7k={JSON} — lido por scripts que não confiam no window.__rmk.

4. Hook React

const { externalId, audienceTags, hasTag, addTag } = useRemarketingId();

if (hasTag("ftd_completed")) {
// mostrar oferta de re-deposit
}

Como ativar pra brand nova

Único arquivo necessário em overrides/<brand>/app/config/features/remarketing.ts:

import type { RemarketingFeatureFlags } from "~/types/remarketing-features";

export const remarketingFeaturesConfig: RemarketingFeatureFlags = {
enabled: true,
cookieName: "rmk7k", // único, brand-neutro
cookieDomain: ".7k.bet.br", // cross-subdomain
pushToDataLayer: true,
exposeOnWindow: true,
sendToBff: false, // inerte hoje — nenhum código lê este flag
};

Pronto. Path tags funcionam automaticamente porque dependem só do route registry brand-aware. Mesma config funciona pra qualquer brand — só muda cookieName e cookieDomain.

Naming convention

O padrão em uso nas 13 brands é rmk<abreviação-da-brand>, minúsculo e sem separador — rmk7k, rmkbpb, rmkcl7k, rmkst77, rmkphst77. Mantenha curto: o nome viaja em todo Set-Cookie.

Proibido: nomes contendo cactus ou bluetec. A validação é em runtime — FORBIDDEN_PLATFORM_NAMES = /cactus|bluetec/i em app/utils/remarketing-id.ts rejeita o nome e desativa o flag.

Brands ativas hoje

Todas as 13 brands do base têm enabled: true, cada uma com cookie e domínio próprios. O default do base é { enabled: false, cookieName: "" } — não há brand nessa situação hoje.

BrandcookieNamecookieDomain
7k-bet-brrmk7k.7k.bet.br
betpontobet-bet-brrmkbpb.betpontobet.bet.br
casateste-comrmkcasateste.casateste.com
cl-bet7k-comrmkcl7k.cl.bet7k.com
donald-bet-brrmkdnb.donald.bet.br
fi-7k-betrmkfi7k.fi.7k.bet
ng-7k-betrmkng7k.ng.7k.bet
pb-betrmkpb.pb.bet
ph-state77-comrmkphst77.ph.state77.com
pt-state77-comrmkptst77.pt.state77.com
rj-betrmkrj.rj.bet
state77-comrmkst77.state77.com
x2b-betrmkx2b.x2b.bet

Todas com pushToDataLayer: true, exposeOnWindow: true e sendToBff: false.

Fonte viva: grep -rn "cookieName\|cookieDomain" overrides/*/app/config/features/remarketing.ts.

Nos exemplos desta página o cookie usado é o do 7k-bet-br (rmk7k / rmk7k_aud); substitua pelo cookieName da sua brand.

Granularidade — opções

Atual: viewed_game_detail agregado

Hoje o cookie marca uma única tag viewed_game_detail quando user abre qualquer game. Audiência: "já abriu algum jogo".

Opção A — viewed_game_<slug> granular

Cardinalidade altíssima (2.000-5.000 games por brand). Cookie eviction tira funnel tags (ftd_completed, etc) pra dar lugar a games. Não recomendado.

Opção B — viewed_provider_<slug> (provider-level)

~30 providers por brand. Cookie controlado. Audience útil ("Pragmatic fans"). Sweet spot.

Opção C — Top-N whitelist

Marketing curate 5-15 games signature (Fortune Tiger, Aviator). Só esses geram tag. Cookie pequeno + high-signal.

Opção D — dataLayer-only

Cada game view dispara dataLayer.push({ event: "rmk_game_view", game_slug, provider_slug }). GTM forwarda pra Meta CAPI / Google Ads / TikTok. Audience criada no painel do ad platform sem precisar enumerar slugs no front. Padrão de mercado pra dynamic remarketing.

Status: nenhuma das opções A-D implementada hoje. Decisão depende de use case real do marketing — discutido em [issue futura].

CAPI / Enhanced Conversions — Roadmap

A intenção é que sendToBff: true ligue o forwarding do external_id no payload de signup/deposit, pro BFF encaminhar server-side.

:::caution sendToBff é inerte hoje — inclusive no front O campo existe no tipo (RemarketingFeatureFlags.sendToBff) e as 13 brands o declaram como false, mas nenhum código o lê. O helper que consultaria a matriz (shouldForwardToBffCapi()) não tem consumidor, e nenhum payload de signup/deposit inclui external_id. Ligar o flag hoje não muda nada. :::

Pra sair do papel, falta em três frentes:

  1. Front: consumir shouldForwardToBffCapi() na montagem dos payloads de signup/deposit e anexar external_id quando sendToBff estiver ligado.
  2. BFF: aceitar o campo external_id no body e chamar Meta CAPI / Google Enhanced Conversions / TikTok Events API server-side, com PII hasheada + external_id.
  3. Plataformas de ads: configurar Dataset / Pixel / Token.

Enquanto isso, o remarketing funciona client-side: window.__rmk + eventos de dataLayer, com o GTM encaminhando pras plataformas. Ver Contract BFF.

Como debuggar

DevTools → Application → Cookies → procura por rmk7k (ou nome da brand) e rmk7k_aud.

window.__rmk

Console:

window.__rmk
// → { id: "...", ts: ..., tags: [...], ... }

dataLayer events

window.dataLayer.filter(e => e.event === "rmk_ready" || e.event === "rmk_audience_tag")

Forçar regeneração

DevTools → Cookies → delete rmk7k. Reload. Server gera novo UUID. Cookie reaparece com id diferente.

Anti-patterns

  1. Persistir viewed_game_<slug> granular sem cap-prioritário. Eviction tira ftd_completed da audiência — mata o sinal mais valioso.
  2. Confiar no external_id server-side. sendToBff: true hoje não tem efeito nenhum — nem o front monta o payload, nem o BFF recebe. Use window.__rmk / dataLayer.
  3. Renomear cookie em produção sem migration one-shot. Existing users perdem ID estável.
  4. Setar cookieName: "rmkcactus". Vaza plataforma white-label. Front loga warning e desativa.
  5. Não setar cookieDomain em brand com subdomain (m.brand.com). Cookie fica host-only — m.brand.com e www.brand.com viram users diferentes.