swetrix 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  [![NPM](https://img.shields.io/npm/v/swetrix)](https://www.npmjs.com/package/swetrix)
8
8
  [![Package size](https://img.shields.io/bundlephobia/minzip/swetrix)](https://bundlephobia.com/package/swetrix)
9
- [![JSDelivr hits](https://data.jsdelivr.com/v1/package/npm/swetrix/badge?style=rounded)](https://data.jsdelivr.com/v1/package/npm/swetrix/badge/stats)
9
+ [![JSDelivr hits](https://data.jsdelivr.com/v1/package/npm/swetrix/badge?style=rounded)](https://www.jsdelivr.com/package/npm/swetrix)
10
10
  [![Contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/swetrix/swetrix-js/issues)
11
11
 
12
12
  # Swetrix Tracking Script
@@ -65,6 +65,7 @@ init('YOUR_PROJECT_ID', {
65
65
  disabled: false,
66
66
  respectDNT: false,
67
67
  profileId: 'user-123',
68
+ preloadSessionReplay: false,
68
69
  })
69
70
  ```
70
71
 
@@ -75,6 +76,7 @@ init('YOUR_PROJECT_ID', {
75
76
  | `disabled` | When `true`, no data is sent. Useful for dev environments. | `false` |
76
77
  | `respectDNT` | When `true`, disables tracking for users with Do Not Track enabled. | `false` |
77
78
  | `profileId` | Profile ID for long-term user tracking (MAU/DAU). | `undefined` |
79
+ | `preloadSessionReplay` | Preload the session replay recorder after `init()`. Recording only starts after `startSessionReplay()`. | `undefined` |
78
80
 
79
81
  ### `trackViews(options?)`
80
82
 
@@ -110,6 +112,7 @@ track({
110
112
  ev: 'signup',
111
113
  unique: true,
112
114
  meta: { plan: 'pro', source: 'landing' },
115
+ profileId: 'user-123',
113
116
  })
114
117
  ```
115
118
 
@@ -118,6 +121,7 @@ track({
118
121
  | `ev` | Event name (max 256 chars). | **required** |
119
122
  | `unique` | Only count once per session. | `false` |
120
123
  | `meta` | Key-value metadata (max 20 keys, 1000 chars total). | `{}` |
124
+ | `profileId` | Optional profile ID. Overrides the global `profileId` for this event. | `undefined` |
121
125
 
122
126
  ### `trackErrors(options?)`
123
127
 
@@ -161,29 +165,66 @@ pageview({
161
165
  ### Feature Flags
162
166
 
163
167
  ```javascript
164
- // Get all flags
168
+ // Get all flags. Results are cached for 5 minutes.
165
169
  const flags = await getFeatureFlags({ profileId: 'user-123' })
166
170
 
167
- // Get a single flag
171
+ // Force a fresh fetch
172
+ const freshFlags = await getFeatureFlags({ profileId: 'user-123' }, true)
173
+
174
+ // Get a single flag. The third argument is an optional fallback value.
168
175
  const enabled = await getFeatureFlag('dark-mode', { profileId: 'user-123' })
176
+ const enabledWithFallback = await getFeatureFlag('dark-mode', { profileId: 'user-123' }, false)
169
177
 
170
- // Clear cache
178
+ // Clear the shared feature flag / experiment cache
171
179
  clearFeatureFlagsCache()
172
180
  ```
173
181
 
174
182
  ### A/B Experiments
175
183
 
176
184
  ```javascript
177
- // Get all experiments
185
+ // Get all running experiment assignments. Results are cached for 5 minutes.
178
186
  const experiments = await getExperiments({ profileId: 'user-123' })
179
187
 
180
- // Get a specific experiment variant
181
- const variant = await getExperiment('checkout-redesign', { profileId: 'user-123' })
188
+ // Force a fresh fetch
189
+ const freshExperiments = await getExperiments({ profileId: 'user-123' }, true)
182
190
 
183
- // Clear cache
191
+ // Get a specific experiment variant. The third argument is an optional fallback variant.
192
+ const variant = await getExperiment('checkout-redesign-experiment-id', { profileId: 'user-123' })
193
+ const variantWithFallback = await getExperiment('checkout-redesign-experiment-id', { profileId: 'user-123' }, 'control')
194
+
195
+ // Clear the shared feature flag / experiment cache
184
196
  clearExperimentsCache()
185
197
  ```
186
198
 
199
+ ### `startSessionReplay(options?)`
200
+
201
+ 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.
202
+
203
+ 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.
204
+
205
+ ```javascript
206
+ const replay = await startSessionReplay({
207
+ privacy: 'total',
208
+ sampleRate: 0.25,
209
+ maxDurationMs: 10 * 60 * 1000,
210
+ idleTimeoutMs: 2 * 60 * 1000,
211
+ })
212
+
213
+ // Stop or flush manually when needed
214
+ await replay.flush()
215
+ await replay.stop()
216
+ ```
217
+
218
+ | Option | Description | Default |
219
+ |---|---|---|
220
+ | `privacy` | Privacy mode: `total`, `normal`, or `none`. | `'total'` |
221
+ | `sampleRate` | Fraction of sessions to record (`0` to `1`). | `1` |
222
+ | `maxDurationMs` | Stop recording after this duration. | `undefined` |
223
+ | `idleTimeoutMs` | Stop recording after this much visitor inactivity. | `undefined` |
224
+ | `flushIntervalMs` | Upload buffered replay events at this interval. | `5000` |
225
+ | `maxEventsPerChunk` | Upload once this many events are buffered. | `100` |
226
+ | `rrweb` | Additional rrweb record options. | `undefined` |
227
+
187
228
  ### Session & Profile IDs
188
229
 
189
230
  ```javascript
@@ -1,3 +1,22 @@
1
+ type RrwebEvent = Record<string, unknown>;
2
+ type RrwebEmit = (event: RrwebEvent) => void;
3
+ interface RrwebRecordOptions {
4
+ emit?: RrwebEmit;
5
+ [key: string]: unknown;
6
+ }
7
+ interface RrwebGlobal {
8
+ record?: (options: RrwebRecordOptions) => (() => void) | undefined;
9
+ Replayer?: unknown;
10
+ }
11
+ type SessionReplayPreloadOption = boolean | {
12
+ rrwebUrl?: string;
13
+ };
14
+ declare global {
15
+ interface Window {
16
+ rrweb?: RrwebGlobal;
17
+ __SWETRIX_RRWEB_LOADING__?: Promise<void>;
18
+ }
19
+ }
1
20
  export interface LibOptions {
2
21
  /**
3
22
  * When set to `true`, localhost events will be sent to server.
@@ -19,6 +38,10 @@ export interface LibOptions {
19
38
  * If set, it will be used for all pageviews and events unless overridden per-call.
20
39
  */
21
40
  profileId?: string;
41
+ /**
42
+ * Preload session replay recorder code. Recording only starts after calling startSessionReplay().
43
+ */
44
+ preloadSessionReplay?: SessionReplayPreloadOption;
22
45
  }
23
46
  export interface TrackEventOptions {
24
47
  /** The custom event name. */
@@ -117,6 +140,21 @@ export interface ErrorActions {
117
140
  /** Stops the tracking of errors. */
118
141
  stop: () => void;
119
142
  }
143
+ declare const SESSION_REPLAY_PRIVACY_VALUES: readonly ["total", "normal", "none"];
144
+ export type SessionReplayPrivacy = (typeof SESSION_REPLAY_PRIVACY_VALUES)[number];
145
+ export interface SessionReplayOptions {
146
+ privacy?: SessionReplayPrivacy;
147
+ rrweb?: RrwebRecordOptions;
148
+ flushIntervalMs?: number;
149
+ maxEventsPerChunk?: number;
150
+ sampleRate?: number;
151
+ maxDurationMs?: number;
152
+ idleTimeoutMs?: number;
153
+ }
154
+ export interface SessionReplayActions {
155
+ stop: () => Promise<void>;
156
+ flush: () => Promise<void>;
157
+ }
120
158
  export interface PageData {
121
159
  /** Current URL path. */
122
160
  path: string;
@@ -169,6 +207,7 @@ export interface PageViewsOptions {
169
207
  export declare const defaultActions: {
170
208
  stop(): void;
171
209
  };
210
+ export declare const defaultSessionReplayActions: SessionReplayActions;
172
211
  export declare class Lib {
173
212
  private projectID;
174
213
  private options?;
@@ -179,6 +218,9 @@ export declare class Lib {
179
218
  private activePage;
180
219
  private errorListenerExists;
181
220
  private cachedData;
221
+ private rrwebLoader;
222
+ private sessionReplayActions;
223
+ private sessionReplayInitPromise;
182
224
  constructor(projectID: string, options?: LibOptions | undefined);
183
225
  captureError(event: ErrorEvent): void;
184
226
  trackErrors(options?: ErrorOptions): ErrorActions;
@@ -187,10 +229,10 @@ export declare class Lib {
187
229
  trackPageViews(options?: PageViewsOptions): PageActions;
188
230
  getPerformanceStats(): IPerfPayload | {};
189
231
  /**
190
- * Fetches all feature flags and experiments for the project.
191
- * Results are cached for 5 minutes by default.
232
+ * Fetches all feature flags for the project.
233
+ * Results are cached for 5 minutes by default and share a cache with experiments.
192
234
  *
193
- * @param options - Options for evaluating feature flags.
235
+ * @param options - Options for evaluating feature flags (`profileId` only).
194
236
  * @param forceRefresh - If true, bypasses the cache and fetches fresh data.
195
237
  * @returns A promise that resolves to a record of flag keys to boolean values.
196
238
  */
@@ -203,8 +245,8 @@ export declare class Lib {
203
245
  * Gets the value of a single feature flag.
204
246
  *
205
247
  * @param key - The feature flag key.
206
- * @param options - Options for evaluating the feature flag.
207
- * @param defaultValue - Default value to return if the flag is not found. Defaults to false.
248
+ * @param options - Options for evaluating the feature flag (`profileId` only).
249
+ * @param defaultValue - Optional default value to return if the flag is not found. Defaults to false.
208
250
  * @returns A promise that resolves to the boolean value of the flag.
209
251
  */
210
252
  getFeatureFlag(key: string, options?: FeatureFlagsOptions, defaultValue?: boolean): Promise<boolean>;
@@ -213,16 +255,16 @@ export declare class Lib {
213
255
  */
214
256
  clearFeatureFlagsCache(): void;
215
257
  /**
216
- * Fetches all A/B test experiments for the project.
258
+ * Fetches variant assignments for running A/B test experiments returned by feature flag evaluation.
217
259
  * Results are cached for 5 minutes by default (shared cache with feature flags).
218
260
  *
219
- * @param options - Options for evaluating experiments.
261
+ * @param options - Options for evaluating experiments (`profileId` only).
220
262
  * @param forceRefresh - If true, bypasses the cache and fetches fresh data.
221
263
  * @returns A promise that resolves to a record of experiment IDs to variant keys.
222
264
  *
223
265
  * @example
224
266
  * ```typescript
225
- * const experiments = await getExperiments()
267
+ * const experiments = await getExperiments({ profileId: 'user-123' })
226
268
  * // experiments = { 'exp-123': 'variant-a', 'exp-456': 'control' }
227
269
  * ```
228
270
  */
@@ -231,13 +273,16 @@ export declare class Lib {
231
273
  * Gets the variant key for a specific A/B test experiment.
232
274
  *
233
275
  * @param experimentId - The experiment ID.
234
- * @param options - Options for evaluating the experiment.
235
- * @param defaultVariant - Default variant key to return if the experiment is not found. Defaults to null.
276
+ * @param options - Options for evaluating the experiment (`profileId` only).
277
+ * @param defaultVariant - Optional default variant key to return if the experiment is not found. Defaults to null.
236
278
  * @returns A promise that resolves to the variant key assigned to this user, or defaultVariant if not found.
237
279
  *
238
280
  * @example
239
281
  * ```typescript
240
- * const variant = await getExperiment('checkout-redesign')
282
+ * const variant = await getExperiment('checkout-redesign', { profileId: 'user-123' })
283
+ *
284
+ * // Optional fallback variant:
285
+ * const variantWithFallback = await getExperiment('checkout-redesign', undefined, 'control')
241
286
  *
242
287
  * if (variant === 'new-checkout') {
243
288
  * // Show new checkout flow
@@ -298,6 +343,10 @@ export declare class Lib {
298
343
  * ```
299
344
  */
300
345
  getSessionId(): Promise<string | null>;
346
+ startSessionReplay(options?: SessionReplayOptions): Promise<SessionReplayActions>;
347
+ private initialiseSessionReplay;
348
+ private shouldSampleSessionReplay;
349
+ private getSessionReplayPrivacy;
301
350
  /**
302
351
  * Gets the API base URL (without /log suffix).
303
352
  */
@@ -307,6 +356,19 @@ export declare class Lib {
307
356
  private trackPage;
308
357
  submitPageView(payload: Partial<IPageViewPayload>, unique: boolean, perf: IPerfPayload | {}, evokeCallback?: boolean): void;
309
358
  private canTrack;
359
+ private getSessionReplayUrl;
360
+ private getSessionReplayPreloadOption;
361
+ private getDefaultSessionReplayUrl;
362
+ private getTrackerScript;
363
+ private preloadSessionReplay;
364
+ private loadSessionReplayRecorder;
365
+ private loadSessionReplayPackage;
366
+ private loadSessionReplayScript;
367
+ private getSessionReplayRecordOptions;
368
+ private mergeSelectors;
369
+ private createReplayId;
370
+ private sendSessionReplayStart;
371
+ private sendSessionReplayChunk;
310
372
  private sendRequest;
311
373
  }
312
374
  export {};