Beacon JavaScript / TypeScript SDK
The Beacon JavaScript / TypeScript SDK provides lightweight, browser-native integration for web applications. Under 6 KB gzipped, it includes automatic page view tracking, session management, and error tracking with full TypeScript definitions.
Installation
Install via npm:
npm install @softagility/beacon-jsThe package ships ESM, CommonJS, and UMD builds:
| Format | Entry |
|---|---|
| ESM | dist/beacon.esm.js |
| CommonJS | dist/beacon.cjs.js |
| UMD (browser) | dist/beacon.umd.js |
| Types | dist/beacon.d.ts |
System Requirements
- Any modern browser (Chrome, Firefox, Safari, Edge)
- Node.js 18 or later (for SSR / Node imports — the SDK falls back to a no-op instance in non-browser environments, but the import itself requires modern Node)
- No runtime dependencies
v3.0.0 (breaking change): The config fields were renamed —
sourceApp→product(v2.0.0) andsourceVersion→productVersion(v3.0.0) — and the wire fieldssource_app→productandsource_version→product_version. Upgrading from 1.x: renamesourceApp→productandsourceVersion→productVersion. Values are unchanged. See the CHANGELOG.
Configuration
import { Beacon } from '@softagility/beacon-js'
const beacon = Beacon.init({
apiKey: 'your-api-key',
product: 'MyWebApp',
productVersion: '1.2.0',
})
beacon.identify('user-123')Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | — | Your Beacon API key (required) |
product | string | — | Your product’s slug as registered in the Beacon dashboard (e.g., "inventory-manager"). Sent as the product field on every event. Must match a registered product or events are rejected with UNRECOGNIZED_PRODUCT. Max 256 chars on the wire. (required) |
productVersion | string | — | Your application’s version string. Max 128 chars on the wire. (required) |
endpoint | string | https://api.beacon.softagility.com | API base URL override |
sessionTimeoutMinutes | number | 30 | Inactivity timeout before session rotates (1-1440) |
autoPageViews | boolean | true | Auto-track page views on route changes |
flushIntervalMs | number | 10000 | Flush interval in milliseconds (1000-300000) |
maxBatchSize | number | 50 | Events per flush batch (1-1000) |
maxQueueSize | number | 5000 | Maximum in-memory queue depth (100-10000) |
maxBreadcrumbs | number | 25 | Breadcrumb ring buffer size (0-200, 0 disables) |
debug | boolean | false | Log SDK actions to console |
Identifying Users
Identify the current user to associate events with an actor:
beacon.identify('user-123')Call identify before or after tracking events. Once set, all subsequent calls use this actor. If not called, the SDK generates an anonymous device ID that persists in localStorage.
Account & License Context
setAccount / setLicense (added in 1.1.0) attach a customer-account ID and / or license ID to every subsequent event, session start, and exception report. Use them for B2B analytics when your application is multi-tenant.
beacon.identify('user-123')
beacon.setAccount('acct_acme') // customer organisation
beacon.setLicense('sub_acme_team_annual') // contract / entitlement
beacon.track('reports', 'report_exported') // event carries both IDsBehaviour:
- Persistence. Values are stored in process memory and applied to every subsequent payload until cleared or
reset()is called. - Validation. 1-256 chars after trim, no whitespace-only, no control characters (including U+2028 / U+2029). Invalid inputs are silently ignored — calls never throw. Validation matches the .NET SDK and the backend ingest validator.
- Clearing.
clearAccount()andclearLicense()each clear only their own field.reset()clears actor, session, account, license, queue, and breadcrumbs. - Per-call payload. When set,
account_id/license_idare included as top-level JSON fields. When unset, the fields are omitted entirely. - No persistence across reloads. Context lives in memory only — a page reload clears it. Call
setAccount/setLicenseagain on the first navigation after login.
beacon.clearAccount()
beacon.clearLicense()
beacon.reset() // clears everything including account / licenseModeling licenses
Prefer per-contract license IDs (one ID shared across every user of a subscription / site / bundle):
beacon.setLicense('sub_acme_team_annual') // recommendedPer-user / per-seat IDs are accepted but make the dashboard’s License Detail page thin. See the Licenses section of the user manual.
Account- and license-level analytics in the Beacon dashboard are gated to Business and Enterprise plans (Trial also during evaluation). Ingestion itself is tier-blind.
Tracking Events
Events are organized by category and name, with optional properties.
Basic Event
beacon.track('ui', 'button_clicked', {
button_name: 'export',
screen: 'dashboard',
})Event Limits
- Category: max 128 characters
- Name: max 256 characters
- Properties: max 20 per event, keys max 64 chars, string values max 256 chars
- Categories starting with
_are reserved and will be ignored
Page View Tracking
Page views are tracked automatically by default. The SDK hooks pushState, replaceState, and popstate to detect URL changes, and emits an initial page view on init() when autoPageViews is enabled. You can also track manually:
beacon.pageView()
// Or with a custom URL and properties
beacon.pageView('/custom-path', { section: 'reports' })Disable auto-tracking with autoPageViews: false in the config.
Error Tracking
Track JavaScript errors with severity levels. Breadcrumbs from recent track() calls are attached automatically.
try {
processOrder(order)
} catch (err) {
beacon.trackError(err, 'non_fatal')
throw err
}Severity options: 'fatal' and 'non_fatal' (default).
Session Management
Sessions are managed automatically based on user activity. A new session starts on the first event. Inactivity is measured as time since the last SDK call that touches event state — track(), pageView(), identify(), etc. After sessionTimeoutMinutes of inactivity, the next event rotates into a fresh session.
The SDK also wires up two browser lifecycle events:
visibilitychange(when the tab becomes hidden) triggers an immediate flush of queued events but does not end the session — the user may return.beforeunload(when the page unloads) ends the active session and flushes remaining events.
Get the current session ID or actor ID:
const sessionId = beacon.getSessionId()
const actorId = beacon.getActorId()Flushing Events
Events are batched and sent on a timer (flushIntervalMs) or when the batch size is reached. On page unload, the SDK uses fetch with keepalive: true to deliver remaining events.
To flush manually:
await beacon.flush()Privacy Controls
The SDK supports opt-out and opt-in for user consent:
// Opt out — stops tracking, clears queue
beacon.optOut()
// Opt back in — resumes tracking
beacon.optIn()Opt-out state persists in localStorage across sessions.
Reset
Clear all state (session, queue, breadcrumbs, actor ID) and generate a new anonymous ID:
beacon.reset()Use this on logout to separate user sessions.
Event Definitions
Register known events for import into the Beacon portal’s allowlist:
beacon.events.define('reports', 'report_exported')
beacon.events.define('ui', 'button_clicked')
const manifest = beacon.events.exportManifest()Destroy
Tear down the SDK instance: clears timers, removes event listeners, clears identity / queue / breadcrumbs / event definitions in-memory state.
beacon.destroy()destroy() does not flush pending events. To deliver them before tearing down, call await beacon.flush() first.
Environment Collection
The SDK automatically collects browser environment data and sends it as a header with each request:
- Browser name and version
- Screen and viewport dimensions
- Language and platform
- Device type (desktop/mobile/tablet)
- Connection type (when available)
No PII is collected.
Singleton Pattern
Beacon.init() returns a singleton. Calling it again returns the existing instance. If the SDK is loaded in a non-browser environment (SSR), it returns a safe no-op instance.
Next Steps
- Getting Started for a general overview
- API Reference for direct HTTP integration
- Verify your first event (User Manual) — confirm ingestion from the Beacon dashboard
- Pricing for plan details