Skip to content
trakoo
Esc
navigateopen⌘Jpreview
On this page

Visitors

Client-only, privacy-friendly web analytics with optional Stripe revenue attribution.

Visitors.now is a lightweight, privacy-focused web analytics service with built-in Stripe revenue attribution.

When to use it

  • You want page-view analytics that sets no cookies by default.
  • You want to attribute Stripe revenue to individual visitors.
  • You care about GDPR-friendly defaults and built-in bot filtering.

Visitors is client-only. For backend events such as payments or signups you must not lose, pair it with a server provider like PostHog, Bento, or Pirsch.

Installation

No npm package required. VisitorsClientProvider loads the tracking script from the Visitors CDN at runtime.

Client-side usage

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

export const visitorsProvider = new VisitorsClientProvider({
  token: process.env.NEXT_PUBLIC_VISITORS_TOKEN!,
  persist: true // sets data-persist on the script tag
});

export const analytics = createClientAnalytics({
  providers: [visitorsProvider]
});

await analytics.initialize();

Page views

Page views are tracked automatically when the Visitors script loads. Calling analytics.pageView() is optional and produces a debug log only — it sends no duplicate event.

Custom events

analytics.track('button_clicked', {
  button: 'cta',
  page: 'pricing',
  value: 99
});

Property values must be string or number. Object and array values are dropped to match the Visitors API contract.

Identify users

analytics.identify('user-123', {
  email: 'user@example.com',
  name: 'Jane Smith',
  plan: 'pro',
  seats: 5
});

This calls visitors.identify({ id, ...traits }). Non-scalar trait values are filtered out automatically.

Page leave

analytics.pageLeave({ section: 'hero' });

This sends a page_leave custom event via visitors.track().

Server-side usage

Visitors is client-only, so there is no server provider. Track backend events with a server-capable provider such as PostHog, Bento, or Pirsch.

Configuration

PropType
tokenstring

Your Visitors project token from the dashboard.

Typestring
persist?boolean

Sets data-persist on the script tag so a visitor cookie is written. Required for cross-session tracking and Stripe revenue attribution.

Typeboolean
Defaultfalse
debug?boolean

Enable debug logging.

Typeboolean
Defaultfalse
enabled?boolean

Set to false to disable the provider entirely.

Typeboolean
Defaulttrue

Stripe revenue attribution

Visitors.now can attribute Stripe revenue to individual visitors through a fallback chain: checkout metadata, then previous attribution, then email matching.

The Visitors script sets a visitor cookie in the browser (this needs persist: true). You read that cookie, pass it in your Stripe checkout session metadata, and Visitors matches the purchase back to the visitor session.

Identify users when they sign in

This enables the email-based fallback.

analytics.identify('user-123', {
  email: 'user@example.com',
  name: 'Jane Smith'
});

Read the visitor cookie on the client

Send the visitor ID to your server when starting checkout.

const visitorId = visitorsProvider.getVisitorId();

const response = await fetch('/api/create-checkout', {
  method: 'POST',
  body: JSON.stringify({ visitorId, priceId: 'price_xxx' })
});

Pass the visitor ID in the checkout session

import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

export async function POST(req: Request) {
  const { visitorId, priceId } = await req.json();

  const session = await stripe.checkout.sessions.create({
    mode: 'subscription',
    line_items: [{ price: priceId, quantity: 1 }],
    success_url: `${process.env.NEXT_PUBLIC_URL}/success`,
    cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing`,
    metadata: {
      visitor: visitorId ?? ''
    }
  });

  return Response.json({ url: session.url });
}

Provider behaviour reference

Method Behaviour
initialize() Injects the cdn.visitors.now/v.js script; idempotent
track(event, ctx) Calls visitors.track(action, scalarProps)
identify(id, traits) Calls visitors.identify({ id, ...scalarTraits })
pageView() No-op — page views are automatic
pageLeave() Calls visitors.track('page_leave', ...)
reset() No-op — Visitors has no native reset method
getVisitorId() Reads the visitor cookie for Stripe attribution

Privacy

  • No cookies by default — opt in with persist: true.
  • GDPR-friendly — identify() requires explicit EU consent when persist mode is enabled.
  • Bot filtering built in.

Resources

Was this page helpful?