Event tracking guide

Track product usage events to power Customer Insights health scores.

Events show how customers use your product. The browser SDK batches them (about 20 per batch, every 5 seconds or on page unload) and sends them to FirstDistro.

Prerequisites: Install the SDK and call setup() so events link to a user and account. New here? Start with Getting started.

Server events

For backend truth (payments, KYC, syncs, sessions), use @firstdistro/sdk/server with a secret sk_* key. See the Server tab on Install for install → init → track → verify, curl examples, and the recommended server events. In Cursor, server wiring uses @firstdistro/mcp tools get_server_event_template, setup_server_tracking, and check_server_events_flowing. See MCP overview.

When those server events are active in event settings, they can also trigger CS playbooks and Today's 5 cards. See Server risk events and CS playbooks.

What is captured automatically

Once you call setup(), the SDK captures page views. You do not track them manually:

  • A $pageview system event fires on initial page load and on every SPA route change.
  • Auto-capture is identity-gated: page views fire only after setup() has set a userId.
  • Query strings are stripped by default. See Quick start privacy for captureQueryParams and maskUrl.

These page views power Activity, Engagement, and Recency on their own. Do not call track('page_viewed') for navigation. That would duplicate $pageview. Custom track() events below are optional. They feed Activity and Recency, and move Milestones only when the name is a default or custom milestone.

Basic tracking

javascript
FirstDistro.track('feature_used', {
  feature: 'export',
  format: 'pdf',
  page_count: 10,
});

Prefer React hooks from @firstdistro/sdk/react when you use the npm package. See Quick start and React hooks.

Setting user and account context

Use setup() (or useFirstDistroSetup in React) with user id and email. FirstDistro derives the company account from the email domain. Pass account only to override (for example a multi-domain org).

javascript
FirstDistro.setup({
  user: {
    id: 'user-123',
    name: 'Jane Doe',
    email: 'jane@acme.com',
  },
});

Without email in setup: events may lack account_id and will not score for Customer Insights.

With email: account is derived, events aggregate into customer accounts, and health scores update on schedule.

Deprecated: Do not use standalone identify() / group(). Use setup() only.

Handling logout

Call FirstDistro.reset() on logout so the next user does not inherit the previous context from localStorage.

javascript
function handleLogout() {
  if (window.FirstDistro) {
    FirstDistro.reset();
  }
  // ... your logout logic
}

Default milestones the product already recognizes:

  • account_created
  • first_feature_used
  • data_imported
  • user_invited
  • milestone_100_users
  • milestone_1000_users

Useful optional custom events:

  • feature_used with a feature property
  • user_signed_up / user_logged_in when those moments matter for your funnel

Page navigation is captured automatically as $pageview. For backend payments, KYC, and syncs, use the recommended server events.

Event properties

Keep properties small and useful. Avoid PII and secrets.

javascript
FirstDistro.track('feature_used', {
  feature: 'export',
  feature_category: 'data',
  format: 'pdf',
  page_count: 10,
});

After setup(), user_id and account_id are attached automatically.

Event batching

  • Batch size: 20 events
  • Flush interval: about 5 seconds
  • Unload flush: sendBeacon() on page close

You do not manage batching yourself.

Best practices

  1. Track actions that show product value, not every click.
  2. Use snake_case names (feature_used, not click).
  3. Prefer enums and buckets over raw balances or IDs in properties.
  4. Always setup() with email before expecting Customer Insights rows.

Troubleshooting

Events not sending? Check the dashboard, browser console, and network tab. Confirm your install token.

Events delayed? Batching can add a few seconds. Flush on unload is normal.

Customers missing from Customer Insights? Call setup() with user.email. See Getting started.

For more help: hello@firstdistro.com.