import * as crypto from 'crypto'; const BASE_URL = 'https://graph.facebook.com/v21.0'; const PIXEL_ID = process.env.META_PIXEL_ID; const ACCESS_TOKEN = process.env.META_ACCESS_TOKEN; function hashValue(value: string): string { return crypto.createHash('sha256').update(value.trim().toLowerCase()).digest('hex'); } interface UserData { email?: string; ip?: string; userAgent?: string; fbc?: string; fbp?: string; } interface ConversionEvent { eventName: 'CompleteRegistration' | 'Purchase' | 'ViewContent' | 'Lead' | 'InitiateCheckout'; eventTime?: number; eventSourceUrl?: string; userData: UserData; customData?: Record; } export async function sendConversionEvent(event: ConversionEvent): Promise { if (!PIXEL_ID || !ACCESS_TOKEN) { return; } const hashedUserData: Record = {}; if (event.userData.email) hashedUserData.em = hashValue(event.userData.email); if (event.userData.ip) hashedUserData.client_ip_address = event.userData.ip; if (event.userData.userAgent) hashedUserData.client_user_agent = event.userData.userAgent; if (event.userData.fbc) hashedUserData.fbc = event.userData.fbc; if (event.userData.fbp) hashedUserData.fbp = event.userData.fbp; const payload = { data: [ { event_name: event.eventName, event_time: event.eventTime ?? Math.floor(Date.now() / 1000), event_source_url: event.eventSourceUrl ?? process.env.NEXT_PUBLIC_APP_URL, action_source: 'website', user_data: hashedUserData, custom_data: event.customData ?? {}, }, ], }; try { const res = await fetch(`${BASE_URL}/${PIXEL_ID}/events?access_token=${ACCESS_TOKEN}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); if (!res.ok) { const err = await res.json(); console.error('[Meta CAPI] Error:', err); } } catch (error) { console.error('[Meta CAPI] Network error:', error); } } export { hashValue };