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:
- Creates a singleton instance internally
- Fetches configuration from remote API
- Enables features based on config (chat widget, event tracking)
- Starts polling for config changes (30-second interval)
- Auto-stores instance in
window.firstDistro
Parameters:
config.vendorId(string, required): Your vendor IDconfig.apiKey(string, required): Your API key (starts withsk_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
windowis 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 identifiertraits(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 identifiertraits(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
$groupevent 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_idand 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:
- Call
identify()first when user logs in or profile loads - Then call
group()when account context is available - 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 eventsgroup()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
- Getting Started - Set up Customer Insights
- Event Tracking Guide - Track product usage events