Back to Documentation
api

SDK API reference

Complete API reference for the FirstDistro SDK v2.0.

Last Updated: November 22, 2025
SDK Version: 2.0.0 (Static API)

Note: For Customer Insights setup, see the Getting Started guide.

Installation

Quick installation (recommended)

Use token-based installation for zero configuration:

<script src="https://firstdistro.com/sdk/install/fd_your-token-here.js"></script>

Get your token from Dashboard → Settings → SDK Configuration.

Firstdistro class (static api)

The SDK uses a static API pattern - no need to create instances. Call methods directly on the FirstDistro class.

Static methods

firstdistro.init(config: initconfig): promise<void>

Initializes the SDK. This is an async operation that:

  1. Creates a singleton instance internally
  2. Fetches configuration from remote API
  3. Enables features based on config (chat widget, event tracking)
  4. Starts polling for config changes (30-second interval)
  5. Auto-stores instance in window.firstDistro

Parameters:

  • config.vendorId (string, required): Your vendor ID
  • config.apiKey (string, required): Your API key (starts with sk_live_)
  • config.apiUrl (string, optional): API URL override (default: https://firstdistro.com)
  • config.persistence (boolean, optional): Save context to localStorage (default: true)
  • config.debug (boolean, optional): Enable debug logging (default: false)

Example:

await FirstDistro.init({
  vendorId: 'vnd_abc123',
  apiKey: 'sk_live_xyz789',
  apiUrl: 'https://firstdistro.com', // Optional
  persistence: true,                  // Optional
  debug: false                        // Optional
});

Behavior:

  • Can only be called once (subsequent calls are ignored with a warning)
  • SSR-safe (no-op if window is undefined)
  • Returns Promise that resolves when initialization is complete

Errors:

  • Throws if API key is invalid
  • Throws if vendor ID is invalid
  • Throws if network request fails (uses cached config if available)

firstdistro.track(eventname: string, properties?: object): void

Tracks a product usage event.

Parameters:

  • eventName (string, required): Event name (e.g., 'user_signed_up')
  • properties (object, optional): Event properties

Example:

FirstDistro.track('user_signed_up', {
  plan: 'pro',
  source: 'website'
});

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

Behavior:

  • Events are queued and batched (20 per batch)
  • Batches are sent every 5 seconds or on page unload
  • Returns early if tracking is disabled
  • Logs warning if tracking not enabled

firstdistro.identify(userid: string, traits?: object): void

Identifies a user for event tracking.

Parameters:

  • userId (string, required): Unique user identifier
  • traits (object, optional): User properties (name, email, etc.)

Example:

FirstDistro.identify('user-123', {
  name: 'John Doe',
  email: 'john@example.com',
  role: 'admin',
  plan: 'pro'
});

Behavior:

  • User ID is stored and attached to all future events
  • Traits are stored and can be updated
  • Call after user logs in or profile loads

⚠️ Important: Always call identify() before group(). This ensures user identification is properly set up before account grouping. See the correct pattern below.

firstdistro.group(accountid: string, traits?: object): void

Groups a user into an account (organization/company).

Parameters:

  • accountId (string, required): Unique account identifier
  • traits (object, optional): Account properties (name, industry, plan, etc.)

Example:

FirstDistro.group('account-456', {
  name: 'Acme Corp',
  industry: 'SaaS',
  plan: 'enterprise',
  user_count: 25
});

Behavior:

  • Account ID is stored and attached to all future events
  • Traits are stored and can be updated
  • Call when account context is available
  • Tracks a $group event internally

⚠️ Important: Always call identify() before group(). User identification must happen first. Do not put user data (user_id, user_email, etc.) in group() traits - use identify() for user information instead.

⚠️ Customer Insights requirement:

Account grouping is required for Customer Insights to work. While events can be tracked without account_id (they're stored but not processed), Customer Insights requires account grouping to:

  • Calculate health scores
  • Show customers in the dashboard
  • Generate alerts for at-risk customers
  • Aggregate events into customer accounts

What happens without group():

  • Events are stored but not processed for health scoring
  • Customers won't appear in Customer Insights dashboard
  • Health scores won't be calculated

What happens with group():

  • Events include account_id and are processed for health scoring
  • Customers appear in Customer Insights dashboard
  • Health scores are calculated hourly
  • Alerts are generated for at-risk customers

Best practice:

  1. Call identify() first when user logs in or profile loads
  2. Then call group() when account context is available
  3. This ensures both user and account identification are properly set up

firstdistro.reset(): void

Resets user/account context. Useful for logout scenarios.

Example:

FirstDistro.reset();

Behavior:

  • Flushes pending events
  • Clears user/account context
  • Clears localStorage (if persistence enabled)
  • Generates new anonymous ID
  • Does NOT stop polling (SDK remains active)

Type definitions

Initconfig

interface InitConfig {
  vendorId: string;
  apiKey: string;
  apiUrl?: string;        // Optional, defaults to 'https://firstdistro.com'
  persistence?: boolean;  // Optional, default: true
  debug?: boolean;        // Optional, default: false
}

Vendorconfig

interface VendorConfig {
  features: {
    chat: ChatConfig;
    tracking: TrackingConfig;
  };
  version: string;
  updatedAt: string;
}

Chatconfig

interface ChatConfig {
  enabled: boolean;
  theme?: {
    primaryColor: string;
    position: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
  };
  aiPersona?: {
    name: string;
    greeting: string;
  };
}

Trackingconfig

interface TrackingConfig {
  enabled: boolean;
  batchSize?: number; // Default: 20
  flushInterval?: number; // Default: 5000 (milliseconds)
  sampleRate?: number; // Default: 1.0 (0.0 to 1.0)
}

Events

The SDK doesn't expose an event emitter API. Instead, features are controlled via remote configuration.

Error handling

Invalid api key

try {
  await FirstDistro.init({
    vendorId: 'vnd_abc123',
    apiKey: 'sk_live_xyz789'
  });
} catch (error) {
  if (error.message.includes('Invalid API key')) {
    console.error('Check your API key in dashboard');
  }
}

Network errors

The SDK handles network errors gracefully:

  • Uses cached config if available (24-hour expiry)
  • Logs warnings to console
  • Continues with cached config

Tracking disabled

FirstDistro.track('event'); // Logs warning if tracking disabled
// No error thrown, just logs warning

Examples

Basic usage

// Initialize SDK (static API)
await FirstDistro.init({
  vendorId: 'vnd_abc123',
  apiKey: 'sk_live_xyz789'
});

// Track events
FirstDistro.track('page_viewed', { page: '/dashboard' });

With user identification

// Initialize SDK
await FirstDistro.init({
  vendorId: 'vnd_abc123',
  apiKey: 'sk_live_xyz789'
});

// Identify user
FirstDistro.identify('user-123', {
  name: 'John Doe',
  email: 'john@example.com'
});

// Track events (user ID auto-attached)
FirstDistro.track('feature_used', { feature: 'export' });

Correct usage pattern

Always follow this order: identify()group()track()

// Initialize SDK
await FirstDistro.init({
  vendorId: 'vnd_abc123',
  apiKey: 'sk_live_xyz789'
});

// Step 1: Identify the USER first (required)
FirstDistro.identify('user-123', {
  name: 'John Doe',
  email: 'john@example.com',
  role: 'admin'
});

// Step 2: Group to the ACCOUNT (after identify)
FirstDistro.group('account-456', {
  name: 'Acme Corp',
  plan: 'enterprise',
  industry: 'SaaS'
  // ❌ Do NOT put user data here (user_id, user_email, etc.)
  // ✅ User data belongs in identify() traits above
});

// Step 3: Track events (now has both user ID and account ID)
FirstDistro.track('feature_used', { feature: 'export' });

Why this order matters:

  • identify() sets the user context that gets attached to all future events
  • group() sets the account context on top of the user context
  • Both user_id and account_id are automatically included in tracked events
  • This ensures proper data structure in the database

Common mistake to avoid:

// ❌ WRONG: Putting user data in group() traits
FirstDistro.group('account-456', {
  name: 'Acme Corp',
  user_id: 'user-123',      // ❌ Don't do this
  user_email: 'john@...'   // ❌ Don't do this
});

// ✅ CORRECT: Use identify() for user data
FirstDistro.identify('user-123', {
  email: 'john@example.com'  // ✅ User data here
});
FirstDistro.group('account-456', {
  name: 'Acme Corp'  // ✅ Account data here
});

Reset (logout)

// Initialize SDK
await FirstDistro.init({
  vendorId: 'vnd_abc123',
  apiKey: 'sk_live_xyz789'
});

// ... use SDK ...

// Reset when user logs out
FirstDistro.reset(); // Clears user/account context

Global access

After initialization, the SDK instance is available globally:

await FirstDistro.init({ vendorId, apiKey });

// Access instance if needed
const sdk = window.firstDistro;

See also