@v-tilt/browser 1.9.0 → 1.10.1
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/dist/all-external-dependencies.js.map +1 -1
- package/dist/array.full.js +1 -1
- package/dist/array.full.js.map +1 -1
- package/dist/array.js +1 -1
- package/dist/array.js.map +1 -1
- package/dist/array.no-external.js +1 -1
- package/dist/array.no-external.js.map +1 -1
- package/dist/autocapture-types.d.ts +119 -0
- package/dist/autocapture-utils.d.ts +85 -0
- package/dist/autocapture.d.ts +41 -0
- package/dist/chat.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/core/capture.d.ts +70 -0
- package/dist/core/feature-manager.d.ts +95 -0
- package/dist/core/identity.d.ts +77 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/remote-config.d.ts +50 -0
- package/dist/extensions/chat/chat-wrapper.d.ts +36 -10
- package/dist/extensions/history-autocapture.d.ts +34 -7
- package/dist/extensions/replay/session-recording-wrapper.d.ts +42 -11
- package/dist/extensions/replay/types.d.ts +1 -1
- package/dist/extensions/web-vitals/index.d.ts +7 -0
- package/dist/extensions/web-vitals/web-vitals-manager.d.ts +81 -0
- package/dist/external-scripts-loader.js.map +1 -1
- package/dist/feature.d.ts +231 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.d.ts +802 -324
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/dist/module.no-external.d.ts +802 -324
- package/dist/module.no-external.js +1 -1
- package/dist/module.no-external.js.map +1 -1
- package/dist/recorder.js.map +1 -1
- package/dist/server.d.ts +6 -0
- package/dist/types.d.ts +66 -2
- package/dist/utils/event-emitter.d.ts +106 -0
- package/dist/utils/globals.d.ts +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/safewrap.d.ts +101 -0
- package/dist/utils/type-guards.d.ts +70 -0
- package/dist/vtilt.d.ts +66 -336
- package/dist/web-vitals.d.ts +39 -53
- package/dist/web-vitals.js.map +1 -1
- package/package.json +1 -1
package/dist/module.d.ts
CHANGED
|
@@ -56,8 +56,12 @@ interface VTiltConfig {
|
|
|
56
56
|
* - 'never': Never create person profiles
|
|
57
57
|
*/
|
|
58
58
|
person_profiles?: PersonProfilesMode;
|
|
59
|
-
/**
|
|
60
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Enable autocapture for automatic DOM event tracking.
|
|
61
|
+
* Can be a boolean or an object with detailed configuration.
|
|
62
|
+
* When true, captures clicks, form submissions, and input changes.
|
|
63
|
+
*/
|
|
64
|
+
autocapture?: boolean | AutocaptureOptions;
|
|
61
65
|
/**
|
|
62
66
|
* Enable web vitals tracking.
|
|
63
67
|
* Can be a boolean or an object with detailed configuration.
|
|
@@ -67,6 +71,8 @@ interface VTiltConfig {
|
|
|
67
71
|
capture_pageview?: boolean | "auto";
|
|
68
72
|
/** Enable page leave tracking */
|
|
69
73
|
capture_pageleave?: boolean | "if_capture_pageview";
|
|
74
|
+
/** Enable rage click detection (rapid clicks in same area) */
|
|
75
|
+
rageclick?: boolean;
|
|
70
76
|
/** Disable compression */
|
|
71
77
|
disable_compression?: boolean;
|
|
72
78
|
/** Whether to stringify payload before sending */
|
|
@@ -230,6 +236,58 @@ interface RequestOptions {
|
|
|
230
236
|
timeout?: number;
|
|
231
237
|
retry?: boolean;
|
|
232
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Autocapture configuration options
|
|
241
|
+
* Controls automatic DOM event tracking (clicks, form submissions, input changes)
|
|
242
|
+
*/
|
|
243
|
+
interface AutocaptureOptions {
|
|
244
|
+
/**
|
|
245
|
+
* Enable autocapture (default: true when autocapture config is present)
|
|
246
|
+
*/
|
|
247
|
+
enabled?: boolean;
|
|
248
|
+
/**
|
|
249
|
+
* URL patterns to allow autocapture on (default: all URLs)
|
|
250
|
+
* Supports strings (exact match) and RegExp patterns
|
|
251
|
+
*/
|
|
252
|
+
url_allowlist?: (string | RegExp)[];
|
|
253
|
+
/**
|
|
254
|
+
* URL patterns to exclude from autocapture
|
|
255
|
+
* Supports strings (exact match) and RegExp patterns
|
|
256
|
+
*/
|
|
257
|
+
url_ignorelist?: (string | RegExp)[];
|
|
258
|
+
/**
|
|
259
|
+
* DOM events to capture (default: ['click', 'change', 'submit'])
|
|
260
|
+
*/
|
|
261
|
+
dom_event_allowlist?: ("click" | "change" | "submit")[];
|
|
262
|
+
/**
|
|
263
|
+
* Element tags to capture (default: ['a', 'button', 'form', 'input', 'select', 'textarea', 'label'])
|
|
264
|
+
*/
|
|
265
|
+
element_allowlist?: string[];
|
|
266
|
+
/**
|
|
267
|
+
* CSS selectors to allow for capture (elements matching these are always captured)
|
|
268
|
+
* Example: ['[data-track]', '.track-click']
|
|
269
|
+
*/
|
|
270
|
+
css_selector_allowlist?: string[];
|
|
271
|
+
/**
|
|
272
|
+
* Element attributes to exclude from capture
|
|
273
|
+
* Example: ['data-secret', 'aria-label']
|
|
274
|
+
*/
|
|
275
|
+
element_attribute_ignorelist?: string[];
|
|
276
|
+
/**
|
|
277
|
+
* Capture text content from copy/cut events (default: false)
|
|
278
|
+
*/
|
|
279
|
+
capture_copied_text?: boolean;
|
|
280
|
+
/**
|
|
281
|
+
* Mask all text content in captured elements (use placeholder).
|
|
282
|
+
* Overrides VTiltConfig.mask_all_text for autocapture specifically.
|
|
283
|
+
*/
|
|
284
|
+
mask_all_text?: boolean;
|
|
285
|
+
/**
|
|
286
|
+
* Mask all element attributes (only safe attributes or none).
|
|
287
|
+
* Overrides VTiltConfig.mask_all_element_attributes for autocapture specifically.
|
|
288
|
+
*/
|
|
289
|
+
mask_all_element_attributes?: boolean;
|
|
290
|
+
}
|
|
233
291
|
/** Mask options for input elements in session recording */
|
|
234
292
|
interface SessionRecordingMaskInputOptions {
|
|
235
293
|
color?: boolean;
|
|
@@ -330,6 +388,8 @@ interface RemoteConfig {
|
|
|
330
388
|
enabled?: boolean;
|
|
331
389
|
sampleRate?: number;
|
|
332
390
|
minimumDurationMs?: number;
|
|
391
|
+
/** Full DOM snapshot interval in ms (default 300000 = 5 min). Higher = less data. */
|
|
392
|
+
fullSnapshotIntervalMs?: number;
|
|
333
393
|
maskAllInputs?: boolean;
|
|
334
394
|
maskAllText?: boolean;
|
|
335
395
|
captureConsole?: boolean;
|
|
@@ -356,23 +416,508 @@ interface RemoteConfig {
|
|
|
356
416
|
ipAnonymization?: boolean;
|
|
357
417
|
};
|
|
358
418
|
featureFlags?: FeatureFlagsConfig;
|
|
419
|
+
/** Whether to send elements as chain string (PostHog compatibility) */
|
|
420
|
+
elementsChainAsString?: boolean;
|
|
421
|
+
/** Server-side autocapture opt-out */
|
|
422
|
+
autocapture_opt_out?: boolean;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Session Manager - Handles session_id and window_id
|
|
427
|
+
*
|
|
428
|
+
* Uses shared StorageManager for consistent storage operations.
|
|
429
|
+
*
|
|
430
|
+
* Session ID: Unique per user session, expires after 30 minutes of inactivity
|
|
431
|
+
* Window ID: Unique per browser tab, persists across page reloads
|
|
432
|
+
*/
|
|
433
|
+
|
|
434
|
+
declare class SessionManager {
|
|
435
|
+
private storage;
|
|
436
|
+
private _windowId;
|
|
437
|
+
constructor(storageMethod?: PersistenceMethod, cross_subdomain?: boolean);
|
|
438
|
+
/**
|
|
439
|
+
* Get session ID (always returns a value, generates if needed)
|
|
440
|
+
*/
|
|
441
|
+
getSessionId(): string;
|
|
442
|
+
/**
|
|
443
|
+
* Set session ID in storage
|
|
444
|
+
* Extends TTL if session_id exists, generates new one if not
|
|
445
|
+
*/
|
|
446
|
+
setSessionId(): string;
|
|
447
|
+
/**
|
|
448
|
+
* Reset session ID (generates new session on reset)
|
|
449
|
+
*/
|
|
450
|
+
resetSessionId(): void;
|
|
451
|
+
/**
|
|
452
|
+
* Get session ID from storage (raw, can return null)
|
|
453
|
+
* Cookie Max-Age handles expiration automatically
|
|
454
|
+
*/
|
|
455
|
+
private _getSessionIdRaw;
|
|
456
|
+
/**
|
|
457
|
+
* Store session ID
|
|
458
|
+
* Uses plain string format - cookie Max-Age handles expiration
|
|
459
|
+
*/
|
|
460
|
+
private _storeSessionId;
|
|
461
|
+
/**
|
|
462
|
+
* Clear session ID from storage
|
|
463
|
+
*/
|
|
464
|
+
private _clearSessionId;
|
|
465
|
+
/**
|
|
466
|
+
* Get window ID
|
|
467
|
+
* Window ID is unique per browser tab/window and persists across page reloads
|
|
468
|
+
* Always returns a window_id (generates one if not set)
|
|
469
|
+
*/
|
|
470
|
+
getWindowId(): string;
|
|
471
|
+
/**
|
|
472
|
+
* Set window ID
|
|
473
|
+
* Stores in sessionStorage which is unique per tab
|
|
474
|
+
*/
|
|
475
|
+
private _setWindowId;
|
|
476
|
+
/**
|
|
477
|
+
* Initialize window ID
|
|
478
|
+
* Detects tab duplication and handles window_id persistence
|
|
479
|
+
*/
|
|
480
|
+
private _initializeWindowId;
|
|
481
|
+
/**
|
|
482
|
+
* Listen to window unload to clear primary window flag
|
|
483
|
+
* This helps distinguish between page reloads and tab duplication
|
|
484
|
+
*/
|
|
485
|
+
private _listenToUnload;
|
|
486
|
+
/**
|
|
487
|
+
* Update storage method at runtime
|
|
488
|
+
*/
|
|
489
|
+
updateStorageMethod(method: PersistenceMethod, cross_subdomain?: boolean): void;
|
|
359
490
|
}
|
|
360
491
|
|
|
361
492
|
/**
|
|
362
|
-
*
|
|
363
|
-
*
|
|
493
|
+
* User Manager - Handles user identity and properties
|
|
494
|
+
*
|
|
495
|
+
* Uses shared StorageManager for consistent storage operations.
|
|
496
|
+
*
|
|
497
|
+
* Manages:
|
|
498
|
+
* - anonymous_id: Generated ID for anonymous users
|
|
499
|
+
* - distinct_id: User-provided ID after identification
|
|
500
|
+
* - device_id: Persistent device identifier
|
|
501
|
+
* - user_properties: Custom properties set via identify/setUserProperties
|
|
502
|
+
* - user_state: "anonymous" or "identified"
|
|
364
503
|
*/
|
|
365
|
-
|
|
504
|
+
|
|
505
|
+
declare class UserManager {
|
|
506
|
+
private storage;
|
|
507
|
+
private userIdentity;
|
|
508
|
+
private _cachedPersonProperties;
|
|
509
|
+
constructor(storageMethod?: PersistenceMethod, cross_subdomain?: boolean);
|
|
510
|
+
/**
|
|
511
|
+
* Get current user identity
|
|
512
|
+
*/
|
|
513
|
+
getUserIdentity(): UserIdentity;
|
|
514
|
+
/**
|
|
515
|
+
* Get current distinct ID (identified user ID)
|
|
516
|
+
*/
|
|
517
|
+
getDistinctId(): string | null;
|
|
518
|
+
/**
|
|
519
|
+
* Get current anonymous ID
|
|
520
|
+
*/
|
|
521
|
+
getAnonymousId(): string;
|
|
522
|
+
/**
|
|
523
|
+
* Get current user properties
|
|
524
|
+
*/
|
|
525
|
+
getUserProperties(): Record<string, any>;
|
|
526
|
+
/**
|
|
527
|
+
* Get the effective ID for event tracking
|
|
528
|
+
*/
|
|
529
|
+
getEffectiveId(): string;
|
|
530
|
+
/**
|
|
531
|
+
* Get current device ID
|
|
532
|
+
*/
|
|
533
|
+
getDeviceId(): string;
|
|
534
|
+
/**
|
|
535
|
+
* Get current user state
|
|
536
|
+
*/
|
|
537
|
+
getUserState(): "anonymous" | "identified";
|
|
538
|
+
/**
|
|
539
|
+
* Identify a user with distinct ID and properties
|
|
540
|
+
*/
|
|
541
|
+
identify(newDistinctId?: string, userPropertiesToSet?: Record<string, any>, userPropertiesToSetOnce?: Record<string, any>): void;
|
|
542
|
+
/**
|
|
543
|
+
* Set user properties without changing distinct ID
|
|
544
|
+
*/
|
|
545
|
+
setUserProperties(userPropertiesToSet?: Record<string, any>, userPropertiesToSetOnce?: Record<string, any>): boolean;
|
|
546
|
+
/**
|
|
547
|
+
* Reset user identity (logout)
|
|
548
|
+
* Generates new anonymous ID, clears user data, optionally resets device ID
|
|
549
|
+
*/
|
|
550
|
+
reset(reset_device_id?: boolean): void;
|
|
551
|
+
/**
|
|
552
|
+
* Update distinct ID (internal use - for VTilt)
|
|
553
|
+
*/
|
|
554
|
+
setDistinctId(distinctId: string): void;
|
|
555
|
+
/**
|
|
556
|
+
* Update user state (internal use - for VTilt)
|
|
557
|
+
*/
|
|
558
|
+
setUserState(state: "anonymous" | "identified"): void;
|
|
559
|
+
/**
|
|
560
|
+
* Update user properties (internal use - for VTilt)
|
|
561
|
+
*/
|
|
562
|
+
updateUserProperties(userPropertiesToSet?: Record<string, any>, userPropertiesToSetOnce?: Record<string, any>): void;
|
|
563
|
+
/**
|
|
564
|
+
* Set device ID if not already set (internal use - for VTilt)
|
|
565
|
+
*/
|
|
566
|
+
ensureDeviceId(deviceId: string): void;
|
|
567
|
+
/**
|
|
568
|
+
* Create an alias to link two distinct IDs
|
|
569
|
+
*/
|
|
570
|
+
createAlias(alias: string, original?: string): AliasEvent | null;
|
|
571
|
+
/**
|
|
572
|
+
* Check if distinct ID is string-like (hardcoded string) - public for validation
|
|
573
|
+
*/
|
|
574
|
+
isDistinctIdStringLikePublic(distinctId: string): boolean;
|
|
575
|
+
/**
|
|
576
|
+
* Set initial person info
|
|
577
|
+
*/
|
|
578
|
+
set_initial_person_info(maskPersonalDataProperties?: boolean, customPersonalDataProperties?: string[]): void;
|
|
579
|
+
/**
|
|
580
|
+
* Get initial props
|
|
581
|
+
*/
|
|
582
|
+
get_initial_props(): Record<string, any>;
|
|
583
|
+
/**
|
|
584
|
+
* Update referrer info
|
|
585
|
+
*/
|
|
586
|
+
update_referrer_info(): void;
|
|
587
|
+
/**
|
|
588
|
+
* Load user identity from storage.
|
|
589
|
+
*
|
|
590
|
+
* For traditional SSR websites where each page navigation reloads JavaScript,
|
|
591
|
+
* identity MUST be persisted immediately when generated to ensure the same
|
|
592
|
+
* anonymous_id is used across all page loads.
|
|
593
|
+
*
|
|
594
|
+
* Flow:
|
|
595
|
+
* 1. Load from storage (reads cookies first for critical properties in SSR mode)
|
|
596
|
+
* 2. Generate new IDs if not found
|
|
597
|
+
* 3. Immediately persist to storage (saved to both localStorage and cookies)
|
|
598
|
+
*
|
|
599
|
+
* With `localStorage+cookie` persistence (default):
|
|
600
|
+
* - Critical properties are stored in cookies for SSR compatibility
|
|
601
|
+
* - Full data is stored in localStorage for fast SPA-style access
|
|
602
|
+
* - Cookies ensure identity persists across full page reloads
|
|
603
|
+
*/
|
|
604
|
+
private loadUserIdentity;
|
|
605
|
+
/**
|
|
606
|
+
* Save user identity to storage
|
|
607
|
+
*/
|
|
608
|
+
private saveUserIdentity;
|
|
609
|
+
/**
|
|
610
|
+
* Get user properties from storage
|
|
611
|
+
*/
|
|
612
|
+
private getStoredUserProperties;
|
|
613
|
+
/**
|
|
614
|
+
* Set user properties in storage
|
|
615
|
+
*/
|
|
616
|
+
private setStoredUserProperties;
|
|
617
|
+
/**
|
|
618
|
+
* Register a value once (only if not already set)
|
|
619
|
+
*/
|
|
620
|
+
private register_once;
|
|
621
|
+
/**
|
|
622
|
+
* Generate a new anonymous ID
|
|
623
|
+
*/
|
|
624
|
+
private generateAnonymousId;
|
|
625
|
+
/**
|
|
626
|
+
* Generate a new device ID
|
|
627
|
+
*/
|
|
628
|
+
private generateDeviceId;
|
|
629
|
+
/**
|
|
630
|
+
* Get hash for person properties (for deduplication)
|
|
631
|
+
*/
|
|
632
|
+
private getPersonPropertiesHash;
|
|
633
|
+
/**
|
|
634
|
+
* Validate distinct ID
|
|
635
|
+
*/
|
|
636
|
+
private isValidDistinctId;
|
|
637
|
+
/**
|
|
638
|
+
* Check if distinct ID is string-like (hardcoded string)
|
|
639
|
+
*/
|
|
640
|
+
private isDistinctIdStringLike;
|
|
641
|
+
/**
|
|
642
|
+
* Update storage method at runtime
|
|
643
|
+
*/
|
|
644
|
+
updateStorageMethod(method: PersistenceMethod, cross_subdomain?: boolean): void;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Feature Interface & Base Class
|
|
649
|
+
*
|
|
650
|
+
* Standard interface that all vTilt features implement.
|
|
651
|
+
* Provides consistent lifecycle management and self-contained configuration.
|
|
652
|
+
*
|
|
653
|
+
* Design Principles:
|
|
654
|
+
* 1. Features are self-contained - they extract their own config
|
|
655
|
+
* 2. Features implement a common interface - vtilt.ts doesn't need to know details
|
|
656
|
+
* 3. Features handle their own errors - using safewrap utilities
|
|
657
|
+
* 4. Features can communicate via events - using the event emitter
|
|
658
|
+
*
|
|
659
|
+
* Based on PostHog's convention patterns, formalized as TypeScript interfaces.
|
|
660
|
+
*/
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Feature interface that all vTilt features should implement.
|
|
664
|
+
* Provides a consistent lifecycle for feature initialization and management.
|
|
665
|
+
*
|
|
666
|
+
* @example
|
|
667
|
+
* ```typescript
|
|
668
|
+
* class MyFeature implements Feature {
|
|
669
|
+
* static extractConfig(config: VTiltConfig): MyFeatureConfig {
|
|
670
|
+
* return { enabled: !!config.myFeature };
|
|
671
|
+
* }
|
|
672
|
+
*
|
|
673
|
+
* get isEnabled(): boolean { return this._config.enabled; }
|
|
674
|
+
* get isStarted(): boolean { return this._started; }
|
|
675
|
+
*
|
|
676
|
+
* startIfEnabled(): void {
|
|
677
|
+
* if (this.isEnabled && !this._started) {
|
|
678
|
+
* this._start();
|
|
679
|
+
* }
|
|
680
|
+
* }
|
|
681
|
+
*
|
|
682
|
+
* stop(): void {
|
|
683
|
+
* if (this._started) {
|
|
684
|
+
* this._cleanup();
|
|
685
|
+
* this._started = false;
|
|
686
|
+
* }
|
|
687
|
+
* }
|
|
688
|
+
* }
|
|
689
|
+
* ```
|
|
690
|
+
*/
|
|
691
|
+
interface Feature {
|
|
692
|
+
/**
|
|
693
|
+
* Feature name for logging and debugging.
|
|
694
|
+
*/
|
|
695
|
+
readonly name: string;
|
|
696
|
+
/**
|
|
697
|
+
* Check if the feature is enabled based on current configuration.
|
|
698
|
+
* Features should check both local config and remote config.
|
|
699
|
+
*/
|
|
700
|
+
readonly isEnabled: boolean;
|
|
701
|
+
/**
|
|
702
|
+
* Check if the feature is currently started/active.
|
|
703
|
+
*/
|
|
704
|
+
readonly isStarted: boolean;
|
|
705
|
+
/**
|
|
706
|
+
* Start the feature if it's enabled, otherwise do nothing.
|
|
707
|
+
* This is the primary lifecycle method called during initialization.
|
|
708
|
+
*
|
|
709
|
+
* Safe to call multiple times - should be idempotent.
|
|
710
|
+
*/
|
|
711
|
+
startIfEnabled(): void;
|
|
712
|
+
/**
|
|
713
|
+
* Stop the feature and clean up any resources (event listeners, timers, etc.).
|
|
714
|
+
* Safe to call multiple times - should be idempotent.
|
|
715
|
+
*/
|
|
716
|
+
stop(): void;
|
|
717
|
+
/**
|
|
718
|
+
* Handle VTilt configuration updates.
|
|
719
|
+
* Called when the main VTilt config is updated via updateConfig().
|
|
720
|
+
*
|
|
721
|
+
* Features should re-evaluate their enabled state and start/stop accordingly.
|
|
722
|
+
*
|
|
723
|
+
* @param config - The new VTilt configuration
|
|
724
|
+
*/
|
|
725
|
+
onConfigUpdate?(config: VTiltConfig): void;
|
|
726
|
+
/**
|
|
727
|
+
* Handle remote configuration updates from /decide endpoint.
|
|
728
|
+
* Called when new remote config is received from the server.
|
|
729
|
+
*
|
|
730
|
+
* Features can use this to enable/disable themselves based on server settings.
|
|
731
|
+
*
|
|
732
|
+
* @param remoteConfig - The remote configuration response
|
|
733
|
+
*/
|
|
734
|
+
onRemoteConfig?(remoteConfig: RemoteConfig): void;
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Feature with the startIfEnabledOrStop pattern.
|
|
738
|
+
* Used for features that should stop when disabled (not just stay stopped).
|
|
739
|
+
*
|
|
740
|
+
* Example: Session recording should stop if disabled mid-session.
|
|
741
|
+
*/
|
|
742
|
+
interface ToggleableFeature extends Feature {
|
|
743
|
+
/**
|
|
744
|
+
* Start the feature if enabled, or stop it if disabled.
|
|
745
|
+
* More aggressive than startIfEnabled - actively stops if conditions change.
|
|
746
|
+
*
|
|
747
|
+
* @param trigger - Optional trigger name for debugging
|
|
748
|
+
*/
|
|
749
|
+
startIfEnabledOrStop(trigger?: string): void;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Base configuration that all features receive.
|
|
753
|
+
* Features extend this for their specific config needs.
|
|
754
|
+
*/
|
|
755
|
+
interface FeatureConfig {
|
|
756
|
+
/** Whether the feature is enabled */
|
|
757
|
+
enabled?: boolean;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* Web Vitals Manager
|
|
762
|
+
*
|
|
763
|
+
* Captures Core Web Vitals (LCP, CLS, FCP, INP, TTFB) and sends them
|
|
764
|
+
* as batched $web_vitals events. Implements the Feature interface for
|
|
765
|
+
* consistent lifecycle management.
|
|
766
|
+
*
|
|
767
|
+
* Follows PostHog's approach with:
|
|
768
|
+
* 1. Extension pattern - checks for callbacks registered on __VTiltExtensions__
|
|
769
|
+
* 2. Lazy loading - loads web-vitals.js on demand if not bundled
|
|
770
|
+
* 3. Configurable metrics - choose which metrics to capture
|
|
771
|
+
* 4. Smart buffering - collects metrics per page, flushes on navigation or timeout
|
|
772
|
+
* 5. Session context - includes session_id and window_id for correlation
|
|
773
|
+
*
|
|
774
|
+
* Event structure:
|
|
775
|
+
* - event: "$web_vitals"
|
|
776
|
+
* - properties:
|
|
777
|
+
* - $web_vitals_LCP_value: number
|
|
778
|
+
* - $web_vitals_LCP_event: { name, value, delta, rating, ... }
|
|
779
|
+
* - $pathname: string
|
|
780
|
+
* - $current_url: string
|
|
781
|
+
*/
|
|
782
|
+
|
|
783
|
+
declare class WebVitalsManager implements Feature {
|
|
784
|
+
readonly name = "WebVitals";
|
|
366
785
|
private _instance;
|
|
786
|
+
private _buffer;
|
|
787
|
+
private _flushTimer;
|
|
788
|
+
private _isStarted;
|
|
789
|
+
private _config;
|
|
790
|
+
/**
|
|
791
|
+
* Extract web vitals config from VTiltConfig (self-contained)
|
|
792
|
+
*/
|
|
793
|
+
static extractConfig(config: VTiltConfig): CapturePerformanceConfig;
|
|
794
|
+
constructor(instance: VTilt);
|
|
795
|
+
/**
|
|
796
|
+
* Check if web vitals capture is enabled
|
|
797
|
+
*/
|
|
798
|
+
get isEnabled(): boolean;
|
|
799
|
+
/**
|
|
800
|
+
* Check if capturing has started
|
|
801
|
+
*/
|
|
802
|
+
get isStarted(): boolean;
|
|
803
|
+
/**
|
|
804
|
+
* Start capturing if enabled
|
|
805
|
+
*/
|
|
806
|
+
startIfEnabled(): void;
|
|
807
|
+
/**
|
|
808
|
+
* Stop capturing (flushes any pending metrics)
|
|
809
|
+
*/
|
|
810
|
+
stop(): void;
|
|
811
|
+
/**
|
|
812
|
+
* Handle config update
|
|
813
|
+
*/
|
|
814
|
+
onConfigUpdate(config: VTiltConfig): void;
|
|
815
|
+
/**
|
|
816
|
+
* Get the list of metrics to capture
|
|
817
|
+
*/
|
|
818
|
+
get allowedMetrics(): SupportedWebVitalsMetric[];
|
|
819
|
+
/**
|
|
820
|
+
* Get flush timeout in ms
|
|
821
|
+
*/
|
|
822
|
+
get flushTimeoutMs(): number;
|
|
823
|
+
/**
|
|
824
|
+
* Get maximum allowed metric value
|
|
825
|
+
*/
|
|
826
|
+
get maxAllowedValue(): number;
|
|
827
|
+
private _createEmptyBuffer;
|
|
828
|
+
private _getWebVitalsCallbacks;
|
|
829
|
+
private _loadWebVitals;
|
|
830
|
+
private _startCapturing;
|
|
831
|
+
private _getCurrentUrl;
|
|
832
|
+
private _getCurrentPathname;
|
|
833
|
+
private _addToBuffer;
|
|
834
|
+
private _cleanAttribution;
|
|
835
|
+
private _getWindowId;
|
|
836
|
+
private _scheduleFlush;
|
|
837
|
+
private _flush;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/**
|
|
841
|
+
* History Autocapture
|
|
842
|
+
*
|
|
843
|
+
* Captures pageview events when the user navigates using the History API
|
|
844
|
+
* (pushState, replaceState) or browser back/forward buttons.
|
|
845
|
+
*
|
|
846
|
+
* Implements the Feature interface for consistent lifecycle management.
|
|
847
|
+
*/
|
|
848
|
+
|
|
849
|
+
interface HistoryAutocaptureConfig extends FeatureConfig {
|
|
850
|
+
/** Whether to capture pageviews on history changes */
|
|
851
|
+
enabled?: boolean;
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* History Autocapture Feature
|
|
855
|
+
*
|
|
856
|
+
* Automatically captures $pageview events on SPA navigation.
|
|
857
|
+
* Implements the Feature interface for consistent lifecycle management.
|
|
858
|
+
*/
|
|
859
|
+
declare class HistoryAutocapture implements Feature {
|
|
860
|
+
readonly name = "HistoryAutocapture";
|
|
861
|
+
private _instance;
|
|
862
|
+
private _config;
|
|
863
|
+
private _isStarted;
|
|
367
864
|
private _popstateListener;
|
|
368
865
|
private _lastPathname;
|
|
369
|
-
constructor(instance: VTilt);
|
|
866
|
+
constructor(instance: VTilt, config?: HistoryAutocaptureConfig);
|
|
867
|
+
/**
|
|
868
|
+
* Extract history autocapture config from VTiltConfig.
|
|
869
|
+
* Self-contained - vtilt.ts doesn't need to know config details.
|
|
870
|
+
*/
|
|
871
|
+
static extractConfig(config: VTiltConfig): HistoryAutocaptureConfig;
|
|
370
872
|
get isEnabled(): boolean;
|
|
873
|
+
get isStarted(): boolean;
|
|
371
874
|
startIfEnabled(): void;
|
|
372
875
|
stop(): void;
|
|
373
|
-
|
|
374
|
-
private
|
|
876
|
+
onConfigUpdate(config: VTiltConfig): void;
|
|
877
|
+
private _start;
|
|
878
|
+
private _patchHistoryMethods;
|
|
375
879
|
private _setupPopstateListener;
|
|
880
|
+
private _capturePageview;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Autocapture
|
|
885
|
+
*
|
|
886
|
+
* Automatic DOM event capture for clicks, form submissions, and input changes.
|
|
887
|
+
* Privacy-first approach with element chain tracking and sensitive data filtering.
|
|
888
|
+
*/
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Autocapture class for automatic DOM event tracking.
|
|
892
|
+
* Implements the Feature interface for consistent lifecycle management.
|
|
893
|
+
*/
|
|
894
|
+
declare class Autocapture implements Feature {
|
|
895
|
+
readonly name = "Autocapture";
|
|
896
|
+
private _instance;
|
|
897
|
+
private _initialized;
|
|
898
|
+
private _isDisabledServerSide;
|
|
899
|
+
private _elementSelectors;
|
|
900
|
+
private _rageclicks;
|
|
901
|
+
private _elementsChainAsString;
|
|
902
|
+
constructor(instance: VTilt);
|
|
903
|
+
private get _config();
|
|
904
|
+
get isEnabled(): boolean;
|
|
905
|
+
get isStarted(): boolean;
|
|
906
|
+
startIfEnabled(): void;
|
|
907
|
+
stop(): void;
|
|
908
|
+
onConfigUpdate(_config: VTiltConfig): void;
|
|
909
|
+
onRemoteConfig(response: RemoteConfig): void;
|
|
910
|
+
/**
|
|
911
|
+
* Update autocapture configuration (for programmatic control)
|
|
912
|
+
*/
|
|
913
|
+
updateConfig(config: Partial<{
|
|
914
|
+
enabled: boolean;
|
|
915
|
+
}>): void;
|
|
916
|
+
setElementSelectors(selectors: Set<string>): void;
|
|
917
|
+
getElementSelectors(element: Element | null): string[] | null;
|
|
918
|
+
private _addDomEventHandlers;
|
|
919
|
+
private _captureEvent;
|
|
920
|
+
private _isBrowserSupported;
|
|
376
921
|
}
|
|
377
922
|
|
|
378
923
|
/**
|
|
@@ -457,7 +1002,7 @@ interface SessionRecordingConfig {
|
|
|
457
1002
|
__mutationThrottlerBucketSize?: number;
|
|
458
1003
|
}
|
|
459
1004
|
/** Recording start reason */
|
|
460
|
-
type SessionStartReason = "recording_initialized" | "session_id_changed" | "linked_flag_matched" | "linked_flag_overridden" | "sampling_overridden" | "url_trigger_matched" | "event_trigger_matched" | "sampled";
|
|
1005
|
+
type SessionStartReason = "recording_initialized" | "session_id_changed" | "linked_flag_matched" | "linked_flag_overridden" | "sampling_overridden" | "url_trigger_matched" | "event_trigger_matched" | "sampled" | "config_updated" | "remote_config";
|
|
461
1006
|
|
|
462
1007
|
/**
|
|
463
1008
|
* Chat message structure (matches PostgreSQL chat_messages table)
|
|
@@ -596,6 +1141,7 @@ interface ChatTheme {
|
|
|
596
1141
|
* The actual recording logic is in LazyLoadedSessionRecording which is
|
|
597
1142
|
* loaded on demand.
|
|
598
1143
|
*
|
|
1144
|
+
* Implements the ToggleableFeature interface for consistent lifecycle management.
|
|
599
1145
|
* Based on PostHog's sessionrecording-wrapper.ts
|
|
600
1146
|
*/
|
|
601
1147
|
|
|
@@ -608,43 +1154,71 @@ type SessionRecordingStatus = "disabled" | "buffering" | "active" | "paused" | "
|
|
|
608
1154
|
* Session Recording Wrapper
|
|
609
1155
|
*
|
|
610
1156
|
* This is the lightweight class that lives in the main bundle.
|
|
1157
|
+
* Implements ToggleableFeature for consistent lifecycle management.
|
|
1158
|
+
*
|
|
611
1159
|
* It handles:
|
|
612
1160
|
* - Deciding if recording should be enabled
|
|
613
1161
|
* - Lazy loading the actual recording code
|
|
614
1162
|
* - Delegating to LazyLoadedSessionRecording
|
|
615
1163
|
*/
|
|
616
|
-
declare class SessionRecordingWrapper {
|
|
1164
|
+
declare class SessionRecordingWrapper implements ToggleableFeature {
|
|
617
1165
|
private readonly _instance;
|
|
1166
|
+
readonly name = "SessionRecording";
|
|
618
1167
|
private _lazyLoadedRecording;
|
|
619
1168
|
private _config;
|
|
1169
|
+
private _isStarted;
|
|
620
1170
|
constructor(_instance: VTilt, config?: SessionRecordingConfig);
|
|
1171
|
+
/**
|
|
1172
|
+
* Extract session recording config from VTiltConfig.
|
|
1173
|
+
* Self-contained - vtilt.ts doesn't need to know config details.
|
|
1174
|
+
*/
|
|
1175
|
+
static extractConfig(config: VTiltConfig): SessionRecordingConfig;
|
|
1176
|
+
get isEnabled(): boolean;
|
|
1177
|
+
get isStarted(): boolean;
|
|
1178
|
+
/**
|
|
1179
|
+
* Start if enabled (Feature interface).
|
|
1180
|
+
* Use startIfEnabledOrStop for recording as it needs to actively stop.
|
|
1181
|
+
*/
|
|
1182
|
+
startIfEnabled(): void;
|
|
1183
|
+
/**
|
|
1184
|
+
* Start if enabled, or stop if disabled (ToggleableFeature interface).
|
|
1185
|
+
* This is the primary method for session recording.
|
|
1186
|
+
*/
|
|
1187
|
+
startIfEnabledOrStop(trigger?: SessionStartReason): void;
|
|
1188
|
+
/**
|
|
1189
|
+
* Stop recording (Feature interface).
|
|
1190
|
+
*/
|
|
1191
|
+
stop(): void;
|
|
1192
|
+
/**
|
|
1193
|
+
* Handle config updates (Feature interface).
|
|
1194
|
+
*/
|
|
1195
|
+
onConfigUpdate(config: VTiltConfig): void;
|
|
1196
|
+
/**
|
|
1197
|
+
* Handle remote config updates (Feature interface).
|
|
1198
|
+
*/
|
|
1199
|
+
onRemoteConfig(remoteConfig: RemoteConfig): void;
|
|
621
1200
|
get started(): boolean;
|
|
622
1201
|
get status(): SessionRecordingStatus;
|
|
623
1202
|
get sessionId(): string;
|
|
624
1203
|
/**
|
|
625
|
-
*
|
|
626
|
-
*/
|
|
627
|
-
startIfEnabledOrStop(startReason?: SessionStartReason): void;
|
|
628
|
-
/**
|
|
629
|
-
* Stop recording
|
|
1204
|
+
* Alias for stop() for backwards compatibility.
|
|
630
1205
|
*/
|
|
631
1206
|
stopRecording(): void;
|
|
632
1207
|
/**
|
|
633
|
-
* Log a message to the recording
|
|
1208
|
+
* Log a message to the recording.
|
|
634
1209
|
*/
|
|
635
1210
|
log(message: string, level?: "log" | "warn" | "error"): void;
|
|
636
1211
|
/**
|
|
637
|
-
* Update configuration
|
|
1212
|
+
* Update configuration.
|
|
638
1213
|
*/
|
|
639
1214
|
updateConfig(config: Partial<SessionRecordingConfig>): void;
|
|
640
|
-
private get _isRecordingEnabled();
|
|
641
1215
|
private get _scriptName();
|
|
642
1216
|
/**
|
|
643
|
-
* Lazy load the recording script and start
|
|
1217
|
+
* Lazy load the recording script and start.
|
|
644
1218
|
*/
|
|
645
1219
|
private _lazyLoadAndStart;
|
|
646
1220
|
/**
|
|
647
|
-
* Called after the recording script is loaded
|
|
1221
|
+
* Called after the recording script is loaded.
|
|
648
1222
|
*/
|
|
649
1223
|
private _onScriptLoaded;
|
|
650
1224
|
}
|
|
@@ -664,12 +1238,14 @@ type ConnectionCallback = (connected: boolean) => void;
|
|
|
664
1238
|
/**
|
|
665
1239
|
* Unsubscribe function type
|
|
666
1240
|
*/
|
|
667
|
-
type Unsubscribe = () => void;
|
|
1241
|
+
type Unsubscribe$1 = () => void;
|
|
668
1242
|
|
|
669
1243
|
/**
|
|
670
1244
|
* Chat Wrapper
|
|
671
1245
|
*
|
|
672
1246
|
* This is the lightweight class that lives in the main bundle.
|
|
1247
|
+
* Implements Feature for consistent lifecycle management.
|
|
1248
|
+
*
|
|
673
1249
|
* It handles:
|
|
674
1250
|
* - Auto-fetching settings from dashboard (Intercom-like)
|
|
675
1251
|
* - Merging server settings with code config
|
|
@@ -678,13 +1254,15 @@ type Unsubscribe = () => void;
|
|
|
678
1254
|
* - Delegating to LazyLoadedChat
|
|
679
1255
|
* - Queuing messages/callbacks before widget loads
|
|
680
1256
|
*/
|
|
681
|
-
declare class ChatWrapper {
|
|
1257
|
+
declare class ChatWrapper implements Feature {
|
|
682
1258
|
private readonly _instance;
|
|
1259
|
+
readonly name = "Chat";
|
|
683
1260
|
private _lazyLoadedChat;
|
|
684
1261
|
private _config;
|
|
685
1262
|
private _serverConfig;
|
|
686
1263
|
private _configFetched;
|
|
687
1264
|
private _isLoading;
|
|
1265
|
+
private _isStarted;
|
|
688
1266
|
private _loadError;
|
|
689
1267
|
private _pendingMessages;
|
|
690
1268
|
private _pendingCallbacks;
|
|
@@ -692,6 +1270,34 @@ declare class ChatWrapper {
|
|
|
692
1270
|
private _typingCallbacks;
|
|
693
1271
|
private _connectionCallbacks;
|
|
694
1272
|
constructor(_instance: VTilt, config?: ChatConfig);
|
|
1273
|
+
/**
|
|
1274
|
+
* Extract chat config from VTiltConfig.
|
|
1275
|
+
* Self-contained - vtilt.ts doesn't need to know config details.
|
|
1276
|
+
*/
|
|
1277
|
+
static extractConfig(config: VTiltConfig): ChatConfig;
|
|
1278
|
+
get isEnabled(): boolean;
|
|
1279
|
+
get isStarted(): boolean;
|
|
1280
|
+
/**
|
|
1281
|
+
* Start chat if enabled (Feature interface).
|
|
1282
|
+
* This is async because it may fetch server settings.
|
|
1283
|
+
*/
|
|
1284
|
+
startIfEnabled(): void;
|
|
1285
|
+
/**
|
|
1286
|
+
* Stop the chat widget (Feature interface).
|
|
1287
|
+
*/
|
|
1288
|
+
stop(): void;
|
|
1289
|
+
/**
|
|
1290
|
+
* Handle config updates (Feature interface).
|
|
1291
|
+
*/
|
|
1292
|
+
onConfigUpdate(config: VTiltConfig): void;
|
|
1293
|
+
/**
|
|
1294
|
+
* Handle remote config updates (Feature interface).
|
|
1295
|
+
*/
|
|
1296
|
+
onRemoteConfig(remoteConfig: RemoteConfig): void;
|
|
1297
|
+
/**
|
|
1298
|
+
* Async start implementation
|
|
1299
|
+
*/
|
|
1300
|
+
private _startAsync;
|
|
695
1301
|
/**
|
|
696
1302
|
* Whether the chat widget is open
|
|
697
1303
|
*/
|
|
@@ -767,23 +1373,15 @@ declare class ChatWrapper {
|
|
|
767
1373
|
/**
|
|
768
1374
|
* Subscribe to new messages
|
|
769
1375
|
*/
|
|
770
|
-
onMessage(callback: MessageCallback): Unsubscribe;
|
|
1376
|
+
onMessage(callback: MessageCallback): Unsubscribe$1;
|
|
771
1377
|
/**
|
|
772
1378
|
* Subscribe to typing indicators
|
|
773
1379
|
*/
|
|
774
|
-
onTyping(callback: TypingCallback): Unsubscribe;
|
|
1380
|
+
onTyping(callback: TypingCallback): Unsubscribe$1;
|
|
775
1381
|
/**
|
|
776
1382
|
* Subscribe to connection changes
|
|
777
1383
|
*/
|
|
778
|
-
onConnectionChange(callback: ConnectionCallback): Unsubscribe;
|
|
779
|
-
/**
|
|
780
|
-
* Start chat if enabled, called by VTilt after init
|
|
781
|
-
*
|
|
782
|
-
* This method supports two modes (Intercom-like):
|
|
783
|
-
* 1. Auto-config: Fetch settings from /api/chat/settings (default)
|
|
784
|
-
* 2. Code-only: Use only code config (autoConfig: false)
|
|
785
|
-
*/
|
|
786
|
-
startIfEnabled(): Promise<void>;
|
|
1384
|
+
onConnectionChange(callback: ConnectionCallback): Unsubscribe$1;
|
|
787
1385
|
/**
|
|
788
1386
|
* Update configuration
|
|
789
1387
|
*/
|
|
@@ -796,7 +1394,6 @@ declare class ChatWrapper {
|
|
|
796
1394
|
* Destroy the chat widget
|
|
797
1395
|
*/
|
|
798
1396
|
destroy(): void;
|
|
799
|
-
private get _isChatEnabled();
|
|
800
1397
|
/**
|
|
801
1398
|
* Fetch chat settings from the server
|
|
802
1399
|
* This enables "snippet-only" installation where widget configures from dashboard
|
|
@@ -846,334 +1443,215 @@ interface QueuedRequest {
|
|
|
846
1443
|
transport?: "xhr" | "sendBeacon";
|
|
847
1444
|
}
|
|
848
1445
|
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
private
|
|
864
|
-
|
|
865
|
-
private
|
|
866
|
-
private
|
|
867
|
-
private
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
/**
|
|
872
|
-
* Initializes a new instance of the VTilt tracking object.
|
|
873
|
-
*
|
|
874
|
-
* @remarks
|
|
875
|
-
* All new instances are added to the main vt object as sub properties (such as
|
|
876
|
-
* `vt.library_name`) and also returned by this function.
|
|
877
|
-
*
|
|
878
|
-
* @example
|
|
879
|
-
* ```js
|
|
880
|
-
* // basic initialization
|
|
881
|
-
* vt.init('<project_id>', {
|
|
882
|
-
* api_host: '<client_api_host>'
|
|
883
|
-
* })
|
|
884
|
-
* ```
|
|
885
|
-
*
|
|
886
|
-
* @example
|
|
887
|
-
* ```js
|
|
888
|
-
* // multiple instances
|
|
889
|
-
* vt.init('<project_id>', {}, 'project1')
|
|
890
|
-
* vt.init('<project_id>', {}, 'project2')
|
|
891
|
-
* ```
|
|
892
|
-
*
|
|
893
|
-
* @public
|
|
894
|
-
*
|
|
895
|
-
* @param projectId - Your VTilt project ID
|
|
896
|
-
* @param config - A dictionary of config options to override
|
|
897
|
-
* @param name - The name for the new VTilt instance that you want created
|
|
1446
|
+
interface RateLimitBucket {
|
|
1447
|
+
tokens: number;
|
|
1448
|
+
last: number;
|
|
1449
|
+
}
|
|
1450
|
+
interface RateLimiterConfig {
|
|
1451
|
+
eventsPerSecond?: number;
|
|
1452
|
+
eventsBurstLimit?: number;
|
|
1453
|
+
persistence?: {
|
|
1454
|
+
get: (key: string) => RateLimitBucket | null;
|
|
1455
|
+
set: (key: string, value: RateLimitBucket) => void;
|
|
1456
|
+
};
|
|
1457
|
+
captureWarning?: (message: string) => void;
|
|
1458
|
+
}
|
|
1459
|
+
declare class RateLimiter {
|
|
1460
|
+
private eventsPerSecond;
|
|
1461
|
+
private eventsBurstLimit;
|
|
1462
|
+
private lastEventRateLimited;
|
|
1463
|
+
private persistence?;
|
|
1464
|
+
private captureWarning?;
|
|
1465
|
+
constructor(config?: RateLimiterConfig);
|
|
1466
|
+
/**
|
|
1467
|
+
* Check if the client should be rate limited
|
|
898
1468
|
*
|
|
899
|
-
* @
|
|
1469
|
+
* @param checkOnly - If true, don't consume a token (just check)
|
|
1470
|
+
* @returns Object with isRateLimited flag and remaining tokens
|
|
900
1471
|
*/
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
*/
|
|
906
|
-
private _init;
|
|
907
|
-
/**
|
|
908
|
-
* Start the request queue if user hasn't opted out
|
|
909
|
-
* Following PostHog's pattern - called from both _init() and _dom_loaded()
|
|
910
|
-
* Safe to call multiple times as enable() is idempotent
|
|
911
|
-
*/
|
|
912
|
-
private _start_queue_if_opted_in;
|
|
913
|
-
/**
|
|
914
|
-
* Set up handler to flush event queue on page unload
|
|
915
|
-
* Uses both beforeunload and pagehide for maximum compatibility
|
|
916
|
-
*/
|
|
917
|
-
private _setup_unload_handler;
|
|
918
|
-
/**
|
|
919
|
-
* Read vt=person_uuid from current URL (tracking link for manually created persons).
|
|
920
|
-
* Stores the value for inclusion in event payload as $vt; removes param from URL via replaceState.
|
|
921
|
-
*/
|
|
922
|
-
private _read_vt_param_from_url;
|
|
923
|
-
/**
|
|
924
|
-
* Load remote config from cache and fetch fresh in background.
|
|
925
|
-
* Uses sessionStorage for per-session caching.
|
|
926
|
-
* Local config always overrides remote config.
|
|
927
|
-
*/
|
|
928
|
-
private _loadRemoteConfig;
|
|
1472
|
+
checkRateLimit(checkOnly?: boolean): {
|
|
1473
|
+
isRateLimited: boolean;
|
|
1474
|
+
remainingTokens: number;
|
|
1475
|
+
};
|
|
929
1476
|
/**
|
|
930
|
-
*
|
|
931
|
-
* Caches response in localStorage for persistence across sessions.
|
|
1477
|
+
* Check if an event should be allowed (consumes a token if allowed)
|
|
932
1478
|
*/
|
|
933
|
-
|
|
1479
|
+
shouldAllowEvent(): boolean;
|
|
934
1480
|
/**
|
|
935
|
-
*
|
|
936
|
-
* Local config takes precedence over remote.
|
|
937
|
-
* Also triggers feature initialization if settings changed after init.
|
|
1481
|
+
* Get remaining tokens without consuming
|
|
938
1482
|
*/
|
|
939
|
-
|
|
1483
|
+
getRemainingTokens(): number;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
/**
|
|
1487
|
+
* Simple Event Emitter
|
|
1488
|
+
*
|
|
1489
|
+
* Lightweight pub/sub system for internal feature communication.
|
|
1490
|
+
* Following PostHog's SimpleEventEmitter pattern.
|
|
1491
|
+
*/
|
|
1492
|
+
/**
|
|
1493
|
+
* Event listener function type
|
|
1494
|
+
*/
|
|
1495
|
+
type EventListener<T = unknown> = (payload: T) => void;
|
|
1496
|
+
/**
|
|
1497
|
+
* Unsubscribe function returned by on()
|
|
1498
|
+
*/
|
|
1499
|
+
type Unsubscribe = () => void;
|
|
1500
|
+
/**
|
|
1501
|
+
* Simple event emitter for internal SDK communication.
|
|
1502
|
+
* Features can emit and listen to events without direct coupling.
|
|
1503
|
+
*
|
|
1504
|
+
* @example
|
|
1505
|
+
* ```typescript
|
|
1506
|
+
* const emitter = new SimpleEventEmitter();
|
|
1507
|
+
*
|
|
1508
|
+
* // Subscribe to events
|
|
1509
|
+
* const unsubscribe = emitter.on('user:identified', (data) => {
|
|
1510
|
+
* console.log('User identified:', data);
|
|
1511
|
+
* });
|
|
1512
|
+
*
|
|
1513
|
+
* // Emit events
|
|
1514
|
+
* emitter.emit('user:identified', { userId: '123' });
|
|
1515
|
+
*
|
|
1516
|
+
* // Unsubscribe when done
|
|
1517
|
+
* unsubscribe();
|
|
1518
|
+
* ```
|
|
1519
|
+
*/
|
|
1520
|
+
declare class SimpleEventEmitter {
|
|
1521
|
+
private _events;
|
|
1522
|
+
private _onceEvents;
|
|
940
1523
|
/**
|
|
941
|
-
*
|
|
942
|
-
* Used for debugging and logging
|
|
1524
|
+
* Subscribe to an event.
|
|
943
1525
|
*
|
|
944
|
-
* @
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
/**
|
|
948
|
-
* Get current domain from location
|
|
949
|
-
* Returns full URL format for consistency with dashboard
|
|
950
|
-
*/
|
|
951
|
-
private getCurrentDomain;
|
|
952
|
-
/**
|
|
953
|
-
* Check if tracking is properly configured
|
|
954
|
-
* Returns true if projectId and token are present, false otherwise
|
|
955
|
-
* Logs a warning only once per instance if not configured
|
|
956
|
-
*/
|
|
957
|
-
private _is_configured;
|
|
958
|
-
/**
|
|
959
|
-
* Build the tracking URL with token in query parameters
|
|
1526
|
+
* @param event - Event name to subscribe to
|
|
1527
|
+
* @param listener - Callback function
|
|
1528
|
+
* @returns Unsubscribe function
|
|
960
1529
|
*/
|
|
961
|
-
|
|
1530
|
+
on<T = unknown>(event: string, listener: EventListener<T>): Unsubscribe;
|
|
962
1531
|
/**
|
|
963
|
-
*
|
|
964
|
-
*
|
|
965
|
-
*
|
|
1532
|
+
* Subscribe to an event once (auto-unsubscribes after first call).
|
|
1533
|
+
*
|
|
1534
|
+
* @param event - Event name to subscribe to
|
|
1535
|
+
* @param listener - Callback function
|
|
1536
|
+
* @returns Unsubscribe function
|
|
966
1537
|
*/
|
|
967
|
-
|
|
1538
|
+
once<T = unknown>(event: string, listener: EventListener<T>): Unsubscribe;
|
|
968
1539
|
/**
|
|
969
|
-
*
|
|
970
|
-
*
|
|
971
|
-
*
|
|
1540
|
+
* Emit an event to all listeners.
|
|
1541
|
+
*
|
|
1542
|
+
* @param event - Event name to emit
|
|
1543
|
+
* @param payload - Data to pass to listeners
|
|
972
1544
|
*/
|
|
973
|
-
|
|
1545
|
+
emit<T = unknown>(event: string, payload?: T): void;
|
|
974
1546
|
/**
|
|
975
|
-
*
|
|
976
|
-
*
|
|
977
|
-
*
|
|
978
|
-
*/
|
|
979
|
-
private _send_http_request;
|
|
980
|
-
/**
|
|
981
|
-
* Send request using sendBeacon for reliable delivery on page unload
|
|
982
|
-
* Uses GZip compression for payloads > 1KB
|
|
1547
|
+
* Remove all listeners for an event.
|
|
1548
|
+
*
|
|
1549
|
+
* @param event - Event name (or undefined to remove all)
|
|
983
1550
|
*/
|
|
984
|
-
|
|
1551
|
+
off(event?: string): void;
|
|
985
1552
|
/**
|
|
986
|
-
*
|
|
1553
|
+
* Get the number of listeners for an event.
|
|
1554
|
+
*
|
|
1555
|
+
* @param event - Event name
|
|
1556
|
+
* @returns Number of listeners
|
|
987
1557
|
*/
|
|
988
|
-
|
|
1558
|
+
listenerCount(event: string): number;
|
|
989
1559
|
/**
|
|
990
|
-
*
|
|
991
|
-
* Automatically adds common properties to all events
|
|
992
|
-
* ($current_url, $host, $pathname, $referrer, $referring_domain, $browser, $os, $device, $timezone, etc.)
|
|
993
|
-
* Only properties in EVENT_TO_PERSON_PROPERTIES are copied to person properties
|
|
994
|
-
* Also adds title property for $pageview events only
|
|
1560
|
+
* Check if there are any listeners for an event.
|
|
995
1561
|
*
|
|
996
|
-
* @param
|
|
997
|
-
* @
|
|
998
|
-
* @param options - Optional capture options
|
|
1562
|
+
* @param event - Event name
|
|
1563
|
+
* @returns True if there are listeners
|
|
999
1564
|
*/
|
|
1565
|
+
hasListeners(event: string): boolean;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
/**
|
|
1569
|
+
* VTilt SDK - Main Entry Point
|
|
1570
|
+
*
|
|
1571
|
+
* Privacy-first analytics SDK with modular architecture.
|
|
1572
|
+
* This file is a thin orchestrator that delegates to specialized managers:
|
|
1573
|
+
*
|
|
1574
|
+
* - ConfigManager: Configuration management
|
|
1575
|
+
* - SessionManager: Session and window ID management
|
|
1576
|
+
* - UserManager: User identity and properties
|
|
1577
|
+
* - CaptureManager: Event capture and payload enrichment
|
|
1578
|
+
* - IdentityManager: High-level identity operations
|
|
1579
|
+
* - RemoteConfigManager: Remote configuration from /decide
|
|
1580
|
+
* - FeatureManager: Feature lifecycle management
|
|
1581
|
+
*
|
|
1582
|
+
* @see docs/tracker/README.md for full documentation
|
|
1583
|
+
*/
|
|
1584
|
+
|
|
1585
|
+
declare class VTilt {
|
|
1586
|
+
readonly version = "1.10.1";
|
|
1587
|
+
__loaded: boolean;
|
|
1588
|
+
__request_queue: QueuedRequest[];
|
|
1589
|
+
historyAutocapture?: HistoryAutocapture;
|
|
1590
|
+
autocapture?: Autocapture;
|
|
1591
|
+
sessionRecording?: SessionRecordingWrapper;
|
|
1592
|
+
chat?: ChatWrapper;
|
|
1593
|
+
webVitals?: WebVitalsManager;
|
|
1594
|
+
private configManager;
|
|
1595
|
+
sessionManager: SessionManager;
|
|
1596
|
+
userManager: UserManager;
|
|
1597
|
+
private _captureManager;
|
|
1598
|
+
private _identityManager;
|
|
1599
|
+
private _remoteConfigManager;
|
|
1600
|
+
private _featureManager;
|
|
1601
|
+
private requestQueue;
|
|
1602
|
+
private retryQueue;
|
|
1603
|
+
rateLimiter: RateLimiter;
|
|
1604
|
+
_emitter: SimpleEventEmitter;
|
|
1605
|
+
private _has_warned_about_config;
|
|
1606
|
+
constructor(config?: Partial<VTiltConfig>);
|
|
1607
|
+
init(projectId: string, config?: Partial<VTiltConfig>, name?: string): VTilt;
|
|
1608
|
+
private _init;
|
|
1609
|
+
private _initFeatures;
|
|
1610
|
+
private _initHistoryAutocapture;
|
|
1611
|
+
private _initAutocapture;
|
|
1612
|
+
private _initWebVitals;
|
|
1613
|
+
_initSessionRecording(): void;
|
|
1614
|
+
_initChat(): void;
|
|
1615
|
+
startAutocapture(): void;
|
|
1616
|
+
stopAutocapture(): void;
|
|
1617
|
+
isAutocaptureActive(): boolean;
|
|
1618
|
+
startSessionRecording(): void;
|
|
1619
|
+
stopSessionRecording(): void;
|
|
1620
|
+
isRecordingActive(): boolean;
|
|
1621
|
+
getSessionRecordingId(): string | null;
|
|
1000
1622
|
capture(name: string, payload: EventPayload, options?: {
|
|
1001
1623
|
skip_client_rate_limiting?: boolean;
|
|
1002
1624
|
}): void;
|
|
1003
|
-
/**
|
|
1004
|
-
* Internal capture method that bypasses rate limiting
|
|
1005
|
-
* Used for system events like rate limit warnings
|
|
1006
|
-
*/
|
|
1007
|
-
private _capture_internal;
|
|
1008
|
-
/**
|
|
1009
|
-
* Track a custom event (alias for capture)
|
|
1010
|
-
*/
|
|
1011
1625
|
trackEvent(name: string, payload?: EventPayload): void;
|
|
1012
|
-
/**
|
|
1013
|
-
* Identify a user with property operations
|
|
1014
|
-
* Sends $identify event when transitioning from anonymous to identified
|
|
1015
|
-
* Event's distinct_id is the previous/anonymous ID, new distinct_id is in payload
|
|
1016
|
-
*
|
|
1017
|
-
* @example
|
|
1018
|
-
* ```js
|
|
1019
|
-
* // Basic identify with properties
|
|
1020
|
-
* vTilt.identify('user_123',
|
|
1021
|
-
* { name: 'John Doe', email: 'john@example.com' }, // $set properties
|
|
1022
|
-
* { first_login: new Date().toISOString() } // $set_once properties
|
|
1023
|
-
* )
|
|
1024
|
-
* ```
|
|
1025
|
-
*
|
|
1026
|
-
* @example
|
|
1027
|
-
* ```js
|
|
1028
|
-
* // If no $set is provided, all properties are treated as $set
|
|
1029
|
-
* vTilt.identify('user_123', { name: 'John Doe', email: 'john@example.com' })
|
|
1030
|
-
* ```
|
|
1031
|
-
*/
|
|
1032
1626
|
identify(newDistinctId?: string, userPropertiesToSet?: Record<string, any>, userPropertiesToSetOnce?: Record<string, any>): void;
|
|
1033
|
-
/**
|
|
1034
|
-
* Set user properties
|
|
1035
|
-
* Sets properties on the person profile associated with the current distinct_id
|
|
1036
|
-
*
|
|
1037
|
-
* @example
|
|
1038
|
-
* ```js
|
|
1039
|
-
* // Set properties that can be updated
|
|
1040
|
-
* vTilt.setUserProperties({ name: 'John Doe', email: 'john@example.com' })
|
|
1041
|
-
* ```
|
|
1042
|
-
*
|
|
1043
|
-
* @example
|
|
1044
|
-
* ```js
|
|
1045
|
-
* // Set properties with $set and $set_once operations
|
|
1046
|
-
* vTilt.setUserProperties(
|
|
1047
|
-
* { name: 'John Doe', last_login: new Date().toISOString() }, // $set properties
|
|
1048
|
-
* { first_login: new Date().toISOString() } // $set_once properties
|
|
1049
|
-
* )
|
|
1050
|
-
* ```
|
|
1051
|
-
*
|
|
1052
|
-
* @param userPropertiesToSet Optional: Properties to set (can be updated)
|
|
1053
|
-
* @param userPropertiesToSetOnce Optional: Properties to set once (preserves first value)
|
|
1054
|
-
*/
|
|
1055
1627
|
setUserProperties(userPropertiesToSet?: Record<string, any>, userPropertiesToSetOnce?: Record<string, any>): void;
|
|
1056
|
-
/**
|
|
1057
|
-
* Reset user identity (logout)
|
|
1058
|
-
* Clears all user data, generates new anonymous ID, resets session
|
|
1059
|
-
*
|
|
1060
|
-
* @param reset_device_id - If true, also resets device_id. Default: false
|
|
1061
|
-
*
|
|
1062
|
-
* @example
|
|
1063
|
-
* // Reset on user logout
|
|
1064
|
-
* vtilt.resetUser()
|
|
1065
|
-
*
|
|
1066
|
-
* @example
|
|
1067
|
-
* // Reset and generate new device ID
|
|
1068
|
-
* vtilt.resetUser(true)
|
|
1069
|
-
*/
|
|
1070
1628
|
resetUser(reset_device_id?: boolean): void;
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
*/
|
|
1074
|
-
getUserIdentity(): UserIdentity;
|
|
1075
|
-
/**
|
|
1076
|
-
* Get current device ID
|
|
1077
|
-
*/
|
|
1629
|
+
createAlias(alias: string, original?: string): void;
|
|
1630
|
+
getUserIdentity(): Record<string, any>;
|
|
1078
1631
|
getDeviceId(): string;
|
|
1079
|
-
/**
|
|
1080
|
-
* Get current user state
|
|
1081
|
-
*/
|
|
1082
1632
|
getUserState(): "anonymous" | "identified";
|
|
1083
|
-
/**
|
|
1084
|
-
* Create an alias to link two distinct IDs
|
|
1085
|
-
* Links anonymous session to account on signup
|
|
1086
|
-
*
|
|
1087
|
-
* @param alias - A unique identifier that you want to use for this user in the future
|
|
1088
|
-
* @param original - The current identifier being used for this user (optional, defaults to current distinct_id)
|
|
1089
|
-
*
|
|
1090
|
-
* @example
|
|
1091
|
-
* // Link anonymous user to account on signup
|
|
1092
|
-
* vtilt.createAlias('user_12345')
|
|
1093
|
-
*
|
|
1094
|
-
* @example
|
|
1095
|
-
* // Explicit alias with original ID
|
|
1096
|
-
* vtilt.createAlias('user_12345', 'anonymous_abc123')
|
|
1097
|
-
*/
|
|
1098
|
-
createAlias(alias: string, original?: string): void;
|
|
1099
|
-
/**
|
|
1100
|
-
* Capture initial pageview with visibility check
|
|
1101
|
-
* Note: The capture_pageview config check happens at the call site (in _init)
|
|
1102
|
-
*/
|
|
1103
|
-
private _capture_initial_pageview;
|
|
1104
|
-
/**
|
|
1105
|
-
* Get current configuration
|
|
1106
|
-
*/
|
|
1107
1633
|
getConfig(): VTiltConfig;
|
|
1108
|
-
/**
|
|
1109
|
-
* Get current session ID
|
|
1110
|
-
*/
|
|
1111
1634
|
getSessionId(): string | null;
|
|
1112
|
-
/**
|
|
1113
|
-
* Get current distinct ID
|
|
1114
|
-
*/
|
|
1115
1635
|
getDistinctId(): string;
|
|
1116
|
-
/**
|
|
1117
|
-
* Get anonymous ID
|
|
1118
|
-
*/
|
|
1119
1636
|
getAnonymousId(): string;
|
|
1120
|
-
|
|
1121
|
-
* Update configuration
|
|
1122
|
-
*/
|
|
1637
|
+
toString(): string;
|
|
1123
1638
|
updateConfig(config: Partial<VTiltConfig>): void;
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
private
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
*/
|
|
1136
|
-
startSessionRecording(): void;
|
|
1137
|
-
/**
|
|
1138
|
-
* Stop session recording
|
|
1139
|
-
*/
|
|
1140
|
-
stopSessionRecording(): void;
|
|
1141
|
-
/**
|
|
1142
|
-
* Check if session recording is active
|
|
1143
|
-
*/
|
|
1144
|
-
isRecordingActive(): boolean;
|
|
1145
|
-
/**
|
|
1146
|
-
* Get session recording ID
|
|
1147
|
-
*/
|
|
1148
|
-
getSessionRecordingId(): string | null;
|
|
1149
|
-
/**
|
|
1150
|
-
* Initialize chat widget
|
|
1151
|
-
*/
|
|
1152
|
-
private _initChat;
|
|
1153
|
-
/**
|
|
1154
|
-
* Build chat config from VTiltConfig
|
|
1155
|
-
*/
|
|
1156
|
-
private _buildChatConfig;
|
|
1157
|
-
/**
|
|
1158
|
-
* _execute_array() deals with processing any vTilt function
|
|
1159
|
-
* calls that were called before the vTilt library was loaded
|
|
1160
|
-
* (and are thus stored in an array so they can be called later)
|
|
1161
|
-
*
|
|
1162
|
-
* Note: we fire off all the vTilt function calls BEFORE we fire off
|
|
1163
|
-
* tracking calls. This is so identify/setUserProperties/updateConfig calls
|
|
1164
|
-
* can properly modify early tracking calls.
|
|
1165
|
-
*
|
|
1166
|
-
* @param {Array} array Array of queued calls in format [methodName, ...args]
|
|
1167
|
-
*/
|
|
1639
|
+
private _notifyFeaturesOfConfigUpdate;
|
|
1640
|
+
buildUrl(): string;
|
|
1641
|
+
sendRequest(url: string, event: TrackingEvent, shouldEnqueue?: boolean): void;
|
|
1642
|
+
private _is_configured;
|
|
1643
|
+
private _send_batched_request;
|
|
1644
|
+
private _send_http_request;
|
|
1645
|
+
private _send_beacon_request;
|
|
1646
|
+
_send_retriable_request(item: QueuedRequest): void;
|
|
1647
|
+
private _setup_unload_handler;
|
|
1648
|
+
private _start_queue_if_opted_in;
|
|
1649
|
+
private _read_vt_param_from_url;
|
|
1168
1650
|
_execute_array(array: any[]): void;
|
|
1169
|
-
/**
|
|
1170
|
-
* Called when DOM is loaded - processes queued requests and enables batching
|
|
1171
|
-
* Following PostHog's pattern in _dom_loaded()
|
|
1172
|
-
*/
|
|
1173
1651
|
_dom_loaded(): void;
|
|
1174
1652
|
}
|
|
1175
1653
|
|
|
1176
1654
|
declare const vt: VTilt;
|
|
1177
1655
|
|
|
1178
1656
|
export { ALL_WEB_VITALS_METRICS, DEFAULT_WEB_VITALS_METRICS, VTilt, vt as default, vt };
|
|
1179
|
-
export type { AliasEvent, CaptureOptions, CapturePerformanceConfig, CaptureResult, ChatWidgetConfig, EventPayload, FeatureFlagsConfig, GeolocationData, GroupsConfig, PersistenceMethod, Properties, Property, PropertyOperations, RemoteConfig, RequestOptions, SessionData, SessionIdChangedCallback, SessionRecordingMaskInputOptions, SessionRecordingOptions, SupportedWebVitalsMetric, TrackingEvent, UserIdentity, UserProperties, VTiltConfig, WebVitalMetric };
|
|
1657
|
+
export type { AliasEvent, AutocaptureOptions, CaptureOptions, CapturePerformanceConfig, CaptureResult, ChatWidgetConfig, EventPayload, FeatureFlagsConfig, GeolocationData, GroupsConfig, PersistenceMethod, Properties, Property, PropertyOperations, RemoteConfig, RequestOptions, SessionData, SessionIdChangedCallback, SessionRecordingMaskInputOptions, SessionRecordingOptions, SupportedWebVitalsMetric, TrackingEvent, UserIdentity, UserProperties, VTiltConfig, WebVitalMetric };
|