docs(S9,S10): planos de intenção — captura de novidades na home + pixel Meta na página de campanha

This commit is contained in:
Francisco Solla 2026-08-19 15:54:13 -03:00 committed by fsolla
parent 484ed4a424
commit d8d85de7be
6 changed files with 403 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1,237 @@
<!doctype html>
<html lang="pt-BR">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<title>UI draft — Captura de novidades na home de campanha</title>
</head>
<body class="bg-zinc-950 text-zinc-100 antialiased">
<main class="mx-auto max-w-5xl p-8">
<p class="text-sm text-zinc-400">
Visitante da home de campanha demonstra apoio e deixa o contato para receber comunicações
(e-mail ou grupos de WhatsApp) — CTA do hero leva à seção de captura na própria página.
</p>
<section data-shot="desktop" class="mt-6 overflow-hidden rounded-xl border border-zinc-800">
<div class="bg-zinc-900 px-10 pt-12 pb-8">
<div class="flex gap-8">
<div class="flex-1">
<div class="h-3 w-24 rounded bg-zinc-700"></div>
<div class="mt-4 h-12 w-72 rounded bg-zinc-700"></div>
<div class="mt-2 h-12 w-64 rounded bg-zinc-700"></div>
<div class="mt-5 space-y-2">
<div class="h-2 w-96 rounded bg-zinc-700"></div>
<div class="h-2 w-80 rounded bg-zinc-700"></div>
<div class="h-2 w-88 rounded bg-zinc-700"></div>
</div>
<div class="mt-7 flex gap-3">
<div
class="inline-flex h-11 items-center justify-center rounded-[10px] bg-red-600 px-5 text-sm font-extrabold text-white"
>
Quero apoiar
</div>
<div
class="inline-flex h-11 items-center justify-center rounded-[10px] border-2 border-zinc-300 px-5 text-sm font-extrabold text-zinc-100"
>
Receba novidades
</div>
</div>
<div class="mt-8 flex gap-8">
<div class="h-2 w-40 rounded bg-zinc-700"></div>
<div class="h-2 w-40 rounded bg-zinc-700"></div>
</div>
</div>
<div class="hidden w-64 shrink-0 lg:block">
<div class="h-72 w-48 rounded-lg bg-zinc-700/60"></div>
</div>
</div>
</div>
<div class="bg-zinc-100 px-10 py-12 text-zinc-900">
<div class="mx-auto max-w-2xl text-center">
<div class="mx-auto h-2 w-28 rounded bg-zinc-400"></div>
<div class="mx-auto mt-4 h-8 w-96 rounded bg-zinc-400"></div>
<div class="mx-auto mt-3 h-2 w-80 rounded bg-zinc-400"></div>
<div class="mx-auto mt-3 h-2 w-72 rounded bg-zinc-400"></div>
</div>
<div class="mx-auto mt-8 max-w-3xl space-y-4">
<div
class="h-12 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
Nome completo*
</div>
<div
class="h-12 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
WhatsApp (com DDD)*
</div>
<div
class="h-12 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
E-mail (opcional)
</div>
<div class="grid grid-cols-2 gap-4">
<div
class="h-12 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
Estado (opcional)
</div>
<div
class="h-12 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
Cidade (opcional)
</div>
</div>
<div
class="h-20 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
Comentário (opcional)
</div>
<div class="rounded-lg border border-zinc-300 bg-white p-4">
<div class="flex items-start gap-3">
<div
class="mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border border-red-600 bg-red-600 text-xs font-bold text-white"
>
✓
</div>
<div class="text-sm text-zinc-800">
<strong>Quero fazer parte do time:</strong> receber novidades com frequência, ser
adicionado(a) aos grupos de WhatsApp da campanha e participar das ações.
</div>
</div>
<p class="mt-2 text-xs text-zinc-500">
Sem marcar, você recebe apenas comunicações esporádicas da campanha — sem grupos e
sem envios frequentes.
</p>
</div>
</div>
<div class="mx-auto mt-4 max-w-3xl">
<div
class="inline-flex h-12 w-full items-center justify-center rounded-lg bg-red-600 text-sm font-extrabold text-white"
>
QUERO RECEBER NOVIDADES
</div>
</div>
<p class="mx-auto mt-4 max-w-xl text-center text-xs text-zinc-500">
Ao enviar, você demonstra apoio à campanha e escolhe como quer acompanhar: comunicações
frequentes e grupos de WhatsApp (marcando a opção acima) ou comunicações esporádicas —
conforme a Política de Privacidade (LGPD).
</p>
</div>
</section>
<section
data-shot="mobile"
class="mt-6 w-[390px] overflow-hidden rounded-xl border border-zinc-800"
>
<div class="bg-zinc-900 px-5 pt-8 pb-6">
<div class="h-3 w-20 rounded bg-zinc-700"></div>
<div class="mt-4 h-9 w-56 rounded bg-zinc-700"></div>
<div class="mt-2 h-9 w-48 rounded bg-zinc-700"></div>
<div class="mt-4 space-y-2">
<div class="h-2 w-72 rounded bg-zinc-700"></div>
<div class="h-2 w-60 rounded bg-zinc-700"></div>
</div>
<div class="mt-6 flex flex-col gap-2">
<div
class="inline-flex h-11 items-center justify-center rounded-[10px] bg-red-600 px-5 text-sm font-extrabold text-white"
>
Quero apoiar
</div>
<div
class="inline-flex h-11 items-center justify-center rounded-[10px] border-2 border-zinc-300 px-5 text-sm font-extrabold text-zinc-100"
>
Receba novidades
</div>
</div>
</div>
<div class="bg-zinc-100 px-5 py-8 text-zinc-900">
<div class="mx-auto h-2 w-24 rounded bg-zinc-400"></div>
<div class="mx-auto mt-4 h-7 w-72 rounded bg-zinc-400"></div>
<div class="mx-auto mt-3 h-2 w-64 rounded bg-zinc-400"></div>
<div class="mt-6 space-y-3">
<div
class="h-12 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
Nome completo*
</div>
<div
class="h-12 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
WhatsApp (com DDD)*
</div>
<div
class="h-12 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
E-mail (opcional)
</div>
<div class="grid grid-cols-2 gap-3">
<div
class="h-12 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
Estado (opcional)
</div>
<div
class="h-12 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
Cidade (opcional)
</div>
</div>
</div>
<div class="mt-3">
<div
class="h-20 rounded-lg border border-zinc-300 bg-white px-4 py-3 text-sm text-zinc-500"
>
Comentário (opcional)
</div>
</div>
<div class="mt-3 rounded-lg border border-zinc-300 bg-white p-4">
<div class="flex items-start gap-3">
<div
class="mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border border-red-600 bg-red-600 text-xs font-bold text-white"
>
✓
</div>
<div class="text-sm text-zinc-800">
<strong>Quero fazer parte do time:</strong> receber novidades com frequência, ser
adicionado(a) aos grupos de WhatsApp da campanha e participar das ações.
</div>
</div>
<p class="mt-2 text-xs text-zinc-500">
Sem marcar, você recebe apenas comunicações esporádicas da campanha — sem grupos e sem
envios frequentes.
</p>
</div>
<div class="mt-4">
<div
class="inline-flex h-12 w-full items-center justify-center rounded-lg bg-red-600 text-sm font-extrabold text-white"
>
QUERO RECEBER NOVIDADES
</div>
</div>
<p class="mx-auto mt-4 max-w-xs text-center text-xs text-zinc-500">
Ao enviar, você demonstra apoio à campanha e escolhe como quer acompanhar: comunicações
frequentes e grupos de WhatsApp (marcando a opção acima) ou comunicações esporádicas —
conforme a Política de Privacidade (LGPD).
</p>
</div>
</section>
<section data-shot="sucesso" class="mt-6 overflow-hidden rounded-xl border border-zinc-800">
<div class="bg-zinc-100 px-10 py-16 text-center text-zinc-900">
<div class="mx-auto h-10 w-10 rounded-full border-2 border-zinc-400"></div>
<div class="mx-auto mt-5 h-7 w-80 rounded bg-zinc-400"></div>
<p class="mx-auto mt-4 max-w-md text-sm text-zinc-600">
Você vai receber as novidades da campanha. Enquanto isso, acompanhe as bandeiras da
campanha abaixo.
</p>
<div
class="mx-auto mt-6 h-11 w-48 rounded-lg border-2 border-zinc-300 bg-white text-sm font-extrabold text-zinc-700"
></div>
</div>
</section>
</main>
</body>
</html>

