JavaScript

JavaScript (Browser) SDK

Official Klime SDK for JavaScript (Browser). Track events, identify users, and associate them with groups.

Installation

npm install @klime/browser

Quick Start

import { KlimeClient } from "@klime/browser";

const client = new KlimeClient({
  writeKey: "your-write-key",
});

// Identify a user
client.identify("user_123", {
  email: "user@example.com",
  name: "Stefan",
});

// Track an event
client.track(
  "Button Clicked",
  {
    buttonName: "Sign up",
    plan: "pro",
  },
  { userId: "user_123" }
);

// Associate user with a group and set group traits
client.group(
  "org_456",
  { name: "Acme Inc", plan: "enterprise" },
  { userId: "user_123" }
);

// Or just link the user to a group (if traits are already set)
client.group("org_456", null, { userId: "user_123" });

Installation Prompt

Copy and paste this prompt into Cursor, Copilot, or your favorite AI editor to integrate Klime:

Integrate Klime for customer analytics. Klime tracks user activity to identify which customers are healthy vs at risk of churning.

ANALYTICS MODES (determine which applies):
- Companies & Teams: Your customers are companies with multiple team members (SaaS, enterprise tools)
  → Use identify() + group() + track()
- Individual Customers: Your customers are individuals with private accounts (consumer apps, creator tools)
  → Use identify() + track() only (no group() needed)

KEY CONCEPTS:
- Every track() call requires either userId OR groupId (no anonymous events)
- Use groupId alone for org-level events (webhooks, cron jobs, system metrics)
- group() links a user to a company AND sets company traits (only for Companies & Teams mode)
- Order doesn't matter - events before identify/group still get attributed correctly

