@gumlethq/event-router-client
v1.0.5
Published
Node.js client library for Event Router Server - Segment.js compatible API
Maintainers
Readme
Event Router Client
A Node.js client library for Event Router Server with a Segment.js-compatible API. Send analytics events with automatic batching, retries, and queue management.
Installation
npm install @gumlet/event-router-clientQuick Start
import { Analytics } from '@gumlet/event-router-client';
// Initialize the client
const analytics = new Analytics({
host: 'http://localhost:3000',
flushAt: 20, // Flush after 20 events
flushInterval: 10000 // Flush every 10 seconds
});
// Identify a user
analytics.identify({
userId: 'user123',
traits: {
email: '[email protected]',
firstName: 'John',
lastName: 'Doe'
}
});
// Track an event
analytics.track({
userId: 'user123',
event: 'Button Clicked',
properties: {
buttonId: 'signup-cta',
page: 'homepage'
}
});
// Gracefully shutdown when your app exits
process.on('SIGTERM', async () => {
await analytics.shutdown();
process.exit(0);
});API Reference
Constructor
const analytics = new Analytics({
host: string; // Required: Event router server URL
flushAt?: number; // Optional: Flush after N events (default: 20)
flushInterval?: number; // Optional: Flush every N ms (default: 10000)
maxQueueSize?: number; // Optional: Max queue size (default: 1000)
timeout?: number; // Optional: Request timeout (default: 10000)
retryCount?: number; // Optional: Retry attempts (default: 3)
enable?: boolean; // Optional: Enable/disable tracking (default: true)
});Methods
identify()
Identify a user with traits. You must provide either userId or anonymousId.
analytics.identify(payload: {
userId?: string;
anonymousId?: string;
traits?: Traits;
context?: Context;
timestamp?: Date;
integrations?: Record<string, boolean>;
}, callback?: Callback): void;Example:
// Identify with userId
analytics.identify({
userId: 'user123',
traits: {
email: '[email protected]',
firstName: 'John',
lastName: 'Doe',
company: 'Acme Inc',
phone: '+1234567890',
createdAt: new Date()
}
});
// Identify anonymous user
analytics.identify({
anonymousId: '48d213bb-95c3-4f8d-af97-86b2b404dcfe',
traits: {
friends: 42
}
});
// With context
analytics.identify({
userId: 'user123',
traits: { email: '[email protected]' },
context: {
ip: '192.168.1.1',
userAgent: 'Mozilla/5.0...'
},
timestamp: new Date()
});
// With callback
analytics.identify({
userId: 'user123',
traits: { email: '[email protected]' }
}, (err) => {
if (err) console.error('Failed to identify:', err);
});track()
Track a custom event. You must provide either userId or anonymousId, and an event name.
analytics.track(payload: {
userId?: string;
anonymousId?: string;
event: string;
properties?: Properties;
context?: Context;
timestamp?: Date;
integrations?: Record<string, boolean>;
}, callback?: Callback): void;Example:
// Track with userId
analytics.track({
userId: 'user123',
event: 'Item Purchased',
properties: {
revenue: 39.95,
shippingMethod: '2-day',
productId: 'prod_123'
}
});
// Track anonymous event
analytics.track({
anonymousId: '48d213bb-95c3-4f8d-af97-86b2b404dcfe',
event: 'Item Purchased',
properties: {
revenue: 39.95
}
});
// With context
analytics.track({
userId: 'user123',
event: 'Button Clicked',
properties: { buttonId: 'signup' },
context: {
page: '/landing'
},
timestamp: new Date()
});
// With callback
analytics.track({
userId: 'user123',
event: 'Video Watched',
properties: { videoId: 'abc' }
}, (err) => {
if (err) console.error('Failed to track:', err);
});
// With selective integrations
analytics.track({
userId: 'user123',
event: 'Membership Upgraded',
integrations: {
'All': false,
'Vero': true,
'Google Analytics': false
}
});page()
Track a page view. You must provide either userId or anonymousId.
analytics.page(payload: {
userId?: string;
anonymousId?: string;
category?: string;
name?: string;
properties?: Properties;
context?: Context;
timestamp?: Date;
integrations?: Record<string, boolean>;
}, callback?: Callback): void;Example:
// Simple page view
analytics.page({
userId: 'user123'
});
// With name
analytics.page({
userId: 'user123',
name: 'Home'
});
// With category and name
analytics.page({
userId: 'user123',
category: 'Docs',
name: 'Node.js Library',
properties: {
url: 'https://segment.com/docs/connections/sources/catalog/libraries/node',
path: '/docs/connections/sources/catalog/libraries/node/',
title: 'Node.js Library - Segment',
referrer: 'https://github.com/segmentio/analytics-node'
}
});screen()
Track a screen view (for mobile apps). You must provide either userId or anonymousId.
analytics.screen(payload: {
userId?: string;
anonymousId?: string;
category?: string;
name?: string;
properties?: Properties;
context?: Context;
timestamp?: Date;
integrations?: Record<string, boolean>;
}, callback?: Callback): void;Example:
analytics.screen({
userId: 'user123',
category: 'Main',
name: 'Home Screen',
properties: {
screenWidth: 1920,
screenHeight: 1080
}
});group()
Associate a user with a group or company. You must provide either userId or anonymousId, and a groupId.
analytics.group(payload: {
userId?: string;
anonymousId?: string;
groupId: string;
traits?: Traits;
context?: Context;
timestamp?: Date;
integrations?: Record<string, boolean>;
}, callback?: Callback): void;Example:
analytics.group({
userId: 'user123',
groupId: '56',
traits: {
name: 'Initech',
description: 'Accounting Software',
employees: 100,
plan: 'Enterprise'
}
});alias()
Link two user identities together. This allows you to associate an anonymous user with an identified user.
analytics.alias(payload: {
userId: string;
previousId: string;
context?: Context;
timestamp?: Date;
integrations?: Record<string, boolean>;
}, callback?: Callback): void;Example:
// Link anonymous ID to user ID after signup/login
analytics.alias({
previousId: 'anonymous_user',
userId: '[email protected]'
});flush()
Manually flush all queued events.
await analytics.flush();Example:
// Flush before critical operations
await analytics.flush();shutdown()
Gracefully shutdown the client (flushes queue and stops timers).
await analytics.shutdown();Example:
// Clean shutdown
process.on('SIGTERM', async () => {
await analytics.shutdown();
process.exit(0);
});enable() / disable()
Enable or disable event tracking.
analytics.disable(); // Stop tracking
analytics.enable(); // Resume trackingExample:
// Disable in development
if (process.env.NODE_ENV === 'development') {
analytics.disable();
}Advanced Usage
Custom Context
Add custom context to all events:
analytics.identify({
userId: 'user123',
traits: {
email: '[email protected]'
},
context: {
app: {
name: 'My App',
version: '1.0.0'
},
device: {
type: 'mobile',
model: 'iPhone 13'
},
ip: '192.168.1.1',
userAgent: 'Mozilla/5.0...'
}
});Error Handling
analytics.track({
userId: 'user123',
event: 'Purchase',
properties: { amount: 100 }
}, (err) => {
if (err) {
console.error('Failed to track purchase:', err);
// Implement fallback logic
} else {
console.log('Purchase tracked successfully');
}
});Batching Configuration
const analytics = new Analytics({
host: 'http://localhost:3000',
flushAt: 50, // Batch 50 events before sending
flushInterval: 30000, // Or flush every 30 seconds
maxQueueSize: 5000 // Max 5000 events in queue
});High-Volume Applications
const analytics = new Analytics({
host: 'http://localhost:3000',
flushAt: 100, // Larger batches
flushInterval: 5000, // Flush more frequently
timeout: 30000, // Longer timeout for large batches
retryCount: 5 // More retries
});Disable in Tests
const analytics = new Analytics({
host: 'http://localhost:3000',
enable: process.env.NODE_ENV !== 'test'
});TypeScript Support
The library is written in TypeScript and provides full type definitions:
import { Analytics, Traits, Properties, Options } from '@gumlet/event-router-client';
const traits: Traits = {
email: '[email protected]',
firstName: 'John',
lastName: 'Doe'
};
const properties: Properties = {
productId: 'prod_123',
price: 99.99
};
const options: Options = {
timestamp: new Date(),
context: {
ip: '192.168.1.1'
}
};Complete Example
import { Analytics } from '@gumlet/event-router-client';
// Initialize
const analytics = new Analytics({
host: process.env.EVENT_ROUTER_URL || 'http://localhost:3000',
flushAt: 20,
flushInterval: 10000
});
// User signup flow
async function handleSignup(user: any) {
// Identify the user
analytics.identify({
userId: user.id,
traits: {
email: user.email,
firstName: user.firstName,
lastName: user.lastName,
createdAt: new Date()
}
});
// Track signup event
analytics.track({
userId: user.id,
event: 'User Signed Up',
properties: {
method: 'email',
plan: user.plan
}
});
// Associate with company
if (user.companyId) {
analytics.group({
userId: user.id,
groupId: user.companyId,
traits: {
name: user.companyName,
plan: user.companyPlan
}
});
}
// Flush immediately for important events
await analytics.flush();
}
// User activity tracking
function trackPageView(userId: string, pageName: string) {
analytics.page({
userId,
name: pageName,
properties: {
url: window.location.href,
referrer: document.referrer,
path: window.location.pathname
}
});
}
// Anonymous user tracking
function trackAnonymousEvent(anonymousId: string, event: string, properties: any) {
analytics.track({
anonymousId,
event,
properties
});
}
// Alias anonymous user after signup
function linkUserIdentities(anonymousId: string, userId: string) {
analytics.alias({
previousId: anonymousId,
userId
});
}
// Graceful shutdown
process.on('SIGTERM', async () => {
console.log('Shutting down...');
await analytics.shutdown();
process.exit(0);
});Comparison with Segment.js
This library provides an API very similar to Segment.js:
| Feature | Segment.js | Event Router Client | |---------|-----------|---------------------| | identify() | ✅ | ✅ | | track() | ✅ | ✅ | | page() | ✅ | ✅ | | screen() | ✅ | ✅ | | group() | ✅ | ✅ | | alias() | ✅ | ✅ | | Auto batching | ✅ | ✅ | | Auto retries | ✅ | ✅ | | TypeScript | ✅ | ✅ | | Callbacks | ✅ | ✅ | | Context | ✅ | ✅ |
License
MIT
