rename lib/conversion to lib/capi; fix exports

This commit is contained in:
Elijah Duffy
2025-12-21 21:12:24 -08:00
parent b6e0830209
commit 90a2063ad3
7 changed files with 3 additions and 4 deletions

94
src/lib/capi/client.ts Normal file
View File

@@ -0,0 +1,94 @@
import { getFbpFbc } from '../metapixel/fbc.ts';
import type { TrackingManager } from '$lib/tracking.svelte';
import {
capiErrorBodySchema,
capiResponseBodySchema,
type CAPIErrorBody,
type CAPIRequestBody,
type CAPIResponseBody
} from './handle.ts';
import type { CAPICustomerInfoParams, CAPIEvent } from './event.ts';
import * as v from 'valibot';
import { dev } from '$app/environment';
/**
* Client abstracts HTTP communication with a spectator server endpoint for
* sending conversion events to Meta Conversions API.
*/
export class CAPIClient {
private _href: string;
private _trackingManager: TrackingManager;
/**
* Creates a new CAPIClient.
*
* @param serverHref - The spectator server endpoint URL.
* @param trackingManager - The tracking manager instance, used for consent status.
*/
constructor(serverHref: string, trackingManager: TrackingManager) {
this._href = serverHref;
this._trackingManager = trackingManager;
}
/**
* Sends CAPIEvents to the server endpoint.
* @param events - The array of CAPIEvents to send.
* @returns A promise that resolves to the server response.
* @throws Will throw an error if input or response shape validation fails.
*/
async sendEvents(events: CAPIEvent[]): Promise<CAPIResponseBody | CAPIErrorBody> {
// Respond with an empty response if consent is not given
if (!this._trackingManager.haveUserConsent()) {
if (dev) {
console.warn(`[CAPIClient] Consent not given. Skipping sending ${events.length} event(s).`);
}
return {
pixelID: '',
fbTraceID: '',
receivedEvents: 0,
processedEvents: 0,
messages: []
};
}
// Attempt to build enriched user data
const { fbp, fbc } = getFbpFbc();
const enrichedUserData: Partial<CAPICustomerInfoParams> = { fbp, fbc };
// Build request body
const body: CAPIRequestBody = {
events: events.map((e) => {
e.enrichUserData(enrichedUserData);
return e.toObject();
})
};
v.parse(v.object({ events: v.array(v.any()) }), body); // Validate body shape
const response = await fetch(this._href, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
});
const json = await response.json();
if (response.ok) {
const parsed = v.parse(capiResponseBodySchema, json);
return parsed as CAPIResponseBody;
} else {
const parsed = v.parse(capiErrorBodySchema, json);
return parsed as CAPIErrorBody;
}
}
/**
* Shorthand for sending a single CAPIEvent to the server endpoint.
* @param event - The CAPIEvent to send.
* @returns A promise that resolves to the server response.
* @throws Will throw an error if input or response shape validation fails.
*/
async trackEvent(event: CAPIEvent): Promise<CAPIResponseBody | CAPIErrorBody> {
return this.sendEvents([event]);
}
}