75 lines
2.1 KiB
TypeScript
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;
|
|
};
|