swetrix
v4.4.0
Published
The JavaScript analytics client for Swetrix Analytics
Downloads
18,848
Maintainers
Readme
Swetrix Tracking Script
Privacy-first, lightweight analytics tracking library for Swetrix. Tracks page views, custom events, errors, feature flags, and A/B experiments — all without cookies or invading user privacy.
Installation
npm / yarn / pnpm
npm install swetrixCDN
<script src="https://swetrix.org/swetrix.js" defer></script>Quick Start
ES Modules
import { init, trackViews, trackErrors } from 'swetrix'
init('YOUR_PROJECT_ID')
trackViews()
trackErrors()CDN / Script Tag
<script src="https://swetrix.org/swetrix.js" defer></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
swetrix.init('YOUR_PROJECT_ID')
swetrix.trackViews()
swetrix.trackErrors()
})
</script>API
init(projectId, options?)
Initialise the library. Must be called before any other method.
init('YOUR_PROJECT_ID', {
apiURL: 'https://api.swetrix.com/log',
devMode: false,
disabled: false,
respectDNT: false,
profileId: 'user-123',
preloadSessionReplay: false,
})| Option | Description | Default |
|---|---|---|
| apiURL | API endpoint. Change this if you're self-hosting. | 'https://api.swetrix.com/log' |
| devMode | When true, localhost events are sent to the server. | false |
| disabled | When true, no data is sent. Useful for dev environments. | false |
| respectDNT | When true, disables tracking for users with Do Not Track enabled. | false |
| profileId | Profile ID for long-term user tracking (MAU/DAU). | undefined |
| preloadSessionReplay | Preload the session replay recorder after init(). Recording only starts after startSessionReplay(). | undefined |
trackViews(options?)
Automatically tracks page views, including navigation changes in SPAs. Returns a Promise<{ stop() }>.
const { stop } = await trackViews({
hash: false,
search: false,
unique: false,
heartbeatOnBackground: false,
callback: undefined,
})
// Stop tracking when needed
stop()| Option | Description | Default |
|---|---|---|
| hash | Track hash-based routing (e.g. /#/path). | false |
| search | Track search/query-based routing (e.g. /path?query). | false |
| unique | Only count unique page views per session. | false |
| heartbeatOnBackground | Send heartbeat when the tab is not active. | false |
| callback | A function to edit or prevent pageview payloads. Return false to block, true to send as-is, or return a modified payload object. | undefined |
track(event)
Track custom events (e.g. button clicks, sign-ups).
track({
ev: 'signup',
unique: true,
meta: { plan: 'pro', source: 'landing' },
profileId: 'user-123',
})| Option | Description | Default |
|---|---|---|
| ev | Event name (max 256 chars). | required |
| unique | Only count once per session. | false |
| meta | Key-value metadata (max 20 keys, 1000 chars total). | {} |
| profileId | Optional profile ID. Overrides the global profileId for this event. | undefined |
trackErrors(options?)
Automatically captures client-side errors. Returns { stop() }.
const { stop } = trackErrors({
sampleRate: 1,
callback: undefined,
})| Option | Description | Default |
|---|---|---|
| sampleRate | Fraction of errors to send (0 to 1). | 1 |
| callback | Edit or prevent error payloads. Return false to block. | undefined |
trackError(payload)
Manually report an error.
trackError({
name: 'PaymentError',
message: 'Card declined',
meta: { gateway: 'stripe' },
})pageview(options)
Manually track a single page view (useful for custom routing).
pageview({
payload: { pg: '/checkout', lc: 'en-US' },
unique: true,
})Feature Flags
// Get all flags. Results are cached for 5 minutes.
const flags = await getFeatureFlags({ profileId: 'user-123' })
// Force a fresh fetch
const freshFlags = await getFeatureFlags({ profileId: 'user-123' }, true)
// Get a single flag. The third argument is an optional fallback value.
const enabled = await getFeatureFlag('dark-mode', { profileId: 'user-123' })
const enabledWithFallback = await getFeatureFlag('dark-mode', { profileId: 'user-123' }, false)
// Clear the shared feature flag / experiment cache
clearFeatureFlagsCache()A/B Experiments
// Get all running experiment assignments. Results are cached for 5 minutes.
const experiments = await getExperiments({ profileId: 'user-123' })
// Force a fresh fetch
const freshExperiments = await getExperiments({ profileId: 'user-123' }, true)
// Get a specific experiment variant. The third argument is an optional fallback variant.
const variant = await getExperiment('checkout-redesign-experiment-id', { profileId: 'user-123' })
const variantWithFallback = await getExperiment('checkout-redesign-experiment-id', { profileId: 'user-123' }, 'control')
// Clear the shared feature flag / experiment cache
clearExperimentsCache()startSessionReplay(options?)
Start recording a session replay. Session replays use total privacy by default, which masks text and inputs and blocks media/canvas capture unless you explicitly choose another mode.
If you use the npm package, rrweb is dynamically imported from your installed dependencies only when the recorder is preloaded or started. If you use the CDN/script-tag build, the standalone replay recorder is loaded with an async script tag.
const replay = await startSessionReplay({
privacy: 'total',
maskAllText: true,
sampleRate: 0.25,
maxDurationMs: 10 * 60 * 1000,
idleTimeoutMs: 2 * 60 * 1000,
maxBytesPerChunk: 512 * 1024,
})
// Stop or flush manually when needed
await replay.flush()
await replay.stop()| Option | Description | Default |
|---|---|---|
| privacy | Privacy mode: total, normal, or none. | 'total' |
| maskAllText | Mask all non-input text with asterisks. Defaults to true when privacy is total, otherwise false. | privacy-based |
| sampleRate | Fraction of sessions to record (0 to 1). | 1 |
| maxDurationMs | Stop recording after this duration. | undefined |
| idleTimeoutMs | Stop recording after this much visitor inactivity. | undefined |
| flushIntervalMs | Upload buffered replay events at this interval. | 5000 |
| maxEventsPerChunk | Upload once this many events are buffered. | 100 |
| maxBytesPerChunk | Upload once buffered replay events reach this approximate byte size. | 524288 |
| maxBytesPerEvent | Drop a single replay event if it is larger than this many bytes. | 5242880 |
| recordIframes | Allow iframe elements to be captured. Iframes are blocked by default to reduce replay size and avoid recording embedded third-party content. | false |
| rrweb | Additional rrweb record options. | undefined |
To mask text while keeping media less restricted than total privacy, combine normal privacy with maskAllText:
await startSessionReplay({
privacy: 'normal',
maskAllText: true,
})By default, Swetrix blocks iframe elements from replay snapshots. If you own the iframe content and need it in the replay, opt in explicitly:
await startSessionReplay({
privacy: 'normal',
recordIframes: true,
})Cross-origin iframe recording also requires rrweb's cross-origin iframe support and should only be enabled for domains you control:
await startSessionReplay({
recordIframes: true,
rrweb: {
recordCrossOriginIframes: true,
},
})Session & Profile IDs
const profileId = await getProfileId()
const sessionId = await getSessionId()These are useful for revenue attribution with payment providers like Paddle.
Self-Hosting
If you're running a self-hosted Swetrix API instance, point the apiURL to your server:
init('YOUR_PROJECT_ID', {
apiURL: 'https://your-api.example.com/log',
})Documentation
Full reference and guides are available at docs.swetrix.com.
Contributing
Contributions are welcome — feel free to open an issue or submit a pull request.
License
MIT
