import { json, type RequestHandler } from '@sveltejs/kit'; import { ConversionControl } from './control.ts'; import type { ConversionErrorResponseBody, ConversionEventParams, ConversionRequestBody, ConversionUserData } from '$lib/types/conversion.js'; import { StatusCodes } from 'http-status-codes'; const getEventIP = (request: Request, getClientAddress: () => string) => { return ( request.headers.get('x-forwarded-for') || request.headers.get('cf-connecting-ip') || request.headers.get('x-real-ip') || request.headers.get('x-client-ip') || request.headers.get('x-cluster-client-ip') || request.headers.get('x-original-forwarded-for') || request.headers.get('forwarded-for') || request.headers.get('forwarded') || getClientAddress() ); }; export const createConversionRequestHandler: (control: ConversionControl) => RequestHandler = ( control ) => { const handle: RequestHandler = async ({ request, getClientAddress }) => { try { const body = (await request.json()) as ConversionRequestBody; // Build user data with IP and user agent const ip = getEventIP(request, getClientAddress); const ua = request.headers.get('user-agent'); const userData: ConversionUserData = { ...body.user, ip, ua: ua ?? body.user?.ua ?? undefined }; // Build custom data with UTM params if applicable let customData: ConversionEventParams = body.customData ?? {}; if (body.eventName === 'PageView' && body.utms) { // For PageView events, automatically include UTM params if provided customData = { ...customData, ...body.utms }; } // Send the event via the control const response = await control.trackEvent( body.eventName, { eventID: body.eventID, eventSourceURL: body.eventSourceURL, actionSource: 'website', userData }, customData ); return json(response, { status: StatusCodes.OK }); } catch (e) { return json( { error: e instanceof Error ? e.message : String(e) } as ConversionErrorResponseBody, { status: StatusCodes.INTERNAL_SERVER_ERROR } ); } }; return handle; };