Skip to main content
A client-side singleton that handles device IDs, sessions, and delivery automatically. No user ID needed on track calls. No cookies. No IP addresses. No cross-site tracking. Visitors are identified by a random device UUID stored in localStorage. The SDK collects anonymous device metadata only — you choose what properties to send. See Audit & Privacy for the full privacy model.

Quick start

Events called before configure() are queued and replayed once ready.

Verify it works

Open your browser’s DevTools Network tab and look for a POST request to https://collect.tell.app/v1/events. If you see a 202 response, the SDK is sending data successfully. In development mode, the SDK also logs to the console at debug level.

Script tag (no bundler)

If you don’t use a bundler, load the SDK directly from a CDN. The global build exposes a Tell object on window.
All configuration options, tracking methods, and privacy controls work the same as the npm install — only the loading mechanism differs.

SPA page view tracking

For single-page apps without a framework router, hook into the History API to track navigations:

Pin a version

Replace @latest with a specific version to avoid unexpected changes in production:

Configuration

For local development, point the SDK at your Tell server:

Tracking events

No user ID parameter — the SDK tracks the current user automatically (anonymous until you call identify). For a full explanation of the identity model (device ID, anonymous ID, user ID), see Users & Identity.
For details on each event type and when to use them, see Events & Properties.

Standard event names

Constants cover user lifecycle, revenue, subscriptions, trials, shopping, engagement, and communication events. Custom string names always work too.

Super properties

Properties automatically attached to every track, group, and revenue call:
Event-specific properties override super properties when keys conflict. See Events & Properties for more on property patterns.

Structured logging

Nine severity levels from logEmergency to logTrace. See Logs for the full level reference and when to use each.

Sessions

Sessions are managed automatically. The session ID is persisted to localStorage, so page navigations within the same site continue the same session. A new session starts after 30 minutes of inactivity (configurable via sessionTimeout) or after 24 hours (configurable via maxSessionLength). The SDK also captures UTM parameters from the URL as super properties. For the full session lifecycle model, see Sessions.

Data collected automatically

The browser SDK captures device context on every session. No PII is collected — all fields are anonymous device and browser metadata.
URLs include query strings. If your app puts tokens or sensitive data in URLs (e.g. ?token=abc), use beforeSend or the redact() utility below to strip them before events leave the browser.

Redaction & beforeSend

The beforeSend hook lets you transform or drop events before they’re queued. Return the modified event, or null to drop it entirely.

Drop events from routes

Strip query params from URLs

Remove PII from properties

Scrub log data

User opt-out via beforeSend

redact() utility

For common redaction patterns, use the built-in redact() factory instead of writing beforeSend by hand:
redact() and redactLog() return standard beforeSend functions. You can combine them with your own in an array:
Client-side redaction is your first line of defense. For defense in depth, also configure server-side pipeline redaction to catch anything that slips through.

Error auto-capture

Set captureErrors: true to automatically log uncaught errors and unhandled promise rejections.

What it captures

window.onerror — uncaught exceptions:
  • message — the error message
  • filename — source file URL
  • lineno / colno — line and column number
  • stack — stack trace (when available)
unhandledrejection — unhandled promise rejections:
  • message — the rejection reason (or "Unhandled promise rejection")
  • stack — stack trace (when the reason is an Error)
Both are logged via logError with service "browser" and appear in your Tell logs dashboard.

When to use vs. your own error boundary

captureErrors is a catch-all safety net for errors that escape your application code. If you use React error boundaries or framework error handlers, you may prefer to log to Tell explicitly from those:

Privacy

Opt-out state is persisted to localStorage. Set respectDoNotTrack: true to honor the browser’s Do Not Track setting.

Lifecycle

Error handling

Tracking calls (track, identify, group, revenue, alias) never throw. Validation errors and network failures route through the onError callback:

Retry behavior

On HTTP send failure (5xx or network error), the SDK retries with exponential backoff: 1-second base delay, 1.5x multiplier, 20% jitter, capped at 30 seconds. After maxRetries attempts (default: 5), the batch is dropped and reported via onError. The SDK also checks navigator.onLine before each attempt and skips if the browser reports offline.

Browser-specific features

Bot detection — automatically disables tracking when navigator.webdriver is set or the user agent contains “headless”. Controlled by botDetection (default: true). Page unload — the SDK flushes via navigator.sendBeacon on beforeunload and visibilitychange to minimize data loss. Pre-init queue — events called before configure() are buffered (up to 1,000) and replayed once the SDK is ready.

Configuration reference