Files
spectator/src/lib/conversion/server.ts

75 lines
2.1 KiB
TypeScript

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;
};