Deduplicação é o coração do desenho. A regra é simples: gere um event_id único no momento da conversão e use o MESMO valor no Pixel (campo eventID) e na CAPI (campo event_id). A Meta compara event_name + event_id e, se vir o par duas vezes dentro da janela de deduplicação, mantém apenas um.
// 1) Browser (Meta Pixel): gera um event_id unico e dispara o evento.
const eventId = crypto.randomUUID(); // ex.: '6f3c0b2a-9d4e-4a11-8c77-1e2b3f4a5d6e'
fbq('track', 'Purchase', {
value: 199.90,
currency: 'BRL',
content_ids: ['SKU-123'],
content_type: 'product',
}, {
eventID: eventId, // <-- chave da deduplicacao no lado do browser
});
// 2) Server (Conversions API): MESMO event_id enviado para o servidor.
// O front passa o eventId no corpo da requisicao de checkout.
await fetch('/api/track/purchase', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ eventId, value: 199.90, currency: 'BRL', sku: 'SKU-123' }),
});
No servidor, o mesmo event_id viaja no payload da CAPI. O exemplo abaixo monta a requisição Purchase, hasheia os dados pessoais em SHA-256 e faz o POST para graph.facebook.com:
// Server-side: envio do mesmo Purchase para a Conversions API.
// O event_id identico ao do Pixel permite que a Meta descarte a duplicata.
import crypto from 'node:crypto';
const sha256 = (value) =>
crypto.createHash('sha256').update(String(value).trim().toLowerCase()).digest('hex');
async function sendPurchaseToCapi({ eventId, email, phone, value, currency, sku, clientIp, userAgent, fbp, fbc }) {
const payload = {
data: [
{
event_name: 'Purchase',
event_time: Math.floor(Date.now() / 1000),
event_id: eventId, // <-- mesmo event_id do Pixel (deduplicacao)
action_source: 'website',
event_source_url: 'https://loja.exemplo.com/checkout',
user_data: {
em: [sha256(email)], // email hashado em SHA-256
ph: [sha256(phone)], // telefone hashado em SHA-256 (formato E.164, so digitos)
client_ip_address: clientIp, // nao hashar IP
client_user_agent: userAgent, // nao hashar user agent
fbp, // cookie _fbp (nao hashar)
fbc, // cookie _fbc (nao hashar)
},
custom_data: { value, currency, content_ids: [sku], content_type: 'product' },
},
],
// test_event_code: 'TEST12345', // use no Events Manager durante o desenvolvimento
};
const url = `https://graph.facebook.com/v19.0/${process.env.PIXEL_ID}/events?access_token=${process.env.CAPI_TOKEN}`;
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
return res.json(); // { events_received, messages, fbtrace_id }
}
- Gere o event_id uma vez (no servidor de preferência) e propague para o browser, ou gere no browser e envie ao servidor: o que importa é ser idêntico nos dois lados.
- Use o mesmo event_name nos dois canais (Purchase com Purchase, Lead com Lead).
- Mantenha event_time coerente: a janela de deduplicação trabalha em torno do horário do evento.
- Valide no Events Manager: a aba de eventos mostra a flag de deduplicação e quantos eventos foram unidos.