From be1106f887f5c6ccc6662f64901f9139b778ae95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Ign=C3=A1cio=20Fontoura=20Solla?= Date: Tue, 21 Jul 2026 10:51:15 -0300 Subject: [PATCH] Add Meta Pixel tracking to public petition pages. Let marketing configure a numeric facebookPixelId per petition in Payload, fire PageView on load and Lead after a successful signature, and mark the roadmap item delivered with deferred follow-ups documented. --- docs/plans/pixel-meta-abaixo-assinado.md | 38 +- docs/roadmap.md | 12 +- .../(frontend)/abaixo-assinado/[id]/page.tsx | 13 +- src/collections/Petition.ts | 32 + src/components/MetaPixel.tsx | 31 + src/components/PetitionForm.tsx | 7 +- src/lib/facebookPixel.ts | 38 + ...133531_add_petition_facebook_pixel_id.json | 10381 ++++++++++++++++ ...1_133531_add_petition_facebook_pixel_id.ts | 13 + src/migrations/index.ts | 8 +- src/payload-types.ts | 11 + tests/unit/facebookPixel.unit.spec.ts | 70 + 12 files changed, 10633 insertions(+), 21 deletions(-) create mode 100644 src/components/MetaPixel.tsx create mode 100644 src/lib/facebookPixel.ts create mode 100644 src/migrations/20260721_133531_add_petition_facebook_pixel_id.json create mode 100644 src/migrations/20260721_133531_add_petition_facebook_pixel_id.ts create mode 100644 tests/unit/facebookPixel.unit.spec.ts diff --git a/docs/plans/pixel-meta-abaixo-assinado.md b/docs/plans/pixel-meta-abaixo-assinado.md index 47c8e887..77e0b21e 100644 --- a/docs/plans/pixel-meta-abaixo-assinado.md +++ b/docs/plans/pixel-meta-abaixo-assinado.md @@ -1,12 +1,14 @@ # Pixel do Meta (Facebook) nos abaixo-assinados -Status: rascunho +Status: entregue 2026-07-21 Atualizado em: 2026-07-21 -Item do roadmap: [docs/roadmap.md](../roadmap.md) (Site público) +Item do roadmap: [docs/roadmap.md](../roadmap.md) (Site público — entregue) Impeccable: B — encaixe no admin `Petition` + script na página `/abaixo-assinado/[id]` e no sucesso do `PetitionForm` Appetite: ~0,5–1 dia eng; migration + 1 campo admin + componente de script + disparo `Lead` no sucesso Responsável: — +_Revisão 2026-07-21: implementação + `/simplify` + `capture-review-debts` — status entregue; unicidade travada; gatilho S10 (fila/retry de `Lead`) em Adiado; débitos de triage registrados em Explicitamente fora._ + ## Design (Impeccable) Âncoras: `PRODUCT.md` / `DESIGN.md` (register `brand` no site público; tema `data-theme='petition'` na página). Admin Payload usa labels pt-BR do grupo `Abaixo-assinados` — sem redesign de paleta. @@ -22,9 +24,9 @@ Brief compacto: ## Contexto -A página pública `/abaixo-assinado/[id]` (`src/app/(frontend)/abaixo-assinado/[id]/page.tsx`) renderiza o documento `petition` e o formulário cliente `PetitionForm` (`src/components/PetitionForm.tsx`). Assinatura bem-sucedida chama `submitPetitionSignature` e abre `PetitionSuccessDialog` — hoje **sem** telemetria de ads. +A página pública `/abaixo-assinado/[id]` renderiza o documento `petition` e o formulário cliente `PetitionForm`. Assinatura bem-sucedida chama `submitPetitionSignature` e abre `PetitionSuccessDialog`. Com Pixel configurado: `MetaPixel` dispara `PageView` no load; `trackMetaLead` dispara `Lead` após assinatura ok. -A collection `Petition` (`src/collections/Petition.ts`, grupo admin `Abaixo-assinados`) tem `title`/`subtitle`/`body`/`enabled` e o grupo `form` (título, subtítulo, `consent`). Não há campo de tracking. +A collection `Petition` (`src/collections/Petition.ts`) expõe o grupo `tracking.facebookPixelId` (admin “Rastreamento / Ads”) além do grupo `form`. O time de marketing digital pediu (2026-07-21) um campo no formulário do abaixo-assinado no Payload para “adicionar o snippet do Pixel do Facebook” e acompanhar assinaturas no Events Manager / otimizar campanhas. @@ -52,17 +54,14 @@ Fontes: [Meta Pixel Get Started](https://developers.facebook.com/docs/meta-pixel - **Pixel por petição (campo no documento `petition`), não global do site.** Campanhas de ads costumam ser por abaixo-assinado/URL; evita Pixel único vazar PageViews de notícias/home. **Rejeitado:** só env `NEXT_PUBLIC_FACEBOOK_PIXEL_ID` site-wide; Global `SiteSettings` único (pode ser fill-in futuro se marketing unificar Dataset). - **v1 = browser Pixel only, com os dois eventos:** `PageView` no load da página da petição **e** `Lead` no sucesso do form (confirmado com produto 2026-07-21). Padrão Meta: retargeting de visitantes + conversão de assinatura. Transparência de cookies/Meta fica no polish de `/privacidade` (dependência suave). **Rejeitado nesta fatia:** só `Lead` sem `PageView`; Conversions API; Advanced Matching com e-mail/telefone no browser/servidor; eventos `CompleteRegistration`/`Contact` além de `Lead`; cookie banner / CMP. - **`Lead` só após `submitPetitionSignature` ok** (mesmo caminho que abre o diálogo de sucesso). **Rejeitado:** `Lead` no `onSubmit` antes da resposta; `Lead` no page load; thank-you page dedicada (não existe hoje — o sucesso é modal same-page). +- **Mesmo Dataset em N petições permitido.** O mesmo `facebookPixelId` pode aparecer em várias petições; `content_name` no `Lead` carrega o título da petição para diferenciar no Events Manager. **Rejeitado:** uniqueness forçada no admin. - **i18n e naming** seguem o AGENTS.md: identificadores em inglês (`facebookPixelId`, `MetaPixel`, `trackMetaLead`); labels admin e copy em pt-BR (“ID do Pixel do Meta (Facebook)”). -## Questões em aberto - -- **Um Pixel por petição vs. mesmo Dataset em várias petições?** **Opções:** A) permitir o mesmo ID em N petições (só conteúdo do `Lead` diferencia) | B) forçar uniqueness. **Recomendação:** A — Dataset único da campanha é o caso comum; `content_name` carrega `petition.id` / título. - ## Abordagem proposta ```mermaid flowchart LR - Admin["Payload admin
petition.facebookPixelId"] + Admin["Payload admin
tracking.facebookPixelId"] Page["abaixo-assinado/[id]
Server Component"] Pixel["MetaPixel client
next/script + fbq init/PageView"] Form["PetitionForm"] @@ -86,8 +85,16 @@ Componentes: - **`trackMetaLead`** (mesmo módulo lib/utilities ou export do componente): `fbq('track', 'Lead', { content_name }, { eventID? })` se `window.fbq` existir; no-op seguro se Pixel não carregou / adblock. - **`PetitionForm`**: após sucesso de `submitPetitionSignature`, chamar `trackMetaLead` com `content_name` = título ou id da petição (e `eventID` = UUID gerado no cliente **só se** quisermos preparar CAPI depois — nesta fatia opcional; preferir gerar UUID e passar já, custo zero, facilita fatia futura). - **Página** `abaixo-assinado/[id]/page.tsx`: passar `petition.facebookPixelId` para `` quando presente; incluir o campo no `select`/cache se a leitura de documento filtrar campos (hoje `getCachedDocumentById` carrega o doc — confirmar após `generate:types`). -- **Migration**: `pnpm migrate:create add_petition_facebook_pixel_id` — coluna nullable em `petition` (+ drafts/versions se Payload espelhar). Sem backfill. -- **Testes:** unit no validador de ID; int opcional na collection validate se o repo já testa Petition; E2E não obrigatório (terceiro externo) — smoke manual com [Meta Pixel Helper](https://developers.facebook.com/docs/meta-pixel/support/pixel-helper). +- **Migration** `20260721_133531_add_petition_facebook_pixel_id` — colunas `tracking_facebook_pixel_id` / `version_tracking_facebook_pixel_id`; sem backfill. +- **Testes:** `tests/unit/facebookPixel.unit.spec.ts` (validador + `trackMetaLead`); smoke manual com [Meta Pixel Helper](https://developers.facebook.com/docs/meta-pixel/support/pixel-helper). + +## Já resolvido no simplify/critique (não reabrir) + +- Normalização única na página (`normalizeFacebookPixelId`) + prop `facebookPixelId` para `PetitionForm` (sem re-normalizar no form). +- `validate` admin e `beforeChange` em `Petition` reutilizam `normalizeFacebookPixelId`. +- Validação duplicada removida de `MetaPixel` (prop pré-validada). +- Tipos one-off removidos (`TrackMetaLeadInput`, `MetaPixelProps`); `trackMetaLead` com assinatura posicional. +- Blockquote da página da petição suavizado (Impeccable side-tab); `impeccable detect` limpo na superfície. ## Dependências @@ -113,10 +120,19 @@ Componentes: ## Adiado com gatilho +- **Fila/retry de `Lead` quando `window.fbq` ainda não carregou** (race submit rápido vs. `afterInteractive`). Revisitar quando smoke com [Meta Pixel Helper](https://developers.facebook.com/docs/meta-pixel/support/pixel-helper) mostrar conversão `Lead` ausente após assinatura bem-sucedida em produção. - **Conversions API + dedup com `event_id` compartilhado.** Revisitar quando: marketing reportar perda material de atribuição (iOS/adblock) **ou** Event Match Quality < 6 no Dataset em uso com volume real de ads. - **Pixel / Dataset global em `SiteSettings`.** Revisitar quando: o mesmo ID for colado em ≥3 petições e o admin reclamar de repetição. - **Cookie banner / CMP.** Revisitar quando: jurídico exigir bloqueio pré-consent de cookies de ads (não só transparência). +## Explicitamente fora (triage capture-review-debts 2026-07-21) + +- **Re-validação em `trackMetaLead`** — defesa em profundidade intencional (custo zero). +- **Flatten `tracking` → campo top-level** — grupo reservado para futuros campos de ads. +- **`eslint` `@next/next/no-img-element` no `