Skip to content
trakoo
Esc
navigateopen⌘Jpreview
On this page

Proxy

Send browser events through your own endpoint, then forward them to server providers.

The Proxy sends browser events through an endpoint you control, then forwards them to your server providers. Because the request goes to your own domain, it bypasses ad-blockers, and your server can enrich or filter events before they reach a vendor.

The Proxy is not an analytics service. It is the transport between client analytics and server analytics: the browser batches events to your API, and your API replays them through whatever server providers you configure.

When to use it

  • You want first-party delivery so ad-blockers and tracking-prevention features don’t drop browser events.
  • You need to add server-side context (authenticated user, geography, feature flags) before events reach a vendor.
  • You use a server provider that needs the incoming request, such as Pirsch, which reads headers to derive page views.
  • You want provider API keys to stay on the server instead of shipping in your client bundle.

If none of these apply, send events straight to a client provider — the Proxy adds an extra hop you don’t need.

Installation

The Proxy ships with trakoo. There is no extra package to install. You do install the server providers you forward to (for example posthog-node for PostHog); Pirsch and EmitKit need no additional package.

Client-side usage

Add ProxyProvider to your client analytics and point it at the endpoint that will receive events. Events are buffered and flushed in batches.

import { createClientAnalytics } from 'trakoo/client';
import { ProxyProvider } from 'trakoo/providers/client';
import type { AppEvents } from './events';

export const analytics = createClientAnalytics<AppEvents>({
  providers: [
    new ProxyProvider({
      endpoint: '/api/events',
      batch: { size: 10, interval: 5000 }
    })
  ]
});

analytics.track('button_clicked', { buttonId: 'signup-cta' });

Server-side usage

Your endpoint receives the batched events and replays them through server analytics. You have two options.

Let trakoo own the whole route with createProxyHandler:

import { createServerAnalytics } from 'trakoo/server';
import {
  EmitKitServerProvider,
  createProxyHandler
} from 'trakoo/providers/server';

const serverAnalytics = createServerAnalytics({
  providers: [
    new EmitKitServerProvider({
      apiKey: process.env.EMITKIT_API_KEY!,
      channelName: 'product-events'
    })
  ]
});

export const POST = createProxyHandler(serverAnalytics);

Or keep your own handler and call ingestProxyEvents when you need to run auth, enrichment, or logging around ingestion:

import { createServerAnalytics } from 'trakoo/server';
import {
  PirschServerProvider,
  ingestProxyEvents
} from 'trakoo/providers/server';

const serverAnalytics = createServerAnalytics({
  providers: [
    new PirschServerProvider({
      hostname: 'example.com',
      clientSecret: process.env.PIRSCH_SECRET!
    })
  ]
});

export async function POST(req: Request) {
  await ingestProxyEvents(req, serverAnalytics);
  return new Response('OK');
}

How events flow

Browser → ProxyProvider (batches) → your /api/events → server providers

The browser collects events and flushes a batch once batch.size is reached or batch.interval elapses, whichever comes first. Your endpoint hands the batch to server analytics, which fans it out to each configured server provider — the same routing rules from Providers apply on the server side.

Configuration

ProxyProvider takes the endpoint and an optional batching policy.

PropType
endpointstring

URL that receives batched events, usually a route on your own domain.

Typestring
batch?object

Controls how events are buffered before they are sent.

Typeobject

The batch object accepts:

PropType
size?number

Number of events to buffer before flushing a batch.

Typenumber
interval?number

Milliseconds to wait before flushing a partial batch.

Typenumber

Resources

Was this page helpful?