Cloudflare Workers
The adscapi dispatch path uses only fetch and WebCrypto — no Node built-ins — so it runs natively on Workers. Pass secrets from env bindings; never from the request body.
Install
shell
npm install adscapi # wrangler.toml — bind platform secrets via `wrangler secret put`
Worker handler
On Workers, process.env is empty. Pass the Worker env bag into createAdscapi(env) so platform tokens resolve from your bindings.
ts
// src/index.ts
import { createAdscapi } from 'adscapi';
import type { AdscapiSecrets } from 'adscapi';
export interface Env {
// Platform tokens + an optional shared auth gate for callers
RELAY_AUTH_TOKEN?: string;
META_CAPI_TOKEN?: string;
META_PIXEL_ID?: string;
// …every other secret listed by `npx adscapi platforms`
[key: string]: string | undefined;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== 'POST') {
return new Response('method not allowed', { status: 405 });
}
// Optional: gate the endpoint so only your backends can call it
if (env.RELAY_AUTH_TOKEN) {
const auth = request.headers.get('authorization') ?? '';
if (auth !== `Bearer ${env.RELAY_AUTH_TOKEN}`) {
return new Response('unauthorized', { status: 401 });
}
}
const body = await request.json<{
name: string;
value?: number;
currency?: string;
email?: string;
consent?: { adUserData: boolean; adPersonalization: boolean };
}>();
// Pass the Worker env as the secrets bag — process.env is empty on Workers.
const ads = createAdscapi(env as AdscapiSecrets);
const results = await ads.conversions.track({
name: body.name,
value: body.value,
currency: body.currency ?? 'USD',
user: body.email ? { email: body.email } : undefined,
consent: {
adUserData: body.consent?.adUserData === true,
adPersonalization: body.consent?.adPersonalization === true,
},
});
return Response.json({ results });
},
};Secrets
shell
# Put each platform secret on the Worker (never in the request body) npx wrangler secret put META_CAPI_TOKEN npx wrangler secret put META_PIXEL_ID npx wrangler secret put RELAY_AUTH_TOKEN # optional caller auth npx wrangler deploy
Prefer npx adscapi platforms for the exact secret names, then wrangler secret put each one.
Dry-run & OAuth
ts
// Dry-run via query string
const dryRun = new URL(request.url).searchParams.has('dryRun');
await ads.conversions.track(event, { dryRun });
// OAuth platforms: supply a fresh token per call without storing it in env
const ads = createAdscapi(env as AdscapiSecrets, {
getToken: async (platform) => {
// look up / refresh from KV, return access_token or undefined
},
});Hosted relay
Don’t want to write a Worker? The package ships a ready-made relay in worker/ with POST /track, optional queue-backed /track/async, and auth. See the any-language guide or the worker README.