Web SDK
@cohorly/web is the browser SDK. It is built on the shared core with localStorage persistence, a fetch/sendBeacon transport (so events survive tab close and navigation), and optional SPA pageview autotracking.
Install
bashpnpm add @cohorly/web# or: npm install @cohorly/web
Initialize
Call init() once at your app entry point. Pass your project token so
events route to the right project; apiHost defaults to the hosted Cohorly
API.
tsimport { init } from "@cohorly/web";const cohorly = init({token: "YOUR_PROJECT_TOKEN",trackPageviews: true,});
After init() has run once, you can import the named cohorly singleton
anywhere instead of threading the returned instance through your app:
tsimport { cohorly } from "@cohorly/web";cohorly.track("Button Clicked", { button: "checkout" });
Options
| Option | Type | Notes |
|---|---|---|
apiHost | string | Optional. Ingestion API base URL. Defaults to the hosted Cohorly endpoint. |
token | string | Project token stamped on every event and request. |
trackPageviews | boolean | Autotrack SPA pageviews. |
flushIntervalMs | number | How often the queue auto-flushes. |
batchSize | number | Flush once this many events are queued. |
superProperties | object | Properties merged into every event from the start. |
debug | boolean | Verbose logging. |
Track events
track(event, properties?) queues an event. The SDK automatically merges in
$browser, $os, $current_url, and screen size, plus distinct_id,
time, $insert_id, and $lib.
tscohorly.track("Signed Up", { plan: "pro" });cohorly.track("Item Added", { sku: "A-100", price: 29 });
Identify
identify(id) switches the current user to a known id. The switch (distinct
id, persisted state) is applied synchronously, before any network call, so a
slow or offline request never delays it. On the first call after being
anonymous it then sends an /alias request so pre-login and post-login
activity link into one profile; the request is best effort - a failure
neither throws nor blocks, since the server also links the anonymous and
identified ids implicitly from the next event that carries both (see
Identity).
tsawait cohorly.identify("user_123");
Use reset() on logout to generate a fresh anonymous id. This matters on
shared devices: without it, the next person to use the device inherits the
previous person's anonymous history.
tscohorly.reset();
Super properties
Super properties are merged into every subsequent event. Register and
unregister them with register() / unregister(). Event-level properties
override super properties of the same key.
tscohorly.register({ app_version: "1.2.3", plan: "free" });cohorly.track("Viewed Page"); // includes app_version and plancohorly.unregister("plan");
People profiles
Update the current user's profile through cohorly.people. These map to the
/engage endpoint.
tsawait cohorly.people.set({ name: "Ada Lovelace", plan: "pro" });await cohorly.people.setOnce({ first_seen: Date.now() });await cohorly.people.increment({ logins: 1 });await cohorly.people.unset(["temp_flag"]);await cohorly.people.delete();
Flush and accessors
tsawait cohorly.flush(); // send the queued batch nowconst id = cohorly.getDistinctId();const anon = cohorly.isAnonymous();
The queue is persisted to localStorage, so events survive reloads and are retried on the next flush if a request fails.
Keeping the token out of the bundle
Passing token to init() embeds it in your client JS. If you would rather
not, proxy ingestion server-side with @cohorly/nextjs's
createCohorlyProxy() and omit token here. See the
Next.js SDK.