mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-15 10:43:07 +00:00
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.
146 lines
13 KiB
Markdown
146 lines
13 KiB
Markdown
# Pixel do Meta (Facebook) nos abaixo-assinados
|
||
|
||
Status: entregue 2026-07-21
|
||
Atualizado em: 2026-07-21
|
||
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.
|
||
|
||
Na implementação (`implement-roadmap-item`): craft compacto → critique → polish (superfície mínima; sem shape longo).
|
||
|
||
Brief compacto:
|
||
|
||
- **Persona / contexto:** marketing digital monta campanha de ads no Meta e precisa ver assinaturas como conversões; editor no `/admin` cola o ID do Pixel no abaixo-assinado.
|
||
- **Job principal:** atribuir assinaturas reais a um Pixel por petição, sem o editor colar JavaScript arbitrário.
|
||
- **Estratégia de cor:** Restrained (tokens `petition` / admin Payload existentes).
|
||
- **Anti-goals:** textarea de snippet HTML; GTM/multi-vendor; cookie banner completo; CAPI/Advanced Matching nesta fatia.
|
||
|
||
## Contexto
|
||
|
||
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`) 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.
|
||
|
||
### O que o Meta Pixel exige (pesquisa)
|
||
|
||
Fontes: [Meta Pixel Get Started](https://developers.facebook.com/docs/meta-pixel/get-started) (atualizado 2026-06-30), [Conversion tracking](https://developers.facebook.com/docs/meta-pixel/implementation/conversion-tracking), [Deduplicate Pixel + CAPI](https://developers.facebook.com/docs/marketing-api/conversions-api/deduplicate-pixel-and-server-events/).
|
||
|
||
1. **Base code** no `<head>` (ou via `next/script`): carrega `fbevents.js`, chama `fbq('init', PIXEL_ID)` e `fbq('track', 'PageView')`. O único dado que o editor precisa fornecer é o **Pixel ID** (número do Dataset no Events Manager) — o restante do “snippet” é boilerplate fixo.
|
||
2. **Evento de conversão para lead-gen:** `fbq('track', 'Lead', {…})` **somente após** a assinatura bem-sucedida — nunca no carregamento da página do formulário (erro clássico que infla leads 5–10× e corrompe o otimizador).
|
||
3. **Parâmetros úteis no `Lead`:** `content_name` (título/id da petição). `eventID` opcional agora; obrigatório se/quando houver Conversions API (CAPI) para deduplicação.
|
||
4. **CAPI + Advanced Matching** (e-mail/telefone hasheados no servidor) melhoram Event Match Quality (~6.0+), mas exigem secret de access token, hashing LGPD-consciente e dedup — fora do appetite desta fatia.
|
||
5. **LGPD:** o Pixel define cookies Meta (`_fbp` etc.) e envia sinais de navegação/conversão. Transparência em `/privacidade` (e, se o jurídico pedir, no texto de Consent da petição) é requisito de produto; cookie banner site-wide fica adiado.
|
||
|
||
## Objetivos
|
||
|
||
- Campo opcional no admin de `petition` para o marketing configurar o Pixel **por abaixo-assinado**.
|
||
- Na página pública: carregar base code + `PageView` quando o ID estiver presente.
|
||
- No sucesso da assinatura: disparar exatamente um `Lead` (não no page load).
|
||
- Guardrails: **nunca** persistir nem executar HTML/JS colado pelo editor; validar ID numérico; sem env var obrigatória (config por documento); migration com `push: false`; cache já revalidado por `revalidateDocumentById` no `afterChange` existente.
|
||
- Sem novo `Consent` key nesta fatia (petição já exige Consent de assinatura); sem CAPI.
|
||
|
||
## Decisões travadas
|
||
|
||
- **Persistir só `facebookPixelId` (texto, dígitos), não o snippet HTML.** O “snippet” que o Meta mostra no Events Manager é boilerplate + ID; colar HTML no admin é XSS / injection e quebra CSP. O app injeta o base code controlado em código. **Rejeitado:** `textarea`/`code` com snippet livre; campo `html`/`richText` de tracking; GTM container ID como substituto nesta fatia.
|
||
- **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)”).
|
||
|
||
## Abordagem proposta
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
Admin["Payload admin<br/>tracking.facebookPixelId"]
|
||
Page["abaixo-assinado/[id]<br/>Server Component"]
|
||
Pixel["MetaPixel client<br/>next/script + fbq init/PageView"]
|
||
Form["PetitionForm"]
|
||
Action["submitPetitionSignature"]
|
||
Lead["trackMetaLead<br/>fbq track Lead"]
|
||
Meta["Meta Events Manager"]
|
||
|
||
Admin --> Page
|
||
Page --> Pixel
|
||
Pixel --> Meta
|
||
Form --> Action
|
||
Action -->|sucesso--> Lead
|
||
Lead --> Meta
|
||
```
|
||
|
||
Componentes:
|
||
|
||
- **Campo `facebookPixelId`** em `src/collections/Petition.ts` (irmão do grupo `form` ou dentro de um group `tracking` com label “Rastreamento / Ads”): `type: 'text'`, opcional, `admin.description` explicando “cole só o ID numérico do Events Manager (ex.: 123456789012345), não o snippet HTML completo”. `validate` rejeita não-dígitos / comprimento fora de ~5–20. Sem `required`.
|
||
- **`isValidFacebookPixelId` / `normalizeFacebookPixelId`** (em `src/lib/facebookPixel.ts` ou `src/utilities/facebookPixel.ts`): helper puro testável (unit) — depth check: um módulo pequeno que esconde a regex e a montagem do init; não inventar “AnalyticsService”.
|
||
- **`MetaPixel`** (client, `src/components/MetaPixel.tsx`): se `pixelId` válido, renderiza `next/script` (`strategy="afterInteractive"`) que carrega o padrão Meta (`fbevents.js` + `fbq('init', id)` + `fbq('track', 'PageView')`) e noscript img opcional. Tipar `window.fbq` localmente (sem `@types` de terceiros se não existir no repo).
|
||
- **`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 `<MetaPixel />` 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** `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
|
||
|
||
- Nenhuma de outro plano de trilha A/B/C/D.
|
||
- **Suave:** polish do Aviso de Privacidade (Site público / Onda 0 textos finais) deve mencionar cookies/ferramentas de ads (Meta) quando Pixel estiver em uso — não bloqueia a engenharia do campo.
|
||
- Reusa: `revalidateDocumentById` já no `afterChange` de `Petition`; `PetitionForm` success path; `next/script`.
|
||
|
||
## Não escopo
|
||
|
||
- Conversions API (CAPI) / access token / Event Match Quality server-side → fatia futura com gatilho abaixo.
|
||
- Google Tag Manager, TikTok Pixel, Google Ads gtag — outro item se marketing pedir.
|
||
- Cookie consent banner site-wide / CMP.
|
||
- Pixel no layout global do site (home, notícias, `/campanha`).
|
||
- Thank-you page dedicada / redirect pós-assinatura.
|
||
- Alterar schema de `signature`/`contact` para guardar `event_id` Meta.
|
||
|
||
## Rabbit holes
|
||
|
||
- **Colar snippet HTML “como o Meta manda”.** Se alguém “só completar” o pedido literal do marketing: XSS + HTML no CMS. **Mitigação:** campo só ID + description no admin + validação server-side.
|
||
- **CAPI “já que estamos no servidor”.** Explode em secrets, hashing PII, dedup, retries. **Mitigação:** defer com gatilho.
|
||
- **Cookie banner completo por causa deste campo.** Projeto de CMP. **Mitigação:** transparência em `/privacidade` + decisão jurídica sobre PageView; não construir banner aqui.
|
||
- **Advanced Matching no browser com e-mail/telefone em claro.** Vazamento + LGPD. **Mitigação:** fora; CAPI hasheado só em fatia futura.
|
||
|
||
## 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 `<noscript>` 1×1** — padrão Meta; `next/image` inadequado.
|
||
- **Int test de `Petition.validate`** — opcional no appetite original; sem evidência de regressão.
|
||
- **Mencionar cookies/Meta em `/privacidade`** — absorvido no item existente do roadmap (Site público / O0+); não duplicar plano.
|
||
|
||
## Referências
|
||
|
||
- `docs/roadmap.md` (Site público)
|
||
- `src/collections/Petition.ts` — schema admin do abaixo-assinado
|
||
- `src/app/(frontend)/abaixo-assinado/[id]/page.tsx` — página pública
|
||
- `src/components/PetitionForm.tsx` — sucesso da assinatura
|
||
- `src/app/(frontend)/actions/submitPetitionSignature.ts` — escrita transacional (inalterada no fluxo de tracking cliente)
|
||
- Meta: [Get Started](https://developers.facebook.com/docs/meta-pixel/get-started) · [Conversion tracking](https://developers.facebook.com/docs/meta-pixel/implementation/conversion-tracking) · [Deduplication](https://developers.facebook.com/docs/marketing-api/conversions-api/deduplicate-pixel-and-server-events/)
|
||
- Next.js: `next/script` + `strategy="afterInteractive"` (App Router)
|
||
- AGENTS.md — naming, migrations `push: false`, Consent por chave (não inventar paralelo aqui), revalidate de documentos
|
||
- `PRODUCT.md` / `DESIGN.md` — canal público / tema `petition`
|