Skip to content
trakoo
Esc
navigateopen⌘Jpreview
On this page

Providers

Choose official providers, understand support by environment, and route events intentionally.

Providers translate trakoo events into the APIs of the services you already use. You can start with one provider, add another later, or route specific methods and event names to the tools that should receive them.

Support matrix

Provider Client import Server import Best for
PostHog PostHogClientProvider PostHogServerProvider Product analytics across browser and backend
OpenPanel OpenPanelClientProvider OpenPanelServerProvider Open-source web and product analytics
Bento BentoClientProvider BentoServerProvider Identified lifecycle events and email automation
Pirsch PirschClientProvider PirschServerProvider Privacy-friendly page views and lightweight events
EmitKit EmitKitServerProvider Notifications and activity channels
Visitors VisitorsClientProvider Lightweight web analytics and revenue attribution
Proxy ProxyProvider ingestProxyEvents, createProxyHandler Sending browser events through your own API

Use client providers from trakoo/providers/client and server providers from trakoo/providers/server.

One event, multiple destinations

import { createClientAnalytics } from 'trakoo/client';
import {
  BentoClientProvider,
  PostHogClientProvider,
  VisitorsClientProvider
} from 'trakoo/providers/client';

const analytics = createClientAnalytics({
  providers: [
    new PostHogClientProvider({
      token: import.meta.env.VITE_POSTHOG_KEY
    }),
    {
      provider: new BentoClientProvider({
        siteUuid: import.meta.env.VITE_BENTO_SITE_UUID
      }),
      methods: ['identify', 'track']
    },
    new VisitorsClientProvider({
      token: import.meta.env.VITE_VISITORS_TOKEN,
      persist: true
    })
  ]
});

analytics.track('user_signed_up', {
  email: 'ada@example.com',
  plan: 'pro'
});

The application emits one typed event. trakoo fans it out to each enabled provider.

Routing

Some providers should not receive every call. Bento is usually better for identified user lifecycle events than anonymous page views. EmitKit is usually better for selected events than high-volume click streams. Wrap a provider in a config object to control exactly which methods and events reach it.

const analytics = createClientAnalytics({
  providers: [
    new PostHogClientProvider({ token: import.meta.env.VITE_POSTHOG_KEY }),
    {
      provider: new BentoClientProvider({
        siteUuid: import.meta.env.VITE_BENTO_SITE_UUID
      }),
      methods: ['identify', 'track'],
      eventPatterns: ['user_*', 'checkout_*']
    }
  ]
});

Routing options are part of the shared provider config:

Option Effect
methods Only call these provider methods
exclude Call every method except these
events Only track these exact event names
excludeEvents Track every event except these names
eventPatterns Track events matching glob-style patterns such as newsletter_*

methods wins over exclude when both are set. events, eventPatterns, and excludeEvents are mutually exclusive; the runtime logs a warning and uses the highest-priority option.

Browser-to-server delivery

Use the proxy when browser events should go through your domain before reaching server providers.

import { createClientAnalytics } from 'trakoo/client';
import { ProxyProvider } from 'trakoo/providers/client';

export const analytics = createClientAnalytics({
  providers: [
    new ProxyProvider({
      endpoint: '/api/events',
      batch: { size: 10, interval: 2000 }
    })
  ]
});
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);

Build your own provider

If a service is not built in, implement the AnalyticsProvider interface or extend BaseAnalyticsProvider.

import {
  BaseAnalyticsProvider,
  type BaseEvent,
  type EventContext
} from 'trakoo/client';

export class CustomProvider extends BaseAnalyticsProvider {
  name = 'CustomProvider';

  initialize() {}

  track(event: BaseEvent, context?: EventContext) {
    console.log(event.action, event.properties, context);
  }

  identify(userId: string, traits?: Record<string, unknown>) {}

  pageView(properties?: Record<string, unknown>, context?: EventContext) {}

  reset() {}
}

Learn more about custom providers →

Was this page helpful?