View file

@ -0,0 +1,90 @@
# Captura de novidades da campanha na home pública
Status: registrado
Atualizado em: 2026-08-19
Issue: #93
Priority: P1
Model: composer-2.5
Impeccable: B — encaixe na home de campanha (CTA do hero + nova seção de captura)
Rascunho UI: docs/plans/captura-novidades-home-campanha-ui-draft.html + PNGs embutidos abaixo
Appetite: ~1–1,5 dia eng; seção de captura na home + CTA no hero + ação transacional com consentimento novo fail-closed
Responsável: —
## Intenção
O site público de campanha (home `jorgesolla1313.com.br`) hoje converte visitante em **doação** (CTA "Quero apoiar") e em **comunidade WhatsApp** (`/mandato-no-whatsapp`), mas não captura o visitante que demonstra apoio e quer acompanhar a campanha sem necessariamente doar. Sem esse degrau, o tráfego orgânico e pago da home sai sem deixar contato, e o time não tem lista própria de interesse para comunicações (novidades, agenda, ações) e para grupos de WhatsApp da campanha. A campanha está em janela eleitoral (propaganda iniciada 16/08, 1º turno 04/10) — cada visitante não capturado é audiência perdida para as semanas decisivas.
A captura tem dupla função, confirmada com produto: o contato é **um sinal de apoio** a Solla (a pessoa se dispõe a receber comunicações da campanha) **e** a porta de entrada para comunicações por e-mail **ou inclusão em grupos de WhatsApp da campanha** — por isso o telefone é campo obrigatório.
## Persona e fluxo
- **Persona / contexto:** visitante da home de campanha (eleitor simpatizante ou indeciso que quer acompanhar), navegando no celular ou no desktop; demonstra apoio deixando o contato para receber comunicações.
- **Job principal:** deixar o contato em segundos (nome + WhatsApp) para receber novidades da campanha, sem sair da página, escolhendo o nível de engajamento.
- **Fluxo desejado:**
1. Chega na home e vê o CTA secundário do hero apontando para a captura (substitui "Conhecer bandeiras").
2. Preenche nome + WhatsApp (obrigatórios) e, opcionalmente, e-mail, estado, cidade e comentário, numa seção da própria home.
3. Decide o nível de engajamento num toggle **pré-selecionado** "Quero fazer parte do time": marcado = comunicações frequentes + inclusão em grupos de WhatsApp da campanha + participação nas ações; desmarcado = apenas comunicações esporádicas, sem grupos e sem envios frequentes.
4. Envia; a seção vira confirmação in-place ("Inscrição confirmada").
5. O registro vira um contato com consentimento próprio **e a escolha do toggle gravada** (nível "time" vs "esporádico"), visível no admin junto das demais listas públicas.
- **Anti-goals de produto:** segundo cadastro de pessoa paralelo a `Contact`; gravar `supporter` (registro nominal interno da campanha — bloqueado pelo lote jurídico da Onda 0; este fluxo é captura pública com consentimento próprio, não o registro de apoiador interno); virar mini-CRM com segmentação/fase do funil; mesclar com o fluxo `/mandato-no-whatsapp` (comunidade do mandato, consentimento `whatsapp-inscricao` — canal e semântica diferentes).
### Rascunho UI (B)
![Rascunho UI — desktop](captura-novidades-home-campanha-ui-draft-desktop.png)
![Rascunho UI — mobile](captura-novidades-home-campanha-ui-draft-mobile.png)
![Rascunho UI — sucesso](captura-novidades-home-campanha-ui-draft-sucesso.png)
Fonte iterável: `docs/plans/captura-novidades-home-campanha-ui-draft.html`.
## Objetivo e aceite
- Visitante da home consegue demonstrar apoio e deixar **nome + WhatsApp** (obrigatórios) para receber comunicações da campanha, com e-mail, estado, cidade e comentário opcionais, e confirmação imediata na própria página.
- **Toggle "Quero fazer parte do time" pré-selecionado**: marcado = comunicações frequentes + inclusão em grupos de WhatsApp da campanha; desmarcado = apenas comunicações esporádicas (sem grupos, sem envios frequentes). A **escolha fica gravada no registro** — o admin distingue quem é "time" de quem é "esporádico".
- O CTA secundário do hero ("Conhecer bandeiras") vira o atalho para a seção de captura — as bandeiras continuam acessíveis na navegação da própria home (âncora `#bandeiras` já existe; o fluxo de captura não pode escondê-las).
- O registro é gravado como contato + vínculo de assinatura com **consentimento novo** (não reutiliza `whatsapp-inscricao`), no padrão fail-closed dos fluxos públicos existentes: sem o(s) texto(s) de consentimento aprovado(s) configurado(s) no admin, o form recusa a captura (nenhum dado é gravado).
- O(s) texto(s) do consentimento cobre(m) os dois níveis — "fazer parte do time" (comunicações frequentes + grupos de WhatsApp) e "esporádico" — aprovado(s) pelo jurídico antes da ativação.
- Guardrail LGPD: nenhuma captura antes do(s) documento(s) de consentimento (chave estável nova) existir(em) no admin — o executor resolve por chave, não por ID; a estrutura exata do consentimento (um texto com dois níveis vs. dois textos) é decisão de implementação junto do jurídico.
## Dados (intenção)
- **Vou apresentar dados?** Não — a captura é o dado; o consumo (quantidade de inscritos, crescimento) é leitura do admin existente, sem superfície nova.
## Direção no codebase (hipótese)
- **Áreas prováveis:** home `src/app/(frontend)/(home)/page.tsx` (nova seção + composição), hero `src/components/CampaignHero.tsx` (troca do CTA secundário), componente de formulário cliente em `src/components/` no padrão `WhatsappForm` (campos `NameInput`/`PhoneInput`/`EmailInput`/`StateSelect`/`CitySelect` já existem e são reutilizáveis), action em `src/app/(frontend)/actions/` no padrão `submitWhatsapp` (transação `Contact` + `Subscription` com consent por chave estável, `requireConsentByKey` fail-closed), chave nova em `src/lib/campaignConsentKeys.ts`.
- **Precedente a olhar:** `src/app/(frontend)/actions/submitWhatsapp.ts` (transação + consent), `src/components/WhatsappForm.tsx` (form e inputs), `src/lib/schemas/whatsapp-form.ts` (schema base `contactSchema` — obrigatoriedade difere: aqui nome + telefone), `/mandato-no-whatsapp` (página irmã — **não** mesclada nesta fatia).
- **Risco de acoplamento:** a home é superfície compartilhada do trilho S (últimos itens S1–S6) — toca o mesmo arquivo que o item S8 (pixel) tocará; serializado por dependência.
## Dependências
- Nenhuma dura. **S10** (pixel da home) depende deste item para disparar `Lead` no sucesso do form.
## Fora de escopo
- Mescla com `/mandato-no-whatsapp` ou reuso do consentimento `whatsapp-inscricao`.
- Gravação em `supporter` (registro nominal interno da campanha) — permanece bloqueado pelo lote jurídico da Onda 0.
- Segmentação, tags de interesse, double opt-in por e-mail, integração com ferramenta de e-mail marketing — anotar como gatilho futuro se marketing pedir.
- Redesign do hero ou da home (mudança de um CTA + uma seção).
## Rabbit holes de produto
- **Mini-CRM.** Se alguém "só completar": campos extras, segmentação, fases de funil. **Corte neste item:** os 6 campos do rascunho (nome + WhatsApp obrigatórios; e-mail, estado, cidade, comentário opcionais) e nada mais; o vínculo reutiliza o modelo de assinatura existente.
- **"Já que o telefone é obrigatório, vira apoiador do sistema interno".** Puxa o registro nominal bloqueado juridicamente. **Corte:** o registro vive nas listas públicas de contato/assinatura com consentimento próprio; `supporter` só quando o lote jurídico liberar.
- **"Um consentimento só para tudo" ou "dois consents mas um só registro".** A escolha do toggle tem que sobreviver no dado, senão o time não sabe quem pode entrar em grupo. **Corte:** a escolha fica gravada e visível no admin; a forma (um texto com os dois níveis vs. dois textos) é decisão de implementação com o jurídico.
- **Form igual ao do WhatsApp.** Copiar a semântica do "comunidade do mandato" arrasta canal e consentimento errados. **Corte:** consentimento novo; fluxos permanecem irmãos, não gêmeos.
- **Double opt-in / verificação de e-mail.** Vira infraestrutura de e-mail marketing. **Corte:** confirmação in-place sem envio de e-mail; gatilho futuro se marketing pedir.
## Questões em aberto (produto)
- **Texto(s) do consentimento?** Novo texto cobrindo os dois níveis — "fazer parte do time" (comunicações frequentes + grupos de WhatsApp + participação nas ações) e "esporádico" (comunicação direta, sem grupos/sem frequência) — com chave estável nova, resolvida fail-closed. **Recomendação:** o jurídico aprova o(s) texto(s) e o admin cria o(s) documento(s) antes da ativação — o app não captura sem ele(s); a chave exata e a estrutura (um vs. dois textos) ficam para a implementação junto do jurídico. _(decisões de campos/local/toggle/Lead já confirmadas com produto em 2026-08-19; só o texto jurídico fica pendente de aprovação)_
## Referências
- Rascunho UI (gate): `docs/plans/captura-novidades-home-campanha-ui-draft.html` + PNGs embutidos acima
- `src/app/(frontend)/actions/submitWhatsapp.ts` — padrão de escrita transacional com consent fail-closed
- `src/components/WhatsappForm.tsx`, `src/lib/schemas/whatsapp-form.ts` — padrão de form cliente e schema
- `src/lib/campaignConsentKeys.ts` — keys estáveis existentes
- `src/components/CampaignHero.tsx` — CTA "Conhecer bandeiras" (linha ~104–114) a substituir
- `AGENTS.md` — `Contact` como pessoa normalizada + joins, consentimento por chave estável, transações multi-collection, bloqueio jurídico de `supporter` (Onda 0)

