@kelpi/sdk
v1.0.0
Published
Official JavaScript/TypeScript SDK for Kelpi - Customer engagement automation
Maintainers
Readme
Kelpi SDK
Official JavaScript/TypeScript SDK for Kelpi - Customer engagement automation.
Installation
# npm
npm install @kelpi/sdk
# yarn
yarn add @kelpi/sdk
# pnpm
pnpm add @kelpi/sdkRequirements
- Node.js 16+ (for server-side usage)
- Modern browser with localStorage support (for client-side usage)
Quick Start
import { Kelpi } from '@kelpi/sdk';
// Create SDK instance
const kelpi = new Kelpi();
// Initialize the SDK (do this once, typically in your app's entry point)
kelpi.init({
apiKey: 'klp_pk_your_public_key',
});
// Identify a user (required before tracking)
await kelpi.identify('user_12345', {
email: '[email protected]',
name: 'John Doe',
plan: 'premium',
});
// Track events
kelpi.track('button_clicked', {
button_id: 'signup_cta',
page: '/pricing',
});
// The SDK automatically batches and sends events
// You can force send immediately with:
await kelpi.flush();API Reference
new Kelpi(options?)
Create a new SDK instance.
import { Kelpi } from '@kelpi/sdk';
const kelpi = new Kelpi();
// or with custom storage
const kelpi = new Kelpi({ storage: customStorageAdapter });init(config)
Initialize the SDK. Must be called before any other methods.
interface KelpiSDKConfig {
apiKey: string; // Required. Your public API key (klp_pk_*)
apiHost?: string; // Optional. API host (default: https://api.kelpi.ai)
flushInterval?: number; // Optional. Batch flush interval in ms (default: 10000)
maxQueueSize?: number; // Optional. Max events before auto-flush (default: 100, max: 1000)
debug?: boolean; // Optional. Enable console logging (default: false)
customLogger?: CustomLogger; // Optional. Custom logger function
}
kelpi.init({
apiKey: 'klp_pk_your_public_key',
debug: true, // Enable for development
});identify(userId, traits?)
Identify a user. Must be called before tracking events.
// Basic identification
await kelpi.identify('user_12345');
// With traits
await kelpi.identify('user_12345', {
email: '[email protected]',
name: 'John Doe',
plan: 'premium',
company: 'Acme Inc',
});Parameters:
userId(string, required) - Unique identifier for the user (max 256 chars)traits(object, optional) - User properties to associate
Returns: Promise<IdentifyResponse> with { success, contact_id, is_new }
Throws: KelpiError on failure
track(event, properties?)
Track an event for the identified user. Events are queued and sent in batches.
// Basic event
kelpi.track('page_viewed');
// With properties
kelpi.track('item_purchased', {
item_id: 'SKU-123',
price: 29.99,
currency: 'USD',
});Parameters:
event(string, required) - Event name (max 256 chars, cannot start with$)properties(object, optional) - Event properties
Returns: void (events are queued, not sent immediately)
Throws:
KelpiErrorwith codeNOT_INITIALIZEDif SDK not initializedKelpiErrorwith codeNOT_IDENTIFIEDif user not identifiedKelpiErrorwith codeINVALID_EVENT_NAMEif event name is invalid
setTraits(traits)
Update user traits by merging with existing traits.
await kelpi.setTraits({
plan: 'enterprise',
last_purchase: '2024-01-15',
});Parameters:
traits(object, required) - Traits to merge with existing traits
Returns: Promise<void>
reset()
Clear the current user identity (for logout). Device ID is preserved.
// Flushes pending events and clears identity
kelpi.reset();flush()
Force send all queued events immediately.
// Useful before navigation or logout
await kelpi.flush();Returns: Promise<void>
getUserId()
Get the current user ID.
const userId = kelpi.getUserId();
// Returns: 'user_12345' or nullisIdentified()
Check if a user is currently identified.
if (kelpi.isIdentified()) {
kelpi.track('some_event');
}getContactId()
Get the Kelpi internal contact ID.
const contactId = kelpi.getContactId();
// Returns: '550e8400-e29b-41d4-a716-446655440000' or nullgetDeviceId()
Get the device ID (persisted across sessions).
const deviceId = kelpi.getDeviceId();
// Returns: UUID string or null if not initializedError Handling
The SDK throws KelpiError instances with specific error codes:
import { Kelpi, KelpiError, ErrorCodes } from '@kelpi/sdk';
const kelpi = new Kelpi();
try {
kelpi.track('event_name');
} catch (error) {
if (error instanceof KelpiError) {
switch (error.code) {
case ErrorCodes.NOT_INITIALIZED:
console.error('SDK not initialized. Call kelpi.init() first.');
break;
case ErrorCodes.NOT_IDENTIFIED:
console.error('User not identified. Call kelpi.identify() first.');
break;
case ErrorCodes.INVALID_EVENT_NAME:
console.error('Invalid event name:', error.message);
break;
default:
console.error('Kelpi error:', error.message);
}
}
}Error Codes
| Code | Description | Retryable |
|------|-------------|-----------|
| NOT_INITIALIZED | SDK not initialized | No |
| NOT_IDENTIFIED | User not identified before tracking | No |
| INVALID_CONFIG | Invalid configuration provided | No |
| INVALID_EVENT_NAME | Event name is empty or starts with $ | No |
| ALREADY_INITIALIZED | SDK already initialized | No |
| RATE_LIMITED | API rate limit exceeded | Yes |
| NETWORK_ERROR | Network request failed | Yes |
| SERVER_ERROR | Server returned 5xx error | Yes |
Automatic Retries
The SDK automatically retries failed API requests:
- Rate limited (429): Respects
Retry-Afterheader - Network errors: Retries with exponential backoff
- Server errors (5xx): Retries with exponential backoff
- Client errors (4xx): No retry (indicates a bug in your code)
TypeScript Support
The SDK is written in TypeScript and provides full type definitions.
import {
Kelpi,
KelpiError,
ErrorCodes,
type KelpiSDKConfig,
type UserTraits,
type IdentifyResponse,
} from '@kelpi/sdk';
// All methods are fully typed
const config: KelpiSDKConfig = {
apiKey: 'klp_pk_...',
debug: true,
};
const kelpi = new Kelpi();
kelpi.init(config);
// Type-safe traits
const traits: UserTraits = {
email: '[email protected]',
name: 'John Doe',
customField: 'value', // Custom properties allowed
};
await kelpi.identify('user_123', traits);Exported Types
// Configuration
interface KelpiSDKConfig {
apiKey: string;
apiHost?: string;
flushInterval?: number;
maxQueueSize?: number;
debug?: boolean;
customLogger?: CustomLogger;
}
// User traits (string-keyed record)
interface UserTraits {
email?: string;
name?: string;
[key: string]: unknown;
}
// Identify response
interface IdentifyResponse {
success: boolean;
contact_id: string;
is_new: boolean;
}
// Error class
class KelpiError extends Error {
code: string;
retryable: boolean;
}
// Error codes
const ErrorCodes = {
NOT_INITIALIZED: 'not_initialized',
NOT_IDENTIFIED: 'not_identified',
INVALID_CONFIG: 'invalid_config',
INVALID_EVENT_NAME: 'invalid_event_name',
ALREADY_INITIALIZED: 'already_initialized',
RATE_LIMITED: 'rate_limited',
NETWORK_ERROR: 'network_error',
SERVER_ERROR: 'server_error',
} as const;Storage
The SDK automatically selects the appropriate storage:
- Browser: Uses
localStoragefor persistence - Node.js/SSR: Uses in-memory storage
You can provide a custom storage adapter:
import { Kelpi, type StorageAdapter } from '@kelpi/sdk';
const customStorage: StorageAdapter = {
get: (key) => { /* ... */ },
set: (key, value) => { /* ... */ },
remove: (key) => { /* ... */ },
getJSON: (key) => { /* ... */ },
setJSON: (key, value) => { /* ... */ },
};
const kelpi = new Kelpi({ storage: customStorage });License
MIT
