Skip to content

TypeScript SDK

If you are building something with TypeScript (or plain JS), this is your go-to. Works in Node.js 18+ and browser. For React Native, use @codeserk/forge-stats-react-native instead.

Terminal window
npm install @codeserk/forge-stats

The easiest way to get started. Initialize once - usually at app startup - and call track from anywhere without passing a client around.

import { init, track, trackView } from '@codeserk/forge-stats'
init({ sdk: 'YOUR_SDK_KEY' })
// track a single event - fire-and-forget, errors are logged
track({ type: 'View', name: '/home' })
// with per-call metadata (merged with defaults, takes precedence)
track({ type: 'Click', name: 'cta-button' }, { userId: 'user_123' })
// convenience shorthand for view events
trackView('/home')
trackView('/about', { referrer: 'https://example.com' })

In browser environments, referrer and userAgent are auto-detected. You can set or update default metadata that is merged into every request:

import { setMeta, updateMeta } from '@codeserk/forge-stats'
// replace all default metadata
setMeta({ appName: 'MyApp', appVersionName: '2.3.1' })
// merge into existing defaults
updateMeta({ userId: 'user_123' })

Per-call metadata always takes precedence over defaults.

To track multiple events in one request, use trackMany:

import { trackMany } from '@codeserk/forge-stats'
trackMany({
content: [
{ type: 'View', name: '/home' },
{ type: 'Click', name: 'cta-button', data: { label: 'Get started' } },
],
meta: { userId: 'user_123' },
})

If you need to await the result or handle errors yourself, use sendEvent / sendEvents:

import { sendEvent, sendEvents } from '@codeserk/forge-stats'
await sendEvent({ type: 'View', name: '/home' })
await sendEvents({
content: [{ type: 'View', name: '/home' }],
})

Track errors manually or capture them globally:

import { trackError, sendError, captureGlobalErrors } from '@codeserk/forge-stats'
// fire-and-forget
trackError(new Error('Something went wrong'))
// with options
trackError(new Error('Oops'), { handled: true, data: { page: '/checkout' } })
// await the result
await sendError(new Error('Critical failure'))
// capture all uncaught errors and unhandled rejections globally
captureGlobalErrors()

Prefer to manage the client yourself? Fair enough.

import { Client } from '@codeserk/forge-stats'
const client = new Client({ sdk: 'YOUR_SDK_KEY' })
client.setMeta({ appName: 'MyApp' })
client.trackView('/home')
client.trackError(new Error('Oops'))

By default, errors go to console. Pass your own logger if you want them somewhere else:

init({
baseUrl: 'https://api-events.forge.codeserk.es',
sdk: 'YOUR_SDK_KEY',
logger: { error: (...args) => myLogger.error(...args) },
})

Initializes the singleton. Call this before any send/track calls.

OptionTypeRequiredDescription
baseUrlstringnoDefaults to https://api-events.forge.codeserk.es
sdkstringyesBase64-encoded SDK key from the Forge dashboard
loggerLoggernoDefaults to console
signHashFnSignHashFnnoCustom HMAC-SHA256 implementation. Defaults to Web Crypto

Replaces the default metadata merged into every request.

Merges new metadata into the existing defaults.

Fire-and-forget for a single event. Swallows errors and logs them via the logger.

Fire-and-forget for multiple events in one request.

Convenience shorthand - equivalent to track({ type: 'View', name }, meta).

Fire-and-forget error tracking. Logs send failures via the logger.

Same as track but returns a Promise - use this when you need to await or catch errors.

Same as trackMany but returns a Promise.

Same as trackError but returns a Promise.

Registers global error handlers (browser, Node.js, React Native) to automatically track uncaught errors and unhandled rejections.

Returns the singleton Client instance. Throws if init() has not been called yet.

FieldTypeRequiredDescription
typestringyesEvent type, e.g. 'View'
namestringyesEvent name, e.g. a page path
bucketstringnoGrouping bucket
traceIDstringnoTrace ID for distributed tracing
spanIDstringnoSpan ID for distributed tracing
parentSpanIDstringnoParent span ID
dataEventDatanoArbitrary key/value data

Optional metadata that can be attached to any event. All fields are optional.

FieldTypeDescription
timestampstringISO 8601 timestamp (defaults to server)
timestampEndstringISO 8601 end timestamp
userIdstringApplication user ID
userIpstringClient IP override
userAgentstringUser-Agent string
userTypestringUser type, e.g. 'premium'
userDataEventDataArbitrary user data
userCountrystringCountry code, e.g. 'US'
userRegionstringRegion, e.g. 'California'
userCitystringCity, e.g. 'San Francisco'
deviceTypestringDevice type, e.g. 'mobile'
deviceOSstringOS, e.g. 'iOS'
deviceOSVersionstringOS version, e.g. '17.4.1'
deviceBrowserstringBrowser, e.g. 'Safari'
appNamestringApplication name
appVersionNamestringVersion name, e.g. '2.3.1'
appVersionIDstringVersion ID / build number
referrerstringReferring URL
referrerEventstringReferrer event
referrerUtmMediumstringUTM medium
referrerUtmSourcestringUTM source
referrerUtmCampaignstringUTM campaign
referrerUtmContentstringUTM content
referrerUtmTermstringUTM term
FieldTypeDefaultDescription
handledbooleantrueWhether the error was caught by user code
dataEventDataExtra data attached to the error event
maxFramesnumber3Stack frames used for fingerprinting

EventData is Record<string, string | number | boolean>.