View file

@ -0,0 +1,76 @@
# Pixel do Meta (Facebook) na página pública de campanha
Status: registrado
Atualizado em: 2026-08-19
Issue: #94
Priority: P1
Model: composer-2.5
Impeccable: A — N/A (campo único no admin replicando precedente aceito + script invisível ao visitante; zero superfície pública nova)
Rascunho UI: N/A — sem UI
Appetite: ~0,5–1 dia eng; campo admin + injeção do base code na home + `Lead` no sucesso do form de captura
Responsável: —
## Intenção
O time de campanha paga roda tráfego no Meta direcionado à home pública de campanha, mas hoje não vê nada: sem Pixel, o Events Manager não registra visitas nem conversões dessa página, e as campanhas otimizam às cegas (sem retargeting, sem evento de conversão). Nos abaixo-assinados o time já configura o ID do Pixel por documento (`petition.tracking.facebookPixelId`, entregue 2026-07-21); a home de campanha precisa do mesmo instrumento em nível de site — um campo no admin para o ID numérico do Dataset, injetado na página pública de campanha, e o evento `Lead` quando a captura de novidades (S9) for concluída. Em janela eleitoral (1º turno 04/10), cada semana sem atribuição é verba paga sem feedback.
Este item revisita a decisão adiada do plano `pixel-meta-abaixo-assinado` ("Pixel / Dataset global em SiteSettings — revisitar quando o mesmo ID for colado em ≥3 petições e o admin reclamar de repetição"): produto agora pede explicitamente um Pixel de site para a página de campanha — o gatilho foi puxado, o precedente segue intacto para os abaixo-assinados.
## Persona e fluxo
- **Persona / contexto:** marketing digital / analista de campanha paga no Meta, no admin; quer ver visitas e conversões da home de campanha no Events Manager do Dataset.
- **Job principal:** configurar um Pixel no admin (colar só o ID numérico) e ver a home de campanha alimentar o Dataset sem colar JavaScript.
- **Fluxo desejado:**
1. Editor no `/admin` cola o ID numérico do Pixel no campo de rastreamento das configurações do site.
2. A home pública de campanha carrega o base code do Meta (`PageView`) quando o ID está presente e válido.
3. Quando o visitante conclui a captura de novidades (S9), exatamente um `Lead` é disparado.
4. O Events Manager mostra PageViews e Leads da página de campanha para otimização/retargeting.
- **Anti-goals de produto:** colar snippet HTML no admin (XSS); Pixel vazando PageViews do resto do site (notícias, etc.); CAPI/Advanced Matching nesta fatia; cookie banner/CMP nesta fatia.
## Objetivo e aceite
- Campo opcional "ID do Pixel do Meta" nas configurações do site (admin), com a mesma validação dos abaixo-assinados (somente ID numérico, 5–20 dígitos, sem HTML) e a mesma normalização no save.
- Quando o ID está configurado e válido, a home pública de campanha carrega o base code + `PageView`; sem ID, nada é carregado (fail-closed, zero impacto).
- Quando a captura de novidades (S9) é concluída com Pixel ativo, dispara exatamente um `Lead` (nunca no page load) — mesmo padrão da petição.
- Guardrails: nunca persistir nem executar HTML/JS do editor; sem env var obrigatória; cache da home revalidado pela edição do admin (o hook de revalidação do global já existe).
## Dados (intenção)
- **Vou apresentar dados?** Não — o dado (PageView/Lead) vive no Meta Events Manager; o app só emite o evento.
## Direção no codebase (hipótese)
- **Áreas prováveis:** global `src/globals/SiteSettings.ts` (campo único, provável dono — o plano anterior já apontava `SiteSettings` para um Pixel global; a revalidação `revalidateGlobal('site-settings')` já existe), home `src/app/(frontend)/(home)/page.tsx` (injeção do `<MetaPixel />`), `src/components/MetaPixel.tsx` + `src/lib/facebookPixel.ts` (reuso direto do precedente), form de captura do S9 (disparo do `Lead` no sucesso, no padrão `PetitionForm`).
- **Precedente a olhar:** `docs/plans/pixel-meta-abaixo-assinado.md` (decisões travadas: persistir só o ID, nunca snippet; `Lead` só no sucesso; validação e normalização reutilizadas), `src/collections/Petition.ts` (grupo `tracking` + `validate` + `beforeChange`), `src/app/(frontend)/abaixo-assinado/[id]/page.tsx` (injeção condicional).
- **Risco de acoplamento:** toca a home (mesmo arquivo do S9) e o `SiteSettings` (global lido por outras superfícies do site) — serializado por dependência; a leitura do global na home deve ser compatível com o caching da página (decisão de implementação, não de produto).
## Dependências
- **S9** (captura de novidades) — necessária só para o `Lead` no sucesso do form; o `PageView` na home é independente. Registrada como dependência para o `Lead` sair junto.
## Fora de escopo
- Pixel nas demais páginas do site (notícias, artigos, privacidade) — o pedido é a página pública de campanha; se marketing quiser site-wide, item futuro.
- Conversions API (CAPI) / Advanced Matching / dedup `eventID` — herda os gatilhos do plano da petição.
- Cookie banner/CMP, GTM, TikTok/Google pixels.
- Uniqueness de Dataset — mesmo ID pode aparecer na petição e na home.
## Rabbit holes de produto
- **Colar snippet HTML "como o Meta manda".** XSS + HTML no CMS. **Corte:** campo só ID + description + validação server-side, idêntico ao precedente aceito.
- **Pixel em tudo.** "Já que o campo existe, coloca em todas as páginas". **Corte:** só a home de campanha; site-wide é decisão separada de produto.
- **CAPI "já que estamos no servidor".** Secrets, hashing PII, dedup, retries. **Corte:** fora, herda os gatilhos do plano da petição.
## Questões em aberto (produto)
- **Evento `Lead` no sucesso do form de captura?** Confirmado com produto em 2026-08-19: **sim** — PageView no load + `Lead` no sucesso da captura (S9), réplica do precedente da petição.
- **Onde o campo mora?** **Opções:** (a) global `SiteSettings` (Configurações do site) | (b) novo global dedicado de rastreamento. **Recomendação:** (a) — dono existente com revalidação pronta; o plano da petição já o apontava como destino natural de um Pixel global. _(assumido — validar com produto)_
## Referências
- `docs/plans/pixel-meta-abaixo-assinado.md` — precedente integral (decisões, gatilhos, rejeitados)
- `src/collections/Petition.ts` — campo `tracking.facebookPixelId` + validação/normalização
- `src/components/MetaPixel.tsx` + `src/lib/facebookPixel.ts` — base code e `trackMetaLead` (reuso)
- `src/globals/SiteSettings.ts` — global provável dono do campo
- `src/app/(frontend)/(home)/page.tsx` — home pública de campanha
- S9 — form de captura de novidades (dependência do `Lead`)