BEST PRACTICES:
- Initialize client ONCE (singleton, React context, or module-level)
- Write key is safe to embed in client code (it's write-only, not a secret)
- Events auto-flush on page unload - no manual shutdown needed

Install: npm install @klime/browser

import { KlimeClient } from "@klime/browser";

const client = new KlimeClient({ writeKey: "YOUR_WRITE_KEY" });

// Identify users at signup/login:
client.identify("usr_abc123", { email: "jane@acme.com", name: "Jane Smith" });

// Track key activities:
client.track("Report Generated", { report_type: "revenue" }, { userId: "usr_abc123" });
client.track("Feature Used", { feature: "export", format: "csv" }, { userId: "usr_abc123" });
client.track("Teammate Invited", { role: "member" }, { userId: "usr_abc123" });

// If Companies & Teams mode: link user to their company and set company traits
client.group("org_456", { name: "Acme Inc", plan: "enterprise" }, { userId: "usr_abc123" });

INTEGRATION WORKFLOW:

Phase 1: Discover
Explore the codebase to understand:
1. What framework is used? (React, Vue, Svelte, vanilla JS, etc.)
2. Where is user identity available? (e.g., useUser().id, useAuth().user.id, session.user.id, store.user)
3. Is this Companies & Teams or Individual Customers?
   - Look for: organization, workspace, tenant, team, account in URL/context/store → Companies & Teams (use group())
   - No company/org concept, just individual users → Individual Customers (skip group())
4. Where do core user actions happen? (onClick handlers, form submissions, hooks, event handlers)
5. Is there existing analytics? (search: segment, posthog, mixpanel, amplitude, .track)
Match your integration style to the framework's conventions.

Phase 2: Instrument
Add these calls using idiomatic patterns for the framework:
- Initialize client once (React: context provider, Vue: plugin, Svelte: store, vanilla: module singleton)
- identify() in auth/login success handler
- group() when user-org association is established (Companies & Teams mode only)
- track() for key user actions (see below)

WHAT TO TRACK:
Active engagement (primary): feature usage, resource creation, collaboration, completing flows
Session signals (secondary): dashboard access, app opened - distinguishes "low usage" from "churned"
Do NOT track: every click, page navigations, component renders

Phase 3: Verify
Confirm: client initialized, identify/group/track calls added

Phase 4: Summarize
Report what you added:
- Files modified and what was added to each
- Events being tracked (list event names and what triggers them)
- How userId is obtained (and groupId if Companies & Teams mode)
- Any assumptions made or questions

API Reference

Constructor

new KlimeClient(config: {
  writeKey: string;              // Required: Your Klime write key
  endpoint?: string;              // Optional: API endpoint (default: https://i.klime.com)
  flushInterval?: number;        // Optional: Milliseconds between flushes (default: 2000)
  maxBatchSize?: number;         // Optional: Max events per batch (default: 20, max: 100)
  maxQueueSize?: number;         // Optional: Max queued events (default: 1000)
  retryMaxAttempts?: number;     // Optional: Max retry attempts (default: 5)
  retryInitialDelay?: number;    // Optional: Initial retry delay in ms (default: 1000)
  autoFlushOnUnload?: boolean;   // Optional: Auto-flush on page unload (default: true)
})

Methods

track(event: string, properties?: object, options?: { userId?, groupId? })

Track an event. Events can be attributed in two ways:

  • User events: Provide userId to track user activity (most common)
  • Group events: Provide groupId without userId for organization-level events
// User event (most common)
client.track(
  "Button Clicked",
  {
    buttonName: "Sign up",
    plan: "pro",
  },
  { userId: "user_123" }
);

// Group event (for webhooks, cron jobs, system events)
client.track(
  "Events Received",
  {
    count: 100,
    source: "webhook",
  },
  { groupId: "org_456" }
);

Note: The groupId option can also be combined with userId for multi-tenant scenarios where you need to specify which organization context a user event occurred in.

identify(userId: string, traits?: object)

Identify a user with traits.

client.identify("user_123", {
  email: "user@example.com",
  name: "Stefan",
});

group(groupId: string, traits?: object, options?: { userId? })

Associate a user with a group and/or set group traits.

// Associate user with a group and set group traits (most common)
client.group(
  "org_456",
  { name: "Acme Inc", plan: "enterprise" },
  { userId: "user_123" }
);

// Just link a user to a group (traits already set or not needed)
client.group("org_456", null, { userId: "user_123" });

// Just update group traits (e.g., from a webhook or background job)
client.group("org_456", { plan: "enterprise", employeeCount: 50 });

flush(): Promise<void>

Manually flush queued events immediately.

await client.flush();

shutdown(): Promise<void>

Gracefully shutdown the client, flushing remaining events.

await client.shutdown();

Features

  • Automatic Batching: Events are automatically batched and sent every 2 seconds or when the batch size reaches 20 events
  • Automatic Retries: Failed requests are automatically retried with exponential backoff
  • Browser Context: Automatically captures userAgent, locale, and timezone
  • Page Unload Handling: Automatically flushes events when the page is about to unload
  • Zero Dependencies: Uses only native browser APIs
  • Universal Module Support: Works with ESM and CommonJS (no transpilePackages needed)

Performance

When you call track(), identify(), or group(), the SDK:

  1. Adds the event to an in-memory queue (microseconds)
  2. Returns immediately without waiting for network I/O

Events are sent to Klime's servers asynchronously via the browser's fetch API. This means:

  • No network waiting: HTTP requests happen asynchronously in the background
  • No UI blocking: Tracking calls don't freeze the browser or delay user interactions
  • Automatic batching: Events are queued and sent in batches (default: every 2 seconds or 20 events)
// This returns immediately - no HTTP request is made here
client.track("Button Clicked", { button: "signup" }, { userId: "user_123" });

// Your code continues without waiting
navigate("/dashboard");

The only blocking operation is await flush(), which waits for all queued events to be sent. The SDK automatically flushes on page unload, so explicit flush() calls are rarely needed.

Configuration

Default Values

  • flushInterval: 2000ms
  • maxBatchSize: 20 events
  • maxQueueSize: 1000 events
  • retryMaxAttempts: 5 attempts
  • retryInitialDelay: 1000ms
  • autoFlushOnUnload: true

Error Handling

The SDK automatically handles:

  • Transient errors (429, 503, network failures): Retries with exponential backoff
  • Permanent errors (400, 401): Logs error and drops event
  • Rate limiting: Respects Retry-After header