Skip to content
adscapi

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.

Next