/** * CDP Edge — GA4 Measurement Protocol * Envia eventos server-side para o GA4 via Measurement Protocol. */ import { normalizePhone } from '../utils.js'; import { logApiFailure } from '../db.js'; import { Env, TrackPayload } from '../../types.js'; import { ExecutionContext } from '@cloudflare/workers-types'; export async function sendGA4Mp(env: Env, ga4EventName: string, payload: TrackPayload, ctx: ExecutionContext | null): Promise<{ ok?: boolean; status?: number; skipped?: string; error?: string }> { if (!env.GA4_API_SECRET) return { skipped: 'GA4_API_SECRET not set' }; const { gaClientId: clientId, sessionId, value, currency, contentName, email, phone, firstName, orderId, } = payload; if (!clientId) return { skipped: 'no clientId' }; const eventParams: Record = { ...(value !== undefined && { value: parseFloat(String(value)) }), ...(currency && { currency: String(currency).toUpperCase() }), ...(contentName && { content_name: contentName }), ...(orderId && { transaction_id: orderId }), ...(email && { user_data_email_address: email.toLowerCase().trim() }), ...(phone && { user_data_phone_number: normalizePhone(phone) || '' }), ...(firstName && { user_data_first_name: firstName.toLowerCase().trim() }), ...(sessionId && { session_id: sessionId }), engagement_time_msec: 100, }; const body = { client_id: clientId, events: [{ name: ga4EventName, params: eventParams }], }; const url = `https://www.google-analytics.com/mp/collect` + `?measurement_id=${env.GA4_MEASUREMENT_ID}` + `&api_secret=${env.GA4_API_SECRET}`; try { const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); if (res.status !== 204) { if (env.DB && ctx) { ctx.waitUntil(logApiFailure(env.DB, 'ga4', ga4EventName, String(res.status), 'GA4 returned non-204 status', '', JSON.stringify(body))); } } return res.status === 204 ? { ok: true } : { status: res.status }; } catch (err: any) { console.error('GA4 MP fetch failed:', err?.message || String(err)); if (env.DB && ctx) { ctx.waitUntil(logApiFailure(env.DB, 'ga4', ga4EventName, 'FETCH_ERROR', err?.message || String(err), '', JSON.stringify(body))); } if (env.RETRY_QUEUE) { const send = env.RETRY_QUEUE.send({ eventType: ga4EventName, payload, platform: 'ga4' }); if (ctx) ctx.waitUntil(send); else send.catch(() => {}); } return { error: err?.message || String(err) }; } }