Core SDK
@cohorly/core is the transport-agnostic client that every JavaScript SDK is built on. It owns the event queue, batching, flush scheduling, identity, and super properties. Storage and network transport are injected, so the package has zero DOM, Node, or React Native dependencies. Use it directly only when you are building a new platform SDK; most apps should reach for a platform package instead.
Install
bashpnpm add @cohorly/core
Quickstart
You supply a CohorlyStorage (persist the queue and identity) and a CohorlyTransport (send batches over the network). The package ships fetchTransport for environments with a global fetch.
typescriptimport { CohorlyClient, fetchTransport } from "@cohorly/core";import type { CohorlyStorage } from "@cohorly/core";const storage: CohorlyStorage = {get: (key) => myStore.get(key) ?? null,set: (key, value) => myStore.set(key, value),remove: (key) => myStore.delete(key),};const client = new CohorlyClient({// apiHost defaults to the hosted Cohorly API; set it to target a different deployment.// Project token: attached to every event's properties and to every// /engage and /alias body so the server routes data to your project.token: "YOUR_PROJECT_TOKEN",storage,transport: fetchTransport, // or a custom CohorlyTransport});client.track("Signed Up", { plan: "pro" });await client.identify("user_123");await client.people.set({ name: "Ada Lovelace" });
API
| Member | Notes |
|---|---|
new CohorlyClient(options) | Options: storage is required, apiHost defaults to the hosted API; transport, token, flushIntervalMs, batchSize, debug, lib, maxQueueSize (1000), maxRetryDelayMs (10 min) are optional. |
track(event, properties?) | Enqueues an event and auto-flushes once batchSize is reached. Returns the TrackedEvent. |
identify(id) | Switches the distinct id; sends /alias the first time if the user was previously anonymous. |
reset() | Assigns a fresh anonymous distinct id. |
register(props) / unregister(key) | Super properties merged into every event. |
people.set / setOnce / increment / unset / delete | Profile updates sent to /engage. |
flush(transportOverride?) | Manually flush the queue; always forces an attempt. |
getDistinctId / isAnonymous / getApiHost | Accessors. |
stop() | Stops the auto-flush timer. |
Delivery and retries
Non-2xx responses surface as a TransportError (status plus optional retryAfterMs parsed from Retry-After) that drives the retry contract: 429 and 5xx or network errors keep the queue and enter exponential backoff (base 2s, doubling, 10 min cap, +/-20% jitter, honoring Retry-After); 413 halves the effective batch size and retries smaller without dropping events; 400 drops the rejected batch; 401 keeps the queue at max backoff. A success resets the failure counter. The persisted queue is bounded at maxQueueSize (oldest dropped first).
Building for the browser, React, Next.js, or React Native? Use the platform packages (@cohorly/web, @cohorly/react, @cohorly/nextjs, @cohorly/react-native), which wire up storage and transport for you.