@tracelog/lib 2.9.0 → 2.10.0-rc.113.17
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 +161 -728
- package/dist/browser/tracelog-shopify-pixel.iife.js +1 -1
- package/dist/browser/tracelog-shopify-pixel.iife.js.map +1 -1
- package/dist/browser/tracelog.esm.js +1435 -2745
- package/dist/browser/tracelog.esm.js.map +1 -1
- package/dist/browser/tracelog.js +2 -2
- package/dist/browser/tracelog.js.map +1 -1
- package/dist/pixel/index.cjs +2 -2
- package/dist/pixel/index.cjs.map +1 -1
- package/dist/pixel/index.js +2 -2
- package/dist/pixel/index.js.map +1 -1
- package/dist/public-api.cjs +2 -2
- package/dist/public-api.cjs.map +1 -1
- package/dist/public-api.d.mts +200 -774
- package/dist/public-api.d.ts +200 -774
- package/dist/public-api.js +2 -2
- package/dist/public-api.js.map +1 -1
- package/package.json +3 -3
package/dist/public-api.d.mts
CHANGED
|
@@ -78,66 +78,10 @@ interface InitResult {
|
|
|
78
78
|
sessionId: string;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
/**
|
|
82
|
-
* Element configuration for viewport tracking with optional identifiers
|
|
83
|
-
*/
|
|
84
|
-
interface ViewportElement {
|
|
85
|
-
/**
|
|
86
|
-
* CSS selector for the element
|
|
87
|
-
* @example '.hero' | '.cta-button' | '#pricing'
|
|
88
|
-
*/
|
|
89
|
-
selector: string;
|
|
90
|
-
/**
|
|
91
|
-
* Optional unique identifier for analytics
|
|
92
|
-
* Used to distinguish between multiple elements with the same selector
|
|
93
|
-
* @example 'homepage-hero' | 'pricing-cta' | 'customer-testimonials'
|
|
94
|
-
*/
|
|
95
|
-
id?: string;
|
|
96
|
-
/**
|
|
97
|
-
* Optional human-readable name for dashboards and reports
|
|
98
|
-
* @example 'Homepage Hero Banner' | 'Pricing Page CTA' | 'Customer Testimonials Section'
|
|
99
|
-
*/
|
|
100
|
-
name?: string;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Configuration for viewport visibility tracking
|
|
104
|
-
*/
|
|
105
|
-
interface ViewportConfig {
|
|
106
|
-
/**
|
|
107
|
-
* Elements to track with optional identifiers
|
|
108
|
-
* Provides analytics support with business identifiers
|
|
109
|
-
* @example [{ selector: '.hero', id: 'homepage-hero', name: 'Homepage Hero Banner' }]
|
|
110
|
-
*/
|
|
111
|
-
elements: ViewportElement[];
|
|
112
|
-
/**
|
|
113
|
-
* Minimum percentage of element that must be visible (0-1)
|
|
114
|
-
* @default 0.5 (50%)
|
|
115
|
-
*/
|
|
116
|
-
threshold?: number;
|
|
117
|
-
/**
|
|
118
|
-
* Minimum time (ms) element must be visible to count as a view
|
|
119
|
-
* @default 1000 (1 second)
|
|
120
|
-
*/
|
|
121
|
-
minDwellTime?: number;
|
|
122
|
-
/**
|
|
123
|
-
* Cooldown period (ms) before same element can fire visibility event again
|
|
124
|
-
* Prevents repeated events from carousels, sticky headers, and scrolling patterns
|
|
125
|
-
* @default 60000 (60 seconds)
|
|
126
|
-
*/
|
|
127
|
-
cooldownPeriod?: number;
|
|
128
|
-
/**
|
|
129
|
-
* Maximum number of elements to track simultaneously (Phase 3)
|
|
130
|
-
* Prevents memory/server issues with broad selectors
|
|
131
|
-
* @default 100
|
|
132
|
-
*/
|
|
133
|
-
maxTrackedElements?: number;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
81
|
/**
|
|
137
82
|
* Coordinate information from a click event
|
|
138
|
-
* Includes absolute and relative positioning
|
|
139
83
|
*/
|
|
140
|
-
type ClickCoordinates = Pick<ClickData, 'x' | 'y'
|
|
84
|
+
type ClickCoordinates = Pick<ClickData, 'x' | 'y'>;
|
|
141
85
|
/**
|
|
142
86
|
* Web performance metric types tracked by the library
|
|
143
87
|
* - LCP: Largest Contentful Paint
|
|
@@ -145,9 +89,8 @@ type ClickCoordinates = Pick<ClickData, 'x' | 'y' | 'relativeX' | 'relativeY'>;
|
|
|
145
89
|
* - INP: Interaction to Next Paint
|
|
146
90
|
* - FCP: First Contentful Paint
|
|
147
91
|
* - TTFB: Time to First Byte
|
|
148
|
-
* - LONG_TASK: Tasks exceeding 50ms
|
|
149
92
|
*/
|
|
150
|
-
type WebVitalType = 'LCP' | 'CLS' | 'INP' | 'FCP' | 'TTFB'
|
|
93
|
+
type WebVitalType = 'LCP' | 'CLS' | 'INP' | 'FCP' | 'TTFB';
|
|
151
94
|
/**
|
|
152
95
|
* Event type name
|
|
153
96
|
*/
|
|
@@ -169,32 +112,13 @@ declare enum EventType {
|
|
|
169
112
|
/** Performance metrics */
|
|
170
113
|
WEB_VITALS = "web_vitals",
|
|
171
114
|
/** JavaScript errors and rejections */
|
|
172
|
-
ERROR = "error"
|
|
173
|
-
/** Element visibility tracking */
|
|
174
|
-
VIEWPORT_VISIBLE = "viewport_visible"
|
|
115
|
+
ERROR = "error"
|
|
175
116
|
}
|
|
176
117
|
/**
|
|
177
|
-
* Per-session event counts structure for rate limiting
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
* runaway event generation.
|
|
182
|
-
*
|
|
183
|
-
* **Usage**:
|
|
184
|
-
* - Persisted to localStorage: `tlog:{userId}:session_counts:{sessionId}`
|
|
185
|
-
* - Restored on page reload to maintain limits across navigations
|
|
186
|
-
* - Debounced writes for performance (500ms delay)
|
|
187
|
-
*
|
|
188
|
-
* **Limits** (from config.constants.ts):
|
|
189
|
-
* - Total: 1000 events per session
|
|
190
|
-
* - Clicks: 500 per session
|
|
191
|
-
* - Page Views: 100 per session
|
|
192
|
-
* - Custom: 500 per session
|
|
193
|
-
* - Viewport: 200 per session
|
|
194
|
-
* - Scroll: 120 per session
|
|
195
|
-
*
|
|
196
|
-
* @see src/managers/event.manager.ts for implementation
|
|
197
|
-
* @see src/constants/config.constants.ts for limit values
|
|
118
|
+
* Per-session event counts structure for rate limiting.
|
|
119
|
+
*
|
|
120
|
+
* Persisted to localStorage: `tlog:{userId}:session_counts:{sessionId}`
|
|
121
|
+
* Restored on page reload to maintain limits across navigations.
|
|
198
122
|
*/
|
|
199
123
|
interface SessionEventCounts {
|
|
200
124
|
/** Total events across all types */
|
|
@@ -205,8 +129,6 @@ interface SessionEventCounts {
|
|
|
205
129
|
[EventType.PAGE_VIEW]: number;
|
|
206
130
|
/** Custom events count */
|
|
207
131
|
[EventType.CUSTOM]: number;
|
|
208
|
-
/** Viewport visibility events count */
|
|
209
|
-
[EventType.VIEWPORT_VISIBLE]: number;
|
|
210
132
|
/** Scroll events count */
|
|
211
133
|
[EventType.SCROLL]: number;
|
|
212
134
|
/** Index signature for dynamic event type access */
|
|
@@ -240,12 +162,6 @@ interface ScrollData {
|
|
|
240
162
|
direction: ScrollDirection;
|
|
241
163
|
/** CSS selector of the scrolled container */
|
|
242
164
|
container_selector: string;
|
|
243
|
-
/** Whether this is the primary viewport scroll */
|
|
244
|
-
is_primary: boolean;
|
|
245
|
-
/** Scroll velocity in pixels per second */
|
|
246
|
-
velocity: number;
|
|
247
|
-
/** Maximum scroll depth reached during session (0-100) */
|
|
248
|
-
max_depth_reached: number;
|
|
249
165
|
}
|
|
250
166
|
/**
|
|
251
167
|
* Click event data capturing user interaction details
|
|
@@ -255,10 +171,6 @@ interface ClickData {
|
|
|
255
171
|
x: number;
|
|
256
172
|
/** Absolute Y coordinate in viewport (pixels) */
|
|
257
173
|
y: number;
|
|
258
|
-
/** Relative X position within element (0-1) */
|
|
259
|
-
relativeX: number;
|
|
260
|
-
/** Relative Y position within element (0-1) */
|
|
261
|
-
relativeY: number;
|
|
262
174
|
/** Element ID attribute */
|
|
263
175
|
id?: string;
|
|
264
176
|
/** Element class attribute */
|
|
@@ -269,16 +181,6 @@ interface ClickData {
|
|
|
269
181
|
text?: string;
|
|
270
182
|
/** Link href for anchor elements */
|
|
271
183
|
href?: string;
|
|
272
|
-
/** Element title attribute */
|
|
273
|
-
title?: string;
|
|
274
|
-
/** Image alt text for img elements */
|
|
275
|
-
alt?: string;
|
|
276
|
-
/** ARIA role attribute */
|
|
277
|
-
role?: string;
|
|
278
|
-
/** ARIA label attribute */
|
|
279
|
-
ariaLabel?: string;
|
|
280
|
-
/** Custom data attributes (data-*) */
|
|
281
|
-
dataAttributes?: Record<string, string>;
|
|
282
184
|
}
|
|
283
185
|
/**
|
|
284
186
|
* Element data for specialized click tracking
|
|
@@ -301,6 +203,22 @@ interface CustomEventData {
|
|
|
301
203
|
/** Additional event metadata */
|
|
302
204
|
metadata?: Record<string, MetadataType> | Record<string, MetadataType>[];
|
|
303
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* Optional flags for `tracelog.event()`.
|
|
208
|
+
*/
|
|
209
|
+
interface EventOptions {
|
|
210
|
+
/**
|
|
211
|
+
* If `true`, the event queue is flushed via `navigator.sendBeacon()`
|
|
212
|
+
* immediately after this event is tracked. The browser guarantees the
|
|
213
|
+
* request is queued for delivery even if the page is about to unload.
|
|
214
|
+
*
|
|
215
|
+
* Use for high-value events where loss is unacceptable (Purchase, Signup,
|
|
216
|
+
* AddPaymentInfo).
|
|
217
|
+
*
|
|
218
|
+
* @default false
|
|
219
|
+
*/
|
|
220
|
+
critical?: boolean;
|
|
221
|
+
}
|
|
304
222
|
/**
|
|
305
223
|
* Web performance metrics data
|
|
306
224
|
*/
|
|
@@ -318,6 +236,8 @@ interface ErrorData {
|
|
|
318
236
|
type: ErrorType;
|
|
319
237
|
/** Error message text */
|
|
320
238
|
message: string;
|
|
239
|
+
/** Error constructor name (TypeError, ReferenceError, etc.) when available */
|
|
240
|
+
name?: string;
|
|
321
241
|
/** Source file where error occurred */
|
|
322
242
|
filename?: string;
|
|
323
243
|
/** Line number in source file */
|
|
@@ -350,27 +270,6 @@ interface PageViewData {
|
|
|
350
270
|
referrer?: string;
|
|
351
271
|
/** Page title from document */
|
|
352
272
|
title?: string;
|
|
353
|
-
/** URL pathname */
|
|
354
|
-
pathname?: string;
|
|
355
|
-
/** URL query string */
|
|
356
|
-
search?: string;
|
|
357
|
-
/** URL hash fragment */
|
|
358
|
-
hash?: string;
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* Data captured when element becomes visible
|
|
362
|
-
*/
|
|
363
|
-
interface ViewportEventData {
|
|
364
|
-
/** CSS selector that matched the element */
|
|
365
|
-
selector: string;
|
|
366
|
-
/** Optional unique identifier for analytics (if configured) */
|
|
367
|
-
id?: string;
|
|
368
|
-
/** Optional human-readable name (if configured) */
|
|
369
|
-
name?: string;
|
|
370
|
-
/** Actual time (ms) element was visible before event fired */
|
|
371
|
-
dwellTime: number;
|
|
372
|
-
/** Actual visibility ratio when event fired (0-1) */
|
|
373
|
-
visibilityRatio: number;
|
|
374
273
|
}
|
|
375
274
|
/**
|
|
376
275
|
* Complete event data structure
|
|
@@ -401,11 +300,20 @@ interface EventData {
|
|
|
401
300
|
page_view?: PageViewData;
|
|
402
301
|
/** Error details (when type is ERROR) */
|
|
403
302
|
error_data?: ErrorData;
|
|
404
|
-
/** Viewport visibility details (when type is VIEWPORT_VISIBLE) */
|
|
405
|
-
viewport_data?: ViewportEventData;
|
|
406
303
|
/** Campaign tracking parameters */
|
|
407
304
|
utm?: UTM;
|
|
408
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* Internal queue entry: an `EventData` enriched with the session ID frozen at
|
|
308
|
+
* `track()` time. Survives session renewal — when the user is idle past the
|
|
309
|
+
* timeout, `state.sessionId` is nulled but events already in the queue keep
|
|
310
|
+
* their original `_session_id`, so `EventManager.buildBatchesWithIds()` can
|
|
311
|
+
* still attribute them correctly instead of emitting `session_id: null` to the
|
|
312
|
+
* wire.
|
|
313
|
+
*/
|
|
314
|
+
interface QueuedEvent extends EventData {
|
|
315
|
+
_session_id: string;
|
|
316
|
+
}
|
|
409
317
|
|
|
410
318
|
/**
|
|
411
319
|
* Web Vitals filtering mode
|
|
@@ -425,10 +333,6 @@ interface Config {
|
|
|
425
333
|
errorSampling?: number;
|
|
426
334
|
/** Event sampling rate between 0 and 1. @default 1 */
|
|
427
335
|
samplingRate?: number;
|
|
428
|
-
/** CSS selector to manually override primary scroll container detection. */
|
|
429
|
-
primaryScrollSelector?: string;
|
|
430
|
-
/** Viewport visibility tracking configuration. */
|
|
431
|
-
viewport?: ViewportConfig;
|
|
432
336
|
/** Page view throttle duration in milliseconds to prevent rapid navigation spam. @default 1000 */
|
|
433
337
|
pageViewThrottleMs?: number;
|
|
434
338
|
/** Click throttle duration in milliseconds to prevent double-clicks and rapid spam. @default 300 */
|
|
@@ -449,36 +353,28 @@ interface Config {
|
|
|
449
353
|
webVitalsThresholds?: Partial<Record<WebVitalType, number>>;
|
|
450
354
|
/** Interval in milliseconds between event batch sends. @default 10000 (10 seconds) */
|
|
451
355
|
sendIntervalMs?: number;
|
|
452
|
-
/**
|
|
356
|
+
/**
|
|
357
|
+
* Opt-in: when `true`, the event queue is flushed after every SPA navigation
|
|
358
|
+
* (`pushState`, `replaceState`, `popstate`, `hashchange`). Defaults to `false`
|
|
359
|
+
* because per-route flushing can multiply request volume on SPA-heavy apps.
|
|
360
|
+
* @default false
|
|
361
|
+
*/
|
|
362
|
+
flushOnSpaNavigation?: boolean;
|
|
363
|
+
/**
|
|
364
|
+
* If true, the event queue is flushed when `document.hidden` becomes `true`
|
|
365
|
+
* (tab switch, lock screen, app backgrounding). Especially relevant on mobile Safari
|
|
366
|
+
* where `pagehide`/`beforeunload` may not fire reliably.
|
|
367
|
+
* @default true
|
|
368
|
+
*/
|
|
369
|
+
flushOnPageHidden?: boolean;
|
|
370
|
+
/** TraceLog SaaS integration. */
|
|
453
371
|
integrations?: {
|
|
454
|
-
/** TraceLog integration options. */
|
|
455
372
|
tracelog?: {
|
|
456
|
-
/** Required project ID TraceLog SaaS integration. */
|
|
373
|
+
/** Required project ID for TraceLog SaaS integration. */
|
|
457
374
|
projectId: string;
|
|
458
375
|
/** Enable Shopify cart attribute linking for webhook revenue attribution. */
|
|
459
376
|
shopify?: boolean;
|
|
460
377
|
};
|
|
461
|
-
/** Custom integration options. */
|
|
462
|
-
custom?: {
|
|
463
|
-
/** Endpoint for collecting events. */
|
|
464
|
-
collectApiUrl: string;
|
|
465
|
-
/** Allow HTTP URLs (not recommended for production). @default false */
|
|
466
|
-
allowHttp?: boolean;
|
|
467
|
-
/**
|
|
468
|
-
* Static HTTP headers to include in every request.
|
|
469
|
-
* For dynamic headers, use `setCustomHeaders()` instead.
|
|
470
|
-
* @example { 'X-Brand': 'my-brand', 'X-Tenant-Id': 'tenant-123' }
|
|
471
|
-
*/
|
|
472
|
-
headers?: Record<string, string>;
|
|
473
|
-
/**
|
|
474
|
-
* Controls whether cookies and credentials are sent with fetch requests.
|
|
475
|
-
* - `'include'`: Always send cookies (even cross-origin) — required for cookie-based auth
|
|
476
|
-
* - `'same-origin'`: Only send cookies for same-origin requests
|
|
477
|
-
* - `'omit'`: Never send cookies
|
|
478
|
-
* @default 'include'
|
|
479
|
-
*/
|
|
480
|
-
fetchCredentials?: RequestCredentials;
|
|
481
|
-
};
|
|
482
378
|
};
|
|
483
379
|
}
|
|
484
380
|
declare enum SpecialApiUrl {
|
|
@@ -685,90 +581,15 @@ declare enum Mode {
|
|
|
685
581
|
QA = "qa"
|
|
686
582
|
}
|
|
687
583
|
|
|
688
|
-
/**
|
|
689
|
-
* Primary scroll event type (main viewport scroll)
|
|
690
|
-
*
|
|
691
|
-
* **Purpose**: Type-safe representation of primary viewport scroll events
|
|
692
|
-
*
|
|
693
|
-
* Primary scroll events track the main page/viewport scrolling,
|
|
694
|
-
* which is the most important scroll metric for engagement analysis.
|
|
695
|
-
*/
|
|
696
|
-
type PrimaryScrollEvent = EventData & {
|
|
697
|
-
type: EventType.SCROLL;
|
|
698
|
-
scroll_data: ScrollData & {
|
|
699
|
-
is_primary: true;
|
|
700
|
-
};
|
|
701
|
-
};
|
|
702
|
-
/**
|
|
703
|
-
* Secondary scroll event type (scrollable container scroll)
|
|
704
|
-
*
|
|
705
|
-
* **Purpose**: Type-safe representation of container-specific scroll events
|
|
706
|
-
*
|
|
707
|
-
* Secondary scroll events track scrolling within specific elements
|
|
708
|
-
* (e.g., modals, sidebars, embedded content) for granular engagement analysis.
|
|
709
|
-
*/
|
|
710
|
-
type SecondaryScrollEvent = EventData & {
|
|
711
|
-
type: EventType.SCROLL;
|
|
712
|
-
scroll_data: ScrollData & {
|
|
713
|
-
is_primary: false;
|
|
714
|
-
};
|
|
715
|
-
};
|
|
716
|
-
/**
|
|
717
|
-
* Type guard to check if an event is a primary scroll event
|
|
718
|
-
*
|
|
719
|
-
* **Purpose**: Runtime type narrowing for primary viewport scrolls
|
|
720
|
-
*
|
|
721
|
-
* **Use Cases**:
|
|
722
|
-
* - Filter events to process only main viewport scrolling
|
|
723
|
-
* - Separate primary from secondary scroll analytics
|
|
724
|
-
* - Type-safe event processing in transformers
|
|
725
|
-
*
|
|
726
|
-
* @param event - Event to check
|
|
727
|
-
* @returns `true` if event is a primary scroll event
|
|
728
|
-
*
|
|
729
|
-
* @example
|
|
730
|
-
* ```typescript
|
|
731
|
-
* if (isPrimaryScrollEvent(event)) {
|
|
732
|
-
* // event.scroll_data.is_primary is guaranteed to be true
|
|
733
|
-
* console.log('Main viewport scrolled to', event.scroll_data.depth, '%');
|
|
734
|
-
* }
|
|
735
|
-
* ```
|
|
736
|
-
*/
|
|
737
|
-
declare const isPrimaryScrollEvent: (event: EventData) => event is PrimaryScrollEvent;
|
|
738
|
-
/**
|
|
739
|
-
* Type guard to check if an event is a secondary scroll event
|
|
740
|
-
*
|
|
741
|
-
* **Purpose**: Runtime type narrowing for container-specific scrolls
|
|
742
|
-
*
|
|
743
|
-
* **Use Cases**:
|
|
744
|
-
* - Filter events to process only container scrolling
|
|
745
|
-
* - Analyze engagement with specific page sections
|
|
746
|
-
* - Type-safe event processing in transformers
|
|
747
|
-
*
|
|
748
|
-
* @param event - Event to check
|
|
749
|
-
* @returns `true` if event is a secondary scroll event
|
|
750
|
-
*
|
|
751
|
-
* @example
|
|
752
|
-
* ```typescript
|
|
753
|
-
* if (isSecondaryScrollEvent(event)) {
|
|
754
|
-
* // event.scroll_data.is_primary is guaranteed to be false
|
|
755
|
-
* console.log('Container scrolled:', event.scroll_data.container_selector);
|
|
756
|
-
* }
|
|
757
|
-
* ```
|
|
758
|
-
*/
|
|
759
|
-
declare const isSecondaryScrollEvent: (event: EventData) => event is SecondaryScrollEvent;
|
|
760
|
-
|
|
761
584
|
interface State {
|
|
762
585
|
/** QA mode flag - when true, custom events are logged to console */
|
|
763
586
|
mode?: Mode;
|
|
764
587
|
/**
|
|
765
588
|
* Collection of API URLs for different integrations.
|
|
766
589
|
* - saas: TraceLog SaaS endpoint (if projectId configured)
|
|
767
|
-
* - custom: Custom backend endpoint (if collectApiUrl configured)
|
|
768
590
|
*/
|
|
769
591
|
collectApiUrls: {
|
|
770
592
|
saas?: string;
|
|
771
|
-
custom?: string;
|
|
772
593
|
};
|
|
773
594
|
config: Config;
|
|
774
595
|
sessionId: string | null;
|
|
@@ -784,6 +605,15 @@ interface State {
|
|
|
784
605
|
identity?: IdentifyData;
|
|
785
606
|
}
|
|
786
607
|
|
|
608
|
+
/**
|
|
609
|
+
* Regular expressions used to detect and redact common PII patterns from
|
|
610
|
+
* free-form text (click text, error messages, stack traces, etc.).
|
|
611
|
+
*
|
|
612
|
+
* Mirrors the patterns relied on by `ClickHandler` and `ErrorHandler`. Adding
|
|
613
|
+
* a pattern here automatically widens coverage for both handlers.
|
|
614
|
+
*/
|
|
615
|
+
declare const PII_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
616
|
+
|
|
787
617
|
/**
|
|
788
618
|
* Type-safe event emitter for TraceLog internal events
|
|
789
619
|
*
|
|
@@ -944,35 +774,15 @@ declare class Emitter {
|
|
|
944
774
|
/**
|
|
945
775
|
* Abstract base class providing centralized, type-safe state management.
|
|
946
776
|
*
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
*
|
|
950
|
-
* **Architecture**:
|
|
951
|
-
* - All managers/handlers extend this class
|
|
952
|
-
* - Single global state instance shared across all subclasses
|
|
953
|
-
* - Type-safe operations via generic methods
|
|
954
|
-
* - In-memory only (no automatic persistence)
|
|
955
|
-
*
|
|
956
|
-
* **Supported State Properties**:
|
|
957
|
-
* - **Core State**: `collectApiUrls`, `config`, `sessionId`, `userId`, `device`, `pageUrl`
|
|
958
|
-
* - **Control Flags**: `mode` (QA/production), `hasStartSession`, `suppressNextScroll`
|
|
959
|
-
* - **Runtime Counters**: `scrollEventCount` (optional)
|
|
960
|
-
*
|
|
961
|
-
* **Implementation Details**:
|
|
962
|
-
* - Synchronous operations (no async overhead)
|
|
963
|
-
* - Memory-efficient (minimal object creation)
|
|
964
|
-
* - No built-in logging (consumers handle their own state logging)
|
|
965
|
-
* - Read-only snapshots via `getState()` prevent accidental mutations
|
|
966
|
-
*
|
|
967
|
-
* @see src/managers/README.md (lines 170-201) for detailed documentation
|
|
777
|
+
* All managers/handlers extend this class. The global state is shared
|
|
778
|
+
* across every subclass instance.
|
|
968
779
|
*
|
|
969
780
|
* @example
|
|
970
781
|
* ```typescript
|
|
971
782
|
* class MyManager extends StateManager {
|
|
972
783
|
* initialize() {
|
|
973
|
-
* const userId = this.get('userId');
|
|
974
|
-
* this.set('mode', 'qa');
|
|
975
|
-
* const snapshot = this.getState(); // Readonly copy
|
|
784
|
+
* const userId = this.get('userId');
|
|
785
|
+
* this.set('mode', 'qa');
|
|
976
786
|
* }
|
|
977
787
|
* }
|
|
978
788
|
* ```
|
|
@@ -980,52 +790,14 @@ declare class Emitter {
|
|
|
980
790
|
declare abstract class StateManager {
|
|
981
791
|
/**
|
|
982
792
|
* Retrieves a value from global state.
|
|
983
|
-
*
|
|
984
|
-
* Type-safe getter with compile-time key validation.
|
|
985
|
-
*
|
|
986
|
-
* @template T - State key type (compile-time validated)
|
|
987
|
-
* @param key - State property key
|
|
988
|
-
* @returns Current value for the given key (may be undefined)
|
|
989
|
-
*
|
|
990
|
-
* @example
|
|
991
|
-
* ```typescript
|
|
992
|
-
* const userId = this.get('userId');
|
|
993
|
-
* const config = this.get('config');
|
|
994
|
-
* const sessionId = this.get('sessionId');
|
|
995
|
-
* ```
|
|
996
793
|
*/
|
|
997
794
|
protected get<T extends keyof State>(key: T): State[T];
|
|
998
795
|
/**
|
|
999
796
|
* Sets a value in global state.
|
|
1000
|
-
*
|
|
1001
|
-
* Type-safe setter with compile-time type checking.
|
|
1002
|
-
* Changes are immediately visible to all StateManager subclasses.
|
|
1003
|
-
*
|
|
1004
|
-
* @template T - State key type (compile-time validated)
|
|
1005
|
-
* @param key - State property key
|
|
1006
|
-
* @param value - New value (type must match State[T])
|
|
1007
|
-
*
|
|
1008
|
-
* @example
|
|
1009
|
-
* ```typescript
|
|
1010
|
-
* this.set('sessionId', 'session-123');
|
|
1011
|
-
* this.set('mode', Mode.QA);
|
|
1012
|
-
* this.set('hasStartSession', true);
|
|
1013
|
-
* ```
|
|
1014
797
|
*/
|
|
1015
798
|
protected set<T extends keyof State>(key: T, value: State[T]): void;
|
|
1016
799
|
/**
|
|
1017
800
|
* Returns an immutable snapshot of the entire global state.
|
|
1018
|
-
*
|
|
1019
|
-
* Creates a shallow copy to prevent accidental mutations.
|
|
1020
|
-
* Use for debugging or when multiple state properties are needed.
|
|
1021
|
-
*
|
|
1022
|
-
* @returns Readonly shallow copy of global state
|
|
1023
|
-
*
|
|
1024
|
-
* @example
|
|
1025
|
-
* ```typescript
|
|
1026
|
-
* const snapshot = this.getState();
|
|
1027
|
-
* console.log(snapshot.userId, snapshot.sessionId);
|
|
1028
|
-
* ```
|
|
1029
801
|
*/
|
|
1030
802
|
protected getState(): Readonly<State>;
|
|
1031
803
|
}
|
|
@@ -1033,212 +805,29 @@ declare abstract class StateManager {
|
|
|
1033
805
|
/**
|
|
1034
806
|
* Robust localStorage and sessionStorage wrapper with automatic fallback to in-memory storage.
|
|
1035
807
|
*
|
|
1036
|
-
*
|
|
1037
|
-
*
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
* - **Dual Storage**: localStorage (persistent) and sessionStorage (tab-scoped)
|
|
1041
|
-
* - **Automatic Fallback**: In-memory Maps when browser storage unavailable
|
|
1042
|
-
* - **Quota Handling**: Intelligent cleanup on QuotaExceededError
|
|
1043
|
-
* - **SSR-Safe**: No-op in Node.js environments
|
|
1044
|
-
*
|
|
1045
|
-
* **Key Features**:
|
|
1046
|
-
* - Separate fallback Maps for each storage type
|
|
1047
|
-
* - Storage quota error handling with automatic cleanup and retry
|
|
1048
|
-
* - Intelligent cleanup: Prioritizes removing persisted events over critical data
|
|
1049
|
-
* - Preserves: session, user, device, and config keys during cleanup
|
|
1050
|
-
* - Test key validation during initialization (`__tracelog_test__`)
|
|
1051
|
-
* - Public `isAvailable()` and `hasQuotaError()` for conditional logic
|
|
1052
|
-
* - Explicit `clear()` method for TraceLog-namespaced data only (`tracelog_*` prefix)
|
|
1053
|
-
*
|
|
1054
|
-
* **Cleanup Strategy** (on QuotaExceededError):
|
|
1055
|
-
* 1. Remove persisted events (`tracelog_persisted_events_*`) - usually largest data
|
|
1056
|
-
* 2. If no persisted events, remove up to 5 non-critical keys
|
|
1057
|
-
* 3. Preserve critical keys: `tracelog_session_*`, `tracelog_user_id`, `tracelog_device_id`, `tracelog_config`
|
|
1058
|
-
*
|
|
1059
|
-
* @see src/managers/README.md (lines 203-226) for detailed documentation
|
|
1060
|
-
*
|
|
1061
|
-
* @example
|
|
1062
|
-
* ```typescript
|
|
1063
|
-
* const storage = new StorageManager();
|
|
1064
|
-
*
|
|
1065
|
-
* // localStorage operations
|
|
1066
|
-
* storage.setItem('key', 'value');
|
|
1067
|
-
* const value = storage.getItem('key');
|
|
1068
|
-
* storage.removeItem('key');
|
|
1069
|
-
*
|
|
1070
|
-
* // sessionStorage operations
|
|
1071
|
-
* storage.setSessionItem('session_key', 'data');
|
|
1072
|
-
* const sessionValue = storage.getSessionItem('session_key');
|
|
1073
|
-
*
|
|
1074
|
-
* // Check availability
|
|
1075
|
-
* if (storage.isAvailable()) {
|
|
1076
|
-
* // localStorage is working
|
|
1077
|
-
* }
|
|
1078
|
-
*
|
|
1079
|
-
* // Check for quota issues
|
|
1080
|
-
* if (storage.hasQuotaError()) {
|
|
1081
|
-
* // Data may not persist
|
|
1082
|
-
* }
|
|
1083
|
-
* ```
|
|
808
|
+
* - Dual storage: localStorage (persistent) + sessionStorage (tab-scoped).
|
|
809
|
+
* - Automatic in-memory fallback when browser storage unavailable (privacy modes, SSR).
|
|
810
|
+
* - On `QuotaExceededError`: single-pass cleanup — purges `tracelog_persisted_events_*`
|
|
811
|
+
* first (largest, recoverable), retries once. Preserves session/user/device/config keys.
|
|
1084
812
|
*/
|
|
1085
813
|
declare class StorageManager {
|
|
1086
814
|
private readonly storage;
|
|
1087
815
|
private readonly sessionStorageRef;
|
|
1088
816
|
private readonly fallbackStorage;
|
|
1089
817
|
private readonly fallbackSessionStorage;
|
|
1090
|
-
private hasQuotaExceededError;
|
|
1091
818
|
constructor();
|
|
1092
|
-
/**
|
|
1093
|
-
* Retrieves an item from localStorage.
|
|
1094
|
-
*
|
|
1095
|
-
* Automatically falls back to in-memory storage if localStorage unavailable.
|
|
1096
|
-
*
|
|
1097
|
-
* @param key - Storage key
|
|
1098
|
-
* @returns Stored value or null if not found
|
|
1099
|
-
*/
|
|
1100
819
|
getItem(key: string): string | null;
|
|
1101
|
-
/**
|
|
1102
|
-
* Stores an item in localStorage with automatic quota handling.
|
|
1103
|
-
*
|
|
1104
|
-
* **Behavior**:
|
|
1105
|
-
* 1. Updates fallback storage first (ensures consistency)
|
|
1106
|
-
* 2. Attempts to store in localStorage
|
|
1107
|
-
* 3. On QuotaExceededError: Triggers cleanup and retries once
|
|
1108
|
-
* 4. Falls back to in-memory storage if retry fails
|
|
1109
|
-
*
|
|
1110
|
-
* **Cleanup on Quota Error**:
|
|
1111
|
-
* - Removes persisted events (largest data)
|
|
1112
|
-
* - Removes up to 5 non-critical keys
|
|
1113
|
-
* - Preserves session, user, device, and config keys
|
|
1114
|
-
*
|
|
1115
|
-
* @param key - Storage key
|
|
1116
|
-
* @param value - String value to store
|
|
1117
|
-
*/
|
|
1118
820
|
setItem(key: string, value: string): void;
|
|
1119
|
-
/**
|
|
1120
|
-
* Removes an item from localStorage and fallback storage.
|
|
1121
|
-
*
|
|
1122
|
-
* Safe to call even if key doesn't exist (idempotent).
|
|
1123
|
-
*
|
|
1124
|
-
* @param key - Storage key to remove
|
|
1125
|
-
*/
|
|
1126
821
|
removeItem(key: string): void;
|
|
1127
822
|
/**
|
|
1128
|
-
*
|
|
1129
|
-
*
|
|
1130
|
-
*
|
|
1131
|
-
* Clears both localStorage and fallback storage.
|
|
1132
|
-
*
|
|
1133
|
-
* **Use Cases**:
|
|
1134
|
-
* - User logout/privacy actions
|
|
1135
|
-
* - Development/testing cleanup
|
|
1136
|
-
* - Reset analytics state
|
|
1137
|
-
*/
|
|
1138
|
-
clear(): void;
|
|
1139
|
-
/**
|
|
1140
|
-
* Checks if localStorage is available.
|
|
1141
|
-
*
|
|
1142
|
-
* @returns true if localStorage is working, false if using fallback
|
|
1143
|
-
*/
|
|
1144
|
-
isAvailable(): boolean;
|
|
1145
|
-
/**
|
|
1146
|
-
* Checks if a QuotaExceededError has occurred during this session.
|
|
1147
|
-
*
|
|
1148
|
-
* **Purpose**: Detect when localStorage is full and data may not persist.
|
|
1149
|
-
* Allows application to show warnings or adjust behavior.
|
|
1150
|
-
*
|
|
1151
|
-
* **Note**: Flag is set on first QuotaExceededError and never reset.
|
|
1152
|
-
*
|
|
1153
|
-
* @returns true if quota exceeded at any point during this session
|
|
1154
|
-
*/
|
|
1155
|
-
hasQuotaError(): boolean;
|
|
1156
|
-
/**
|
|
1157
|
-
* Implements two-phase cleanup strategy to free storage space when quota exceeded.
|
|
1158
|
-
*
|
|
1159
|
-
* **Purpose**: Removes TraceLog data intelligently to make room for new writes
|
|
1160
|
-
* while preserving critical user state (session, user ID, device ID, config).
|
|
1161
|
-
*
|
|
1162
|
-
* **Two-Phase Cleanup Strategy**:
|
|
1163
|
-
* 1. **Phase 1 (Priority)**: Remove all persisted events (`tracelog_persisted_events_*`)
|
|
1164
|
-
* - These are typically the largest data items (batches of events)
|
|
1165
|
-
* - Safe to remove as they represent recoverable failed sends
|
|
1166
|
-
* - Returns immediately if any persisted events found and removed
|
|
1167
|
-
*
|
|
1168
|
-
* 2. **Phase 2 (Fallback)**: Remove up to 5 non-critical keys
|
|
1169
|
-
* - Only executed if no persisted events found
|
|
1170
|
-
* - Preserves critical keys: session data, user ID, device ID, config
|
|
1171
|
-
* - Limits to 5 keys to avoid excessive cleanup time
|
|
1172
|
-
*
|
|
1173
|
-
* **Critical Keys (Never Removed)**:
|
|
1174
|
-
* - `tracelog_session_*` - Active session data
|
|
1175
|
-
* - `tracelog_user_id` - User identification
|
|
1176
|
-
* - `tracelog_device_id` - Device fingerprint
|
|
1177
|
-
* - `tracelog_config` - Configuration cache
|
|
1178
|
-
*
|
|
1179
|
-
* **Error Handling**:
|
|
1180
|
-
* - Individual key removal failures silently ignored (continue cleanup)
|
|
1181
|
-
* - Overall cleanup errors logged and return false
|
|
1182
|
-
*
|
|
1183
|
-
* @returns true if any data was successfully removed, false if nothing cleaned up
|
|
823
|
+
* Single-pass cleanup for QuotaExceededError. Purges persisted-events keys
|
|
824
|
+
* (largest, safe to discard — recoverable) and up to 5 other non-critical
|
|
825
|
+
* tracelog_* keys in one pass. Preserves session/user/device/config keys.
|
|
1184
826
|
*/
|
|
1185
827
|
private cleanupOldData;
|
|
1186
|
-
/**
|
|
1187
|
-
* Initializes storage with feature detection and write-test validation.
|
|
1188
|
-
*
|
|
1189
|
-
* **Purpose**: Validates storage availability by performing actual write/remove test,
|
|
1190
|
-
* preventing false positives in privacy modes where storage API exists but throws on write.
|
|
1191
|
-
*
|
|
1192
|
-
* **Validation Strategy**:
|
|
1193
|
-
* 1. SSR Safety: Returns null in Node.js environments (`typeof window === 'undefined'`)
|
|
1194
|
-
* 2. API Check: Verifies storage object exists on window
|
|
1195
|
-
* 3. Write Test: Attempts to write test key (`__tracelog_test__`)
|
|
1196
|
-
* 4. Cleanup: Removes test key immediately after validation
|
|
1197
|
-
*
|
|
1198
|
-
* **Why Write Test is Critical**:
|
|
1199
|
-
* - Safari private browsing: storage API exists but throws QuotaExceededError on write
|
|
1200
|
-
* - iOS private mode: storage appears available but operations fail
|
|
1201
|
-
* - Incognito modes: API exists but writes are silently ignored or throw
|
|
1202
|
-
*
|
|
1203
|
-
* **Fallback Behavior**:
|
|
1204
|
-
* - Returns null if storage unavailable or test fails
|
|
1205
|
-
* - Caller automatically falls back to in-memory Map storage
|
|
1206
|
-
*
|
|
1207
|
-
* @param type - Storage type to initialize ('localStorage' | 'sessionStorage')
|
|
1208
|
-
* @returns Storage instance if available and writable, null otherwise
|
|
1209
|
-
*/
|
|
1210
828
|
private initializeStorage;
|
|
1211
|
-
/**
|
|
1212
|
-
* Retrieves an item from sessionStorage.
|
|
1213
|
-
*
|
|
1214
|
-
* Automatically falls back to in-memory storage if sessionStorage unavailable.
|
|
1215
|
-
*
|
|
1216
|
-
* @param key - Storage key
|
|
1217
|
-
* @returns Stored value or null if not found
|
|
1218
|
-
*/
|
|
1219
829
|
getSessionItem(key: string): string | null;
|
|
1220
|
-
/**
|
|
1221
|
-
* Stores an item in sessionStorage with quota error detection.
|
|
1222
|
-
*
|
|
1223
|
-
* **Behavior**:
|
|
1224
|
-
* 1. Updates fallback storage first (ensures consistency)
|
|
1225
|
-
* 2. Attempts to store in sessionStorage
|
|
1226
|
-
* 3. On QuotaExceededError: Logs error and uses fallback (no retry/cleanup)
|
|
1227
|
-
*
|
|
1228
|
-
* **Note**: sessionStorage quota errors are rare (typically 5-10MB per tab).
|
|
1229
|
-
* No automatic cleanup unlike localStorage.
|
|
1230
|
-
*
|
|
1231
|
-
* @param key - Storage key
|
|
1232
|
-
* @param value - String value to store
|
|
1233
|
-
*/
|
|
1234
830
|
setSessionItem(key: string, value: string): void;
|
|
1235
|
-
/**
|
|
1236
|
-
* Removes an item from sessionStorage and fallback storage.
|
|
1237
|
-
*
|
|
1238
|
-
* Safe to call even if key doesn't exist (idempotent).
|
|
1239
|
-
*
|
|
1240
|
-
* @param key - Storage key to remove
|
|
1241
|
-
*/
|
|
1242
831
|
removeSessionItem(key: string): void;
|
|
1243
832
|
}
|
|
1244
833
|
|
|
@@ -1308,7 +897,6 @@ declare class StorageManager {
|
|
|
1308
897
|
declare class EventManager extends StateManager {
|
|
1309
898
|
private readonly dataSenders;
|
|
1310
899
|
private readonly emitter;
|
|
1311
|
-
private readonly transformers;
|
|
1312
900
|
private readonly timeManager;
|
|
1313
901
|
private readonly recentEventFingerprints;
|
|
1314
902
|
private readonly perEventRateLimits;
|
|
@@ -1320,23 +908,16 @@ declare class EventManager extends StateManager {
|
|
|
1320
908
|
private rateLimitCounter;
|
|
1321
909
|
private rateLimitWindowStart;
|
|
1322
910
|
private lastSessionId;
|
|
911
|
+
private pendingSyncFlush;
|
|
1323
912
|
private sessionEventCounts;
|
|
1324
913
|
private readonly saveSessionCountsDebounced;
|
|
1325
914
|
/**
|
|
1326
915
|
* Creates an EventManager instance.
|
|
1327
916
|
*
|
|
1328
|
-
* **Initialization**:
|
|
1329
|
-
* - Creates SenderManager instances for configured integrations (SaaS/Custom)
|
|
1330
|
-
* - Initializes event emitter for local consumption
|
|
1331
|
-
*
|
|
1332
917
|
* @param storeManager - Storage manager for persistence
|
|
1333
918
|
* @param emitter - Optional event emitter for local event consumption
|
|
1334
|
-
* @param transformers - Optional event transformation hooks
|
|
1335
|
-
* @param staticHeaders - Optional static HTTP headers for custom backend (from config)
|
|
1336
|
-
* @param customHeadersProvider - Optional callback for dynamic headers
|
|
1337
|
-
* @param fetchCredentials - Fetch credentials mode for custom backend. @default 'include'
|
|
1338
919
|
*/
|
|
1339
|
-
constructor(storeManager: StorageManager, emitter?: Emitter | null
|
|
920
|
+
constructor(storeManager: StorageManager, emitter?: Emitter | null);
|
|
1340
921
|
/**
|
|
1341
922
|
* Recovers persisted events from localStorage after a crash or page reload.
|
|
1342
923
|
*
|
|
@@ -1421,7 +1002,7 @@ declare class EventManager extends StateManager {
|
|
|
1421
1002
|
*
|
|
1422
1003
|
* @see src/managers/README.md (lines 5-75) for detailed tracking logic
|
|
1423
1004
|
*/
|
|
1424
|
-
track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data,
|
|
1005
|
+
track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, page_view, }: Partial<EventData>): void;
|
|
1425
1006
|
/**
|
|
1426
1007
|
* Stops event tracking and clears all queues and buffers.
|
|
1427
1008
|
*
|
|
@@ -1477,7 +1058,10 @@ declare class EventManager extends StateManager {
|
|
|
1477
1058
|
* **Note**: For page unload, use `flushImmediatelySync()` instead,
|
|
1478
1059
|
* which uses `sendBeacon()` for guaranteed delivery.
|
|
1479
1060
|
*
|
|
1480
|
-
* @returns Promise resolving to `true` if
|
|
1061
|
+
* @returns Promise resolving to `true` if at least one integration accepted
|
|
1062
|
+
* the batch during this call (optimistic removal — failures
|
|
1063
|
+
* persist per-integration for retry). `false` if no events, all
|
|
1064
|
+
* senders failed, or a flush is already in flight.
|
|
1481
1065
|
*
|
|
1482
1066
|
* @example
|
|
1483
1067
|
* ```typescript
|
|
@@ -1513,7 +1097,14 @@ declare class EventManager extends StateManager {
|
|
|
1513
1097
|
* - No retry on failure (sendBeacon is fire-and-forget)
|
|
1514
1098
|
* - 64KB payload limit (large batches may be truncated)
|
|
1515
1099
|
*
|
|
1516
|
-
*
|
|
1100
|
+
* **In-flight contract**: if an async send is already running this call is
|
|
1101
|
+
* deferred (queued for replay in the async send's `finally` block) and
|
|
1102
|
+
* returns `false` — nothing has been delivered yet at the point of return.
|
|
1103
|
+
* Mirrors `flushImmediately()`'s behaviour for the same condition.
|
|
1104
|
+
*
|
|
1105
|
+
* @returns `true` if at least one integration accepted the beacon batch
|
|
1106
|
+
* *during this call*, `false` otherwise (no events, all senders
|
|
1107
|
+
* failed, or the call was deferred behind an in-flight async send)
|
|
1517
1108
|
*
|
|
1518
1109
|
* @example
|
|
1519
1110
|
* ```typescript
|
|
@@ -1527,17 +1118,6 @@ declare class EventManager extends StateManager {
|
|
|
1527
1118
|
* @see src/managers/README.md (lines 5-75) for flush details
|
|
1528
1119
|
*/
|
|
1529
1120
|
flushImmediatelySync(): boolean;
|
|
1530
|
-
/**
|
|
1531
|
-
* Sets the custom headers provider callback for the custom integration.
|
|
1532
|
-
* Only affects requests to custom backend (not TraceLog SaaS).
|
|
1533
|
-
*
|
|
1534
|
-
* @param provider - Callback function that returns custom headers
|
|
1535
|
-
*/
|
|
1536
|
-
setCustomHeadersProvider(provider: CustomHeadersProvider): void;
|
|
1537
|
-
/**
|
|
1538
|
-
* Removes the custom headers provider callback from the custom integration.
|
|
1539
|
-
*/
|
|
1540
|
-
removeCustomHeadersProvider(): void;
|
|
1541
1121
|
/**
|
|
1542
1122
|
* Returns the current number of events in the main queue.
|
|
1543
1123
|
*
|
|
@@ -1628,9 +1208,79 @@ declare class EventManager extends StateManager {
|
|
|
1628
1208
|
flushPendingEvents(): void;
|
|
1629
1209
|
private clearSendTimeout;
|
|
1630
1210
|
private isSuccessfulResult;
|
|
1211
|
+
/**
|
|
1212
|
+
* Groups the queue by frozen `_session_id`, preserving insertion order.
|
|
1213
|
+
* Single pass — `buildBatchesWithIds()` builds one batch + one eventIds list
|
|
1214
|
+
* per group, so the grouping cost is O(N) per flush regardless of session
|
|
1215
|
+
* count.
|
|
1216
|
+
*
|
|
1217
|
+
* **Self-heal**: any entry missing `_session_id` (an internal invariant
|
|
1218
|
+
* violation — `buildEventPayload` always stamps it) is removed from the
|
|
1219
|
+
* queue rather than left behind, otherwise a single corrupted entry would
|
|
1220
|
+
* keep `eventsQueue.length > 0` forever and re-trigger periodic sends.
|
|
1221
|
+
*/
|
|
1222
|
+
private groupQueuedEventsBySession;
|
|
1223
|
+
/**
|
|
1224
|
+
* Builds a parallel list of `(batch, eventIds)` for sending. The eventIds are
|
|
1225
|
+
* the original `_session_id`-tagged event IDs in the queue that map to this
|
|
1226
|
+
* batch — used for optimistic removal. We can't read them off the wrapper's
|
|
1227
|
+
* `events[]` because dedup may have removed some signatures.
|
|
1228
|
+
*/
|
|
1229
|
+
private buildBatchesWithIds;
|
|
1631
1230
|
private flushEvents;
|
|
1231
|
+
/**
|
|
1232
|
+
* Reconciles the periodic send timer after a flush attempt. Clears the
|
|
1233
|
+
* timer when the queue is empty, otherwise (re)schedules a retry tick.
|
|
1234
|
+
*
|
|
1235
|
+
* **Why**: a `flushImmediately()` / `flushImmediatelySync()` call where all
|
|
1236
|
+
* integrations fail leaves events in `eventsQueue` for retry. The periodic
|
|
1237
|
+
* timer is the safety net that drains them when the backend recovers — if
|
|
1238
|
+
* we cleared it unconditionally here, the queue would sit untouched until
|
|
1239
|
+
* the next tracked event resurrects the timer in `addToQueue`. Mirrors the
|
|
1240
|
+
* pattern in `sendEventsQueue()` (the periodic path).
|
|
1241
|
+
*/
|
|
1242
|
+
private settleSendTimeout;
|
|
1243
|
+
/**
|
|
1244
|
+
* Re-runs a sync flush that was deferred while an async send was in flight.
|
|
1245
|
+
*
|
|
1246
|
+
* Called from the `finally` blocks of `flushEvents(false)` and
|
|
1247
|
+
* `sendEventsQueue()`. If `pendingSyncFlush` is set, clears the flag and
|
|
1248
|
+
* invokes `flushImmediatelySync()` synchronously so any events that arrived
|
|
1249
|
+
* after the deferred sync call are delivered before the next event loop
|
|
1250
|
+
* tick. Critical for high-stakes events tracked mid-async-send.
|
|
1251
|
+
*/
|
|
1252
|
+
private drainPendingSyncFlush;
|
|
1253
|
+
/**
|
|
1254
|
+
* Sends one batch synchronously across all integrations (sendBeacon path).
|
|
1255
|
+
* Optimistic removal: if any integration succeeds, we remove the batch's
|
|
1256
|
+
* events from the queue and emit it locally. Failures persist per-integration.
|
|
1257
|
+
*/
|
|
1258
|
+
private sendBatchSync;
|
|
1259
|
+
/**
|
|
1260
|
+
* Sends one batch asynchronously across all integrations (fetch path).
|
|
1261
|
+
*/
|
|
1262
|
+
private sendBatchAsync;
|
|
1632
1263
|
private sendEventsQueue;
|
|
1633
|
-
|
|
1264
|
+
/**
|
|
1265
|
+
* Builds a single batch from a per-session group: dedup by signature,
|
|
1266
|
+
* SESSION_START first, then timestamp order, strip `_session_id`, apply
|
|
1267
|
+
* `beforeBatch` transformer when running standalone.
|
|
1268
|
+
*
|
|
1269
|
+
* **Why N batches per flush**: events freeze their `_session_id` at `track()`
|
|
1270
|
+
* time. If the session was renewed (idle timeout) between two `track()`
|
|
1271
|
+
* calls, the queue contains events from multiple sessions. `buildBatchesWithIds()`
|
|
1272
|
+
* emits one batch per session so the backend's `EventsQueueDto.session_id`
|
|
1273
|
+
* remains the single source of truth and stays consistent with the events it
|
|
1274
|
+
* carries.
|
|
1275
|
+
*
|
|
1276
|
+
* **Strip**: `_session_id` is removed from each event in the wrapper's
|
|
1277
|
+
* `events[]` because the backend uses `forbidNonWhitelisted: true` and would
|
|
1278
|
+
* reject the batch if the field leaked through.
|
|
1279
|
+
*
|
|
1280
|
+
* **Transformer note**: `beforeBatch` is invoked **once per session-batch**,
|
|
1281
|
+
* not once per flush. A queue spanning N sessions triggers N invocations.
|
|
1282
|
+
*/
|
|
1283
|
+
private buildBatchFromGroup;
|
|
1634
1284
|
private buildEventPayload;
|
|
1635
1285
|
private isDuplicateEvent;
|
|
1636
1286
|
private pruneOldFingerprints;
|
|
@@ -1765,7 +1415,6 @@ declare class EventManager extends StateManager {
|
|
|
1765
1415
|
* - Custom threshold overrides via webVitalsThresholds config
|
|
1766
1416
|
* - Navigation-based deduplication with 50-navigation FIFO history
|
|
1767
1417
|
* - CLS accumulation with reset on navigation change
|
|
1768
|
-
* - Long task throttling (maximum 1 event per second)
|
|
1769
1418
|
* - Automatic fallback to Performance Observer if web-vitals library fails
|
|
1770
1419
|
* - Final values only (reportAllChanges: false for all metrics)
|
|
1771
1420
|
*
|
|
@@ -1777,7 +1426,6 @@ declare class EventManager extends StateManager {
|
|
|
1777
1426
|
* - FCP (First Contentful Paint): Initial rendering time
|
|
1778
1427
|
* - TTFB (Time to First Byte): Server response time
|
|
1779
1428
|
* - INP (Interaction to Next Paint): Responsiveness measure
|
|
1780
|
-
* - LONG_TASK: Tasks blocking main thread (>50ms, throttled to 1/second)
|
|
1781
1429
|
*
|
|
1782
1430
|
* **Filtering Modes**:
|
|
1783
1431
|
* - 'all': Track all positive metric values (threshold = 0)
|
|
@@ -1798,7 +1446,6 @@ declare class PerformanceHandler extends StateManager {
|
|
|
1798
1446
|
private readonly navigationHistory;
|
|
1799
1447
|
private readonly observers;
|
|
1800
1448
|
private vitalThresholds;
|
|
1801
|
-
private lastLongTaskSentAt;
|
|
1802
1449
|
private navigationCounter;
|
|
1803
1450
|
constructor(eventManager: EventManager);
|
|
1804
1451
|
/**
|
|
@@ -1811,7 +1458,6 @@ declare class PerformanceHandler extends StateManager {
|
|
|
1811
1458
|
* - Reads webVitalsMode from config ('all', 'needs-improvement', 'poor')
|
|
1812
1459
|
* - Merges webVitalsThresholds with mode defaults for custom thresholds
|
|
1813
1460
|
* - Initializes web-vitals library observers (LCP, CLS, FCP, TTFB, INP)
|
|
1814
|
-
* - Starts long task observation with 1/second throttling
|
|
1815
1461
|
*
|
|
1816
1462
|
* @returns Promise that resolves when tracking is initialized
|
|
1817
1463
|
*/
|
|
@@ -1829,7 +1475,6 @@ declare class PerformanceHandler extends StateManager {
|
|
|
1829
1475
|
private observeWebVitalsFallback;
|
|
1830
1476
|
private initWebVitals;
|
|
1831
1477
|
private reportTTFB;
|
|
1832
|
-
private observeLongTasks;
|
|
1833
1478
|
private sendVital;
|
|
1834
1479
|
private trackWebVital;
|
|
1835
1480
|
/**
|
|
@@ -1871,45 +1516,70 @@ declare class PerformanceHandler extends StateManager {
|
|
|
1871
1516
|
* - Message truncation (500 character limit)
|
|
1872
1517
|
* - Burst detection (>10 errors/second triggers 5-second cooldown)
|
|
1873
1518
|
* - Deduplication within 5-second window per error type+message
|
|
1519
|
+
* - Per-pageview signature cap (`MAX_ERRORS_PER_SIGNATURE_PER_PAGEVIEW`): after the
|
|
1520
|
+
* 5s dedup window expires, the same `(normalizedMessage, filename, line)` may only
|
|
1521
|
+
* recur up to N times per pageview. Counter resets on `pagehide`, `SESSION_START`,
|
|
1522
|
+
* and `PAGE_VIEW` (covers SPA navigation via patched History API + popstate/hashchange).
|
|
1874
1523
|
*
|
|
1875
1524
|
* **Privacy Protection**:
|
|
1876
1525
|
* - Automatically redacts PII from error messages before storage
|
|
1877
1526
|
* - Sanitizes emails, phone numbers, credit cards, IBAN, API keys, Bearer tokens
|
|
1878
1527
|
*
|
|
1879
|
-
* @see src/handlers/README.md (
|
|
1528
|
+
* @see src/handlers/README.md (`## ErrorHandler` section) for detailed documentation
|
|
1880
1529
|
*/
|
|
1881
1530
|
declare class ErrorHandler extends StateManager {
|
|
1882
1531
|
private readonly eventManager;
|
|
1532
|
+
private readonly emitter?;
|
|
1883
1533
|
private readonly recentErrors;
|
|
1534
|
+
private readonly pageviewSignatureCounts;
|
|
1884
1535
|
private errorBurstCounter;
|
|
1885
1536
|
private burstWindowStart;
|
|
1886
1537
|
private burstBackoffUntil;
|
|
1887
|
-
|
|
1538
|
+
private pagehideHandler;
|
|
1539
|
+
private pageviewResetListener;
|
|
1540
|
+
constructor(eventManager: EventManager, emitter?: Emitter);
|
|
1888
1541
|
/**
|
|
1889
1542
|
* Starts tracking JavaScript errors and promise rejections.
|
|
1890
1543
|
*
|
|
1891
1544
|
* - Registers global error event listener
|
|
1892
1545
|
* - Registers unhandledrejection event listener
|
|
1546
|
+
* - Registers pagehide listener to reset the per-pageview signature counter
|
|
1547
|
+
* - Subscribes to emitter SESSION_START + PAGE_VIEW to reset the counter on new
|
|
1548
|
+
* sessions and SPA route changes (the only signal `pagehide` does not cover)
|
|
1893
1549
|
*/
|
|
1894
1550
|
startTracking(): void;
|
|
1895
1551
|
/**
|
|
1896
1552
|
* Stops tracking errors and cleans up resources.
|
|
1897
1553
|
*
|
|
1898
1554
|
* - Removes error event listeners
|
|
1899
|
-
* -
|
|
1555
|
+
* - Removes pagehide listener and unsubscribes from emitter
|
|
1556
|
+
* - Clears recent errors and pageview signature counters
|
|
1900
1557
|
* - Resets burst detection counters
|
|
1901
1558
|
*/
|
|
1902
1559
|
stopTracking(): void;
|
|
1560
|
+
/**
|
|
1561
|
+
* Clears the per-pageview signature counter.
|
|
1562
|
+
*
|
|
1563
|
+
* Public so `App` or tests can drive a reset explicitly; the handler itself wires
|
|
1564
|
+
* `pagehide` and emitter `SESSION_START` / `PAGE_VIEW` in `startTracking()`.
|
|
1565
|
+
*/
|
|
1566
|
+
resetPageviewCounter(): void;
|
|
1903
1567
|
/**
|
|
1904
1568
|
* Checks sampling rate and burst detection
|
|
1905
1569
|
* Returns false if in cooldown period after burst detection
|
|
1906
1570
|
*/
|
|
1907
1571
|
private shouldSample;
|
|
1572
|
+
/**
|
|
1573
|
+
* Returns true when the per-pageview signature cap has been hit for this error.
|
|
1574
|
+
* Dropped errors do not increment the counter — the 5s suppression window already
|
|
1575
|
+
* silences identical repeats, and double-counting here would skew the cap for any
|
|
1576
|
+
* later signature that recycles the same map key after a counter reset.
|
|
1577
|
+
*/
|
|
1578
|
+
private shouldThrottleBySignature;
|
|
1908
1579
|
private readonly handleError;
|
|
1909
1580
|
private readonly handleRejection;
|
|
1910
1581
|
private extractRejectionMessage;
|
|
1911
1582
|
private sanitize;
|
|
1912
|
-
private sanitizePii;
|
|
1913
1583
|
private shouldSuppressError;
|
|
1914
1584
|
private static readonly TRUNCATION_SUFFIX;
|
|
1915
1585
|
private truncateStack;
|
|
@@ -2136,128 +1806,36 @@ declare class ClickHandler extends StateManager {
|
|
|
2136
1806
|
private getElementPath;
|
|
2137
1807
|
private findTrackingElement;
|
|
2138
1808
|
private getRelevantClickElement;
|
|
2139
|
-
/**
|
|
2140
|
-
* Clamps relative coordinate values to [0, 1] range with 3 decimal precision.
|
|
2141
|
-
*
|
|
2142
|
-
* @param value - Raw relative coordinate value
|
|
2143
|
-
* @returns Clamped value between 0 and 1 with 3 decimal places (e.g., 0.123)
|
|
2144
|
-
*
|
|
2145
|
-
* @example
|
|
2146
|
-
* clamp(1.234) // returns 1.000
|
|
2147
|
-
* clamp(0.12345) // returns 0.123
|
|
2148
|
-
* clamp(-0.5) // returns 0.000
|
|
2149
|
-
*/
|
|
2150
|
-
private clamp;
|
|
2151
1809
|
private calculateClickCoordinates;
|
|
2152
1810
|
private extractTrackingData;
|
|
2153
1811
|
private generateClickData;
|
|
2154
|
-
/**
|
|
2155
|
-
* Sanitizes text by replacing PII patterns with [REDACTED].
|
|
2156
|
-
*
|
|
2157
|
-
* Protects against:
|
|
2158
|
-
* - Email addresses
|
|
2159
|
-
* - Phone numbers (US format)
|
|
2160
|
-
* - Credit card numbers
|
|
2161
|
-
* - IBAN numbers
|
|
2162
|
-
* - API keys/tokens
|
|
2163
|
-
* - Bearer tokens
|
|
2164
|
-
*
|
|
2165
|
-
* @param text - Raw text content from element
|
|
2166
|
-
* @returns Sanitized text with PII replaced by [REDACTED]
|
|
2167
|
-
*
|
|
2168
|
-
* @example
|
|
2169
|
-
* sanitizeText('Email: user@example.com') // returns 'Email: [REDACTED]'
|
|
2170
|
-
* sanitizeText('Card: 1234-5678-9012-3456') // returns 'Card: [REDACTED]'
|
|
2171
|
-
* sanitizeText('Bearer token123') // returns '[REDACTED]'
|
|
2172
|
-
*/
|
|
2173
|
-
private sanitizeText;
|
|
2174
1812
|
private getRelevantText;
|
|
2175
|
-
private extractElementAttributes;
|
|
2176
1813
|
private createCustomEventData;
|
|
2177
1814
|
}
|
|
2178
1815
|
|
|
2179
1816
|
/**
|
|
2180
|
-
* Tracks scroll depth
|
|
1817
|
+
* Tracks scroll depth and direction across the window and any detected scrollable containers.
|
|
2181
1818
|
*
|
|
2182
|
-
* **
|
|
2183
|
-
* - Automatic container detection with intelligent retry (5 attempts @ 200ms intervals)
|
|
2184
|
-
* - Manual override via primaryScrollSelector config
|
|
2185
|
-
* - Smart filtering with multiple guardrails:
|
|
2186
|
-
* - Visibility check (element must be connected to DOM with dimensions)
|
|
2187
|
-
* - Scrollability check (content must overflow container)
|
|
2188
|
-
* - Significant movement (minimum 10px position delta)
|
|
2189
|
-
* - Depth change (minimum 5% depth change between events)
|
|
2190
|
-
* - Rate limiting (minimum 500ms interval between events per container)
|
|
2191
|
-
* - Session cap (maximum 120 events per session with single warning)
|
|
2192
|
-
* - Multi-container support with per-container debouncing (250ms)
|
|
2193
|
-
* - Velocity calculation for engagement analysis
|
|
2194
|
-
* - Max depth tracking per session
|
|
2195
|
-
* - Primary vs secondary container classification
|
|
2196
|
-
*
|
|
2197
|
-
* **Events Generated**: `scroll`
|
|
2198
|
-
*
|
|
2199
|
-
* **Analytics Fields**:
|
|
2200
|
-
* - depth: Current scroll depth (0-100%)
|
|
2201
|
-
* - direction: 'up' | 'down'
|
|
2202
|
-
* - container_selector: CSS selector or 'window'
|
|
2203
|
-
* - is_primary: Boolean indicating main scroll container
|
|
2204
|
-
* - velocity: Scroll speed in px/s
|
|
2205
|
-
* - max_depth_reached: Peak engagement per container
|
|
2206
|
-
*
|
|
2207
|
-
* **Container Detection**:
|
|
2208
|
-
* - Uses TreeWalker for performance
|
|
2209
|
-
* - Pre-filters elements with overflow: auto/scroll CSS properties
|
|
2210
|
-
* - Validates visibility and scrollability
|
|
2211
|
-
* - Retries up to 5 times for dynamically loaded content (SPAs)
|
|
2212
|
-
* - Falls back to window-only if no containers found
|
|
1819
|
+
* **Captured fields**: `depth` (0-100), `direction` (up/down), `container_selector`.
|
|
2213
1820
|
*
|
|
2214
|
-
*
|
|
2215
|
-
*
|
|
2216
|
-
*
|
|
2217
|
-
*
|
|
2218
|
-
*
|
|
2219
|
-
*
|
|
2220
|
-
* ```
|
|
1821
|
+
* **Guardrails**:
|
|
1822
|
+
* - Significant movement (minimum 10px position delta)
|
|
1823
|
+
* - Depth change (minimum 5% delta between events)
|
|
1824
|
+
* - Rate limiting (minimum 500ms interval between events per container)
|
|
1825
|
+
* - Session cap (maximum 120 events per session)
|
|
1826
|
+
* - Multi-container support with 250ms per-container debouncing
|
|
2221
1827
|
*/
|
|
2222
1828
|
declare class ScrollHandler extends StateManager {
|
|
2223
1829
|
private readonly eventManager;
|
|
2224
1830
|
private readonly containers;
|
|
2225
1831
|
private limitWarningLogged;
|
|
2226
|
-
private minDepthChange;
|
|
2227
|
-
private minIntervalMs;
|
|
2228
|
-
private maxEventsPerSession;
|
|
2229
1832
|
private containerDiscoveryTimeoutId;
|
|
2230
1833
|
constructor(eventManager: EventManager);
|
|
2231
|
-
/**
|
|
2232
|
-
* Starts tracking scroll events across all detected scrollable containers.
|
|
2233
|
-
*
|
|
2234
|
-
* Automatically detects scrollable containers using TreeWalker with retry logic:
|
|
2235
|
-
* - Searches DOM for elements with overflow: auto/scroll
|
|
2236
|
-
* - Validates visibility and scrollability
|
|
2237
|
-
* - Retries up to 5 times with 200ms intervals for dynamic content
|
|
2238
|
-
* - Falls back to window-only tracking if no containers found
|
|
2239
|
-
* - Applies primaryScrollSelector config override if provided
|
|
2240
|
-
*
|
|
2241
|
-
* Attaches debounced scroll listeners (250ms per container) with smart filtering:
|
|
2242
|
-
* - Significant movement (10px minimum)
|
|
2243
|
-
* - Depth change (5% minimum)
|
|
2244
|
-
* - Rate limiting (500ms minimum interval)
|
|
2245
|
-
* - Session cap (120 events maximum)
|
|
2246
|
-
*/
|
|
2247
1834
|
startTracking(): void;
|
|
2248
|
-
/**
|
|
2249
|
-
* Stops tracking scroll events and cleans up resources.
|
|
2250
|
-
*
|
|
2251
|
-
* Removes all scroll event listeners, clears debounce timers, cancels retry attempts,
|
|
2252
|
-
* and resets session state (event counter, warning flags). Prevents memory leaks by
|
|
2253
|
-
* properly cleaning up all containers and timers.
|
|
2254
|
-
*/
|
|
2255
1835
|
stopTracking(): void;
|
|
2256
1836
|
private tryDetectScrollContainers;
|
|
2257
|
-
private applyPrimaryScrollSelectorIfConfigured;
|
|
2258
1837
|
private findScrollableElements;
|
|
2259
1838
|
private getElementSelector;
|
|
2260
|
-
private determineIfPrimary;
|
|
2261
1839
|
private setupScrollContainer;
|
|
2262
1840
|
private processScrollEvent;
|
|
2263
1841
|
private shouldEmitScrollEvent;
|
|
@@ -2265,7 +1843,6 @@ declare class ScrollHandler extends StateManager {
|
|
|
2265
1843
|
private hasElapsedMinimumInterval;
|
|
2266
1844
|
private hasSignificantDepthChange;
|
|
2267
1845
|
private logLimitOnce;
|
|
2268
|
-
private applyConfigOverrides;
|
|
2269
1846
|
private isWindowScrollable;
|
|
2270
1847
|
private clearContainerTimer;
|
|
2271
1848
|
private getScrollDirection;
|
|
@@ -2275,101 +1852,7 @@ declare class ScrollHandler extends StateManager {
|
|
|
2275
1852
|
private getViewportHeight;
|
|
2276
1853
|
private getScrollHeight;
|
|
2277
1854
|
private isElementScrollable;
|
|
2278
|
-
private applyPrimaryScrollSelector;
|
|
2279
|
-
private updateContainerPrimary;
|
|
2280
|
-
}
|
|
2281
|
-
|
|
2282
|
-
/**
|
|
2283
|
-
* Handles viewport visibility tracking using IntersectionObserver API.
|
|
2284
|
-
* Fires events when elements become visible for a minimum dwell time.
|
|
2285
|
-
*/
|
|
2286
|
-
declare class ViewportHandler extends StateManager {
|
|
2287
|
-
private readonly eventManager;
|
|
2288
|
-
private readonly trackedElements;
|
|
2289
|
-
private observer;
|
|
2290
|
-
private mutationObserver;
|
|
2291
|
-
private mutationDebounceTimer;
|
|
2292
|
-
private config;
|
|
2293
|
-
constructor(eventManager: EventManager);
|
|
2294
|
-
/**
|
|
2295
|
-
* Starts tracking viewport visibility for configured elements
|
|
2296
|
-
*/
|
|
2297
|
-
startTracking(): void;
|
|
2298
|
-
/**
|
|
2299
|
-
* Stops tracking and cleans up resources
|
|
2300
|
-
*/
|
|
2301
|
-
stopTracking(): void;
|
|
2302
|
-
/**
|
|
2303
|
-
* Query and observe all elements matching configured elements
|
|
2304
|
-
*/
|
|
2305
|
-
private observeElements;
|
|
2306
|
-
/**
|
|
2307
|
-
* Handles intersection events from IntersectionObserver
|
|
2308
|
-
*/
|
|
2309
|
-
private readonly handleIntersection;
|
|
2310
|
-
/**
|
|
2311
|
-
* Fires a viewport visible event
|
|
2312
|
-
*/
|
|
2313
|
-
private fireViewportEvent;
|
|
2314
|
-
/**
|
|
2315
|
-
* Sets up MutationObserver to detect dynamically added elements
|
|
2316
|
-
*/
|
|
2317
|
-
private setupMutationObserver;
|
|
2318
|
-
/**
|
|
2319
|
-
* Cleans up tracking for removed DOM nodes
|
|
2320
|
-
*/
|
|
2321
|
-
private cleanupRemovedNodes;
|
|
2322
|
-
}
|
|
2323
|
-
|
|
2324
|
-
/**
|
|
2325
|
-
* Transform individual events before sending to backend.
|
|
2326
|
-
* Applied per-event, can filter by returning null.
|
|
2327
|
-
*
|
|
2328
|
-
* @param event - The event to transform
|
|
2329
|
-
* @returns Transformed event or null to filter
|
|
2330
|
-
*/
|
|
2331
|
-
type BeforeSendTransformer = (event: EventData) => EventData | null;
|
|
2332
|
-
/**
|
|
2333
|
-
* Transform entire batch before sending to backend.
|
|
2334
|
-
* Applied per-batch (10s interval or 50 events), can filter by returning null.
|
|
2335
|
-
*
|
|
2336
|
-
* @param batch - The batch to transform
|
|
2337
|
-
* @returns Transformed batch or null to filter
|
|
2338
|
-
*/
|
|
2339
|
-
type BeforeBatchTransformer = (batch: EventsQueue) => EventsQueue | null;
|
|
2340
|
-
/**
|
|
2341
|
-
* Runtime transformer hooks that can be updated after initialization
|
|
2342
|
-
* - 'beforeSend': Transform per-event before sending to backend
|
|
2343
|
-
* - 'beforeBatch': Transform entire batch before sending to backend
|
|
2344
|
-
*/
|
|
2345
|
-
type TransformerHook = 'beforeSend' | 'beforeBatch';
|
|
2346
|
-
/**
|
|
2347
|
-
* Strongly-typed transformer map for internal storage
|
|
2348
|
-
*/
|
|
2349
|
-
interface TransformerMap {
|
|
2350
|
-
beforeSend?: BeforeSendTransformer;
|
|
2351
|
-
beforeBatch?: BeforeBatchTransformer;
|
|
2352
1855
|
}
|
|
2353
|
-
/**
|
|
2354
|
-
* Callback function for providing dynamic HTTP headers.
|
|
2355
|
-
*
|
|
2356
|
-
* Called synchronously before each fetch request to custom backends.
|
|
2357
|
-
* Return empty object {} to send no custom headers.
|
|
2358
|
-
*
|
|
2359
|
-
* **Note**: Only applies to `custom` integration (not TraceLog SaaS).
|
|
2360
|
-
* Headers are NOT applied to sendBeacon requests (page unload).
|
|
2361
|
-
*
|
|
2362
|
-
* @returns Record of header names to values
|
|
2363
|
-
*
|
|
2364
|
-
* @example
|
|
2365
|
-
* ```typescript
|
|
2366
|
-
* tracelog.setCustomHeaders(() => ({
|
|
2367
|
-
* 'Authorization': `Bearer ${getAuthToken()}`,
|
|
2368
|
-
* 'X-Request-ID': crypto.randomUUID()
|
|
2369
|
-
* }));
|
|
2370
|
-
* ```
|
|
2371
|
-
*/
|
|
2372
|
-
type CustomHeadersProvider = () => Record<string, string>;
|
|
2373
1856
|
|
|
2374
1857
|
/**
|
|
2375
1858
|
* Testing bridge interface for E2E and integration tests
|
|
@@ -2384,25 +1867,16 @@ interface TraceLogTestBridge {
|
|
|
2384
1867
|
readonly initialized: boolean;
|
|
2385
1868
|
init(config?: Config): Promise<InitResult>;
|
|
2386
1869
|
destroy(force?: boolean): void;
|
|
2387
|
-
sendCustomEvent(name: string, data?: Record<string, unknown> | Record<string, unknown>[]): void;
|
|
2388
|
-
event(name: string, metadata?: Record<string, unknown> | Record<string, unknown>[]): void;
|
|
1870
|
+
sendCustomEvent(name: string, data?: Record<string, unknown> | Record<string, unknown>[], options?: EventOptions): void;
|
|
1871
|
+
event(name: string, metadata?: Record<string, unknown> | Record<string, unknown>[], options?: EventOptions): void;
|
|
2389
1872
|
on(event: string, callback: (data: any) => void): void;
|
|
2390
1873
|
off(event: string, callback: (data: any) => void): void;
|
|
2391
1874
|
get<T extends keyof State>(key: T): State[T];
|
|
2392
1875
|
getFullState(): Readonly<State>;
|
|
2393
1876
|
getState(): Readonly<State>;
|
|
2394
|
-
updateGlobalMetadata(metadata: Record<string, unknown>): void;
|
|
2395
|
-
mergeGlobalMetadata(metadata: Record<string, unknown>): void;
|
|
2396
1877
|
getSessionData(): Record<string, unknown> | null;
|
|
2397
1878
|
getQueueLength(): number;
|
|
2398
1879
|
getQueueEvents(): EventData[];
|
|
2399
|
-
setQaMode(enabled: boolean): void;
|
|
2400
|
-
setTransformer(hook: 'beforeSend', fn: BeforeSendTransformer): void;
|
|
2401
|
-
setTransformer(hook: 'beforeBatch', fn: BeforeBatchTransformer): void;
|
|
2402
|
-
setTransformer(hook: TransformerHook, fn: BeforeSendTransformer | BeforeBatchTransformer): void;
|
|
2403
|
-
removeTransformer(hook: TransformerHook): void;
|
|
2404
|
-
setCustomHeaders(provider: CustomHeadersProvider): void;
|
|
2405
|
-
removeCustomHeaders(): void;
|
|
2406
1880
|
getEventManager(): EventManager | undefined;
|
|
2407
1881
|
getStorageManager(): StorageManager | null;
|
|
2408
1882
|
getPerformanceHandler(): PerformanceHandler | null;
|
|
@@ -2411,7 +1885,6 @@ interface TraceLogTestBridge {
|
|
|
2411
1885
|
getPageViewHandler(): PageViewHandler | null;
|
|
2412
1886
|
getClickHandler(): ClickHandler | null;
|
|
2413
1887
|
getScrollHandler(): ScrollHandler | null;
|
|
2414
|
-
getViewportHandler(): ViewportHandler | null;
|
|
2415
1888
|
getHandlers(): {
|
|
2416
1889
|
performance: PerformanceHandler | null;
|
|
2417
1890
|
error: ErrorHandler | null;
|
|
@@ -2419,7 +1892,6 @@ interface TraceLogTestBridge {
|
|
|
2419
1892
|
pageView: PageViewHandler | null;
|
|
2420
1893
|
click: ClickHandler | null;
|
|
2421
1894
|
scroll: ScrollHandler | null;
|
|
2422
|
-
viewport: ViewportHandler | null;
|
|
2423
1895
|
};
|
|
2424
1896
|
identify(userId: string, traits?: Record<string, string>): void;
|
|
2425
1897
|
resetIdentity(): Promise<void>;
|
|
@@ -2487,31 +1959,6 @@ declare global {
|
|
|
2487
1959
|
}
|
|
2488
1960
|
}
|
|
2489
1961
|
|
|
2490
|
-
/**
|
|
2491
|
-
* Transforms events at runtime before sending to custom backend.
|
|
2492
|
-
*
|
|
2493
|
-
* Note: Only applies to custom backend integration. TraceLog SaaS ignores transformers.
|
|
2494
|
-
*
|
|
2495
|
-
* @param hook - 'beforeSend' (per-event) or 'beforeBatch' (batch-level)
|
|
2496
|
-
* @param fn - Transformer function. Return null to filter event/batch.
|
|
2497
|
-
* @throws {Error} If called during destroy()
|
|
2498
|
-
* @throws {Error} If fn is not a function
|
|
2499
|
-
*
|
|
2500
|
-
* @example
|
|
2501
|
-
* ```typescript
|
|
2502
|
-
* tracelog.setTransformer('beforeSend', (data) => {
|
|
2503
|
-
* if ('type' in data) {
|
|
2504
|
-
* return { ...data, appVersion: '1.0.0' };
|
|
2505
|
-
* }
|
|
2506
|
-
* return data;
|
|
2507
|
-
* });
|
|
2508
|
-
* ```
|
|
2509
|
-
*
|
|
2510
|
-
* @see {@link https://github.com/tracelog/tracelog-lib/blob/main/API_REFERENCE.md#settransformer} for integration behavior
|
|
2511
|
-
*/
|
|
2512
|
-
declare function setTransformer(hook: 'beforeSend', fn: BeforeSendTransformer): void;
|
|
2513
|
-
declare function setTransformer(hook: 'beforeBatch', fn: BeforeBatchTransformer): void;
|
|
2514
|
-
|
|
2515
1962
|
/**
|
|
2516
1963
|
* Consolidated configuration constants for TraceLog
|
|
2517
1964
|
* This file centralizes all timing, limits, browser, and initialization constants
|
|
@@ -2526,16 +1973,6 @@ declare const MAX_STRING_LENGTH = 1000;
|
|
|
2526
1973
|
declare const MAX_STRING_LENGTH_IN_ARRAY = 500;
|
|
2527
1974
|
declare const MAX_ARRAY_LENGTH = 1000;
|
|
2528
1975
|
|
|
2529
|
-
/**
|
|
2530
|
-
* Error handling and PII sanitization constants for TraceLog
|
|
2531
|
-
* Centralizes patterns and limits for error tracking and data protection
|
|
2532
|
-
*/
|
|
2533
|
-
/**
|
|
2534
|
-
* Regular expressions for detecting and sanitizing Personally Identifiable Information (PII)
|
|
2535
|
-
* These patterns are used to replace sensitive information with [REDACTED] in error messages
|
|
2536
|
-
*/
|
|
2537
|
-
declare const PII_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
2538
|
-
|
|
2539
1976
|
/**
|
|
2540
1977
|
* Performance monitoring and web vitals constants for TraceLog
|
|
2541
1978
|
* Centralizes thresholds and configuration for performance tracking
|
|
@@ -2543,20 +1980,15 @@ declare const PII_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, Re
|
|
|
2543
1980
|
|
|
2544
1981
|
/**
|
|
2545
1982
|
* Web Vitals "good" thresholds (75th percentile boundaries)
|
|
2546
|
-
* Metrics below or equal to these values are considered good performance.
|
|
2547
1983
|
* Reference: https://web.dev/articles/vitals
|
|
2548
1984
|
*/
|
|
2549
1985
|
declare const WEB_VITALS_GOOD_THRESHOLDS: Record<WebVitalType, number>;
|
|
2550
1986
|
/**
|
|
2551
1987
|
* Web Vitals "needs improvement" thresholds
|
|
2552
|
-
* Metrics exceeding these values need attention but aren't critically poor.
|
|
2553
|
-
* Reference: https://web.dev/articles/vitals
|
|
2554
1988
|
*/
|
|
2555
1989
|
declare const WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS: Record<WebVitalType, number>;
|
|
2556
1990
|
/**
|
|
2557
1991
|
* Web Vitals "poor" thresholds
|
|
2558
|
-
* Metrics exceeding these values indicate poor performance requiring immediate attention.
|
|
2559
|
-
* Reference: https://web.dev/articles/vitals
|
|
2560
1992
|
*/
|
|
2561
1993
|
declare const WEB_VITALS_POOR_THRESHOLDS: Record<WebVitalType, number>;
|
|
2562
1994
|
/**
|
|
@@ -2572,21 +2004,15 @@ declare const getWebVitalsThresholds: (mode?: WebVitalsMode) => Record<WebVitalT
|
|
|
2572
2004
|
|
|
2573
2005
|
declare const tracelog: {
|
|
2574
2006
|
init: (config?: Config) => Promise<InitResult>;
|
|
2575
|
-
event: (name: string, metadata?: Record<string, MetadataType> | Record<string, MetadataType>[]) => void;
|
|
2007
|
+
event: (name: string, metadata?: Record<string, MetadataType> | Record<string, MetadataType>[], options?: EventOptions) => void;
|
|
2576
2008
|
on: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
|
|
2577
2009
|
off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
|
|
2578
|
-
setTransformer: typeof setTransformer;
|
|
2579
|
-
removeTransformer: (hook: TransformerHook) => void;
|
|
2580
|
-
setCustomHeaders: (provider: CustomHeadersProvider) => void;
|
|
2581
|
-
removeCustomHeaders: () => void;
|
|
2582
2010
|
isInitialized: () => boolean;
|
|
2583
2011
|
getSessionId: () => string | null;
|
|
2012
|
+
getUserId: () => string | null;
|
|
2584
2013
|
destroy: () => void;
|
|
2585
|
-
setQaMode: (enabled: boolean) => void;
|
|
2586
|
-
updateGlobalMetadata: (metadata: Record<string, MetadataType>) => void;
|
|
2587
|
-
mergeGlobalMetadata: (metadata: Record<string, MetadataType>) => void;
|
|
2588
2014
|
identify: (userId: string, traits?: Record<string, string>) => void;
|
|
2589
2015
|
resetIdentity: () => Promise<void>;
|
|
2590
2016
|
};
|
|
2591
2017
|
|
|
2592
|
-
export { AppConfigValidationError, type
|
|
2018
|
+
export { AppConfigValidationError, type ClickCoordinates, type ClickData, type ClickTrackingElementData, type Config, type CustomEventData, DEFAULT_SESSION_TIMEOUT, DEFAULT_WEB_VITALS_MODE, type DeviceInfo, DeviceType, type EmitterCallback, EmitterEvent, type EmitterMap, type ErrorData, ErrorType, type EventData, type EventOptions, EventType, type EventTypeName, type EventsQueue, type IdentifyData, type InitResult, InitializationTimeoutError, IntegrationValidationError, MAX_ARRAY_LENGTH, MAX_CUSTOM_EVENT_ARRAY_SIZE, MAX_CUSTOM_EVENT_KEYS, MAX_CUSTOM_EVENT_NAME_LENGTH, MAX_CUSTOM_EVENT_STRING_SIZE, MAX_NESTED_OBJECT_KEYS, MAX_STRING_LENGTH, MAX_STRING_LENGTH_IN_ARRAY, type MetadataType, Mode, PII_PATTERNS, type PageViewData, PermanentError, type PersistedEventsQueue, type QueueMetadata, type QueuedEvent, RateLimitError, SamplingRateValidationError, type ScrollData, ScrollDirection, type SessionEventCounts, SessionTimeoutValidationError, SpecialApiUrl, type State, TimeoutError, type TraceLogTestBridge, TraceLogValidationError, type UTM, WEB_VITALS_GOOD_THRESHOLDS, WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS, WEB_VITALS_POOR_THRESHOLDS, type WebVitalType, type WebVitalsData, type WebVitalsMode, getWebVitalsThresholds, tracelog };
|