@v-tilt/browser 1.0.11 → 1.1.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/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/constants.d.ts +172 -10
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.d.ts +230 -46
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/dist/module.no-external.d.ts +230 -46
- package/dist/module.no-external.js +1 -1
- package/dist/module.no-external.js.map +1 -1
- package/dist/rate-limiter.d.ts +52 -0
- package/dist/request-queue.d.ts +78 -0
- package/dist/request.d.ts +54 -0
- package/dist/retry-queue.d.ts +64 -0
- package/dist/session.d.ts +2 -2
- package/dist/types.d.ts +154 -37
- package/dist/user-manager.d.ts +2 -2
- package/dist/vtilt.d.ts +51 -12
- package/lib/config.js +6 -13
- package/lib/constants.d.ts +172 -10
- package/lib/constants.js +644 -439
- package/lib/rate-limiter.d.ts +52 -0
- package/lib/rate-limiter.js +80 -0
- package/lib/request-queue.d.ts +78 -0
- package/lib/request-queue.js +156 -0
- package/lib/request.d.ts +54 -0
- package/lib/request.js +265 -0
- package/lib/retry-queue.d.ts +64 -0
- package/lib/retry-queue.js +182 -0
- package/lib/session.d.ts +2 -2
- package/lib/session.js +3 -3
- package/lib/types.d.ts +154 -37
- package/lib/types.js +6 -0
- package/lib/user-manager.d.ts +2 -2
- package/lib/user-manager.js +38 -11
- package/lib/utils/event-utils.js +88 -82
- package/lib/utils/index.js +2 -2
- package/lib/utils/request-utils.js +21 -19
- package/lib/vtilt.d.ts +51 -12
- package/lib/vtilt.js +199 -40
- package/lib/web-vitals.js +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request Queue - Event Batching (PostHog-style)
|
|
3
|
+
*
|
|
4
|
+
* Batches multiple events together and sends them at configurable intervals.
|
|
5
|
+
* This reduces the number of HTTP requests significantly for active users.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Configurable flush interval (default 3 seconds)
|
|
9
|
+
* - Batches events by URL/batchKey
|
|
10
|
+
* - Uses sendBeacon on page unload for reliable delivery
|
|
11
|
+
* - Converts absolute timestamps to relative offsets before sending
|
|
12
|
+
*/
|
|
13
|
+
import type { TrackingEvent } from "./types";
|
|
14
|
+
export declare const DEFAULT_FLUSH_INTERVAL_MS = 3000;
|
|
15
|
+
export interface QueuedRequest {
|
|
16
|
+
url: string;
|
|
17
|
+
event: TrackingEvent;
|
|
18
|
+
batchKey?: string;
|
|
19
|
+
transport?: "xhr" | "sendBeacon";
|
|
20
|
+
}
|
|
21
|
+
export interface BatchedRequest {
|
|
22
|
+
url: string;
|
|
23
|
+
events: TrackingEvent[];
|
|
24
|
+
batchKey?: string;
|
|
25
|
+
transport?: "xhr" | "sendBeacon";
|
|
26
|
+
}
|
|
27
|
+
export interface RequestQueueConfig {
|
|
28
|
+
flush_interval_ms?: number;
|
|
29
|
+
}
|
|
30
|
+
export declare class RequestQueue {
|
|
31
|
+
private _isPaused;
|
|
32
|
+
private _queue;
|
|
33
|
+
private _flushTimeout?;
|
|
34
|
+
private _flushTimeoutMs;
|
|
35
|
+
private _sendRequest;
|
|
36
|
+
constructor(sendRequest: (req: BatchedRequest) => void, config?: RequestQueueConfig);
|
|
37
|
+
/**
|
|
38
|
+
* Get the current queue length
|
|
39
|
+
*/
|
|
40
|
+
get length(): number;
|
|
41
|
+
/**
|
|
42
|
+
* Enqueue an event for batched sending
|
|
43
|
+
*/
|
|
44
|
+
enqueue(req: QueuedRequest): void;
|
|
45
|
+
/**
|
|
46
|
+
* Flush all queued events immediately using sendBeacon
|
|
47
|
+
* Called on page unload to ensure events are delivered
|
|
48
|
+
*/
|
|
49
|
+
unload(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Enable the queue and start flushing
|
|
52
|
+
*/
|
|
53
|
+
enable(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Pause the queue (stops flushing but keeps events)
|
|
56
|
+
*/
|
|
57
|
+
pause(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Force an immediate flush
|
|
60
|
+
*/
|
|
61
|
+
flush(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Set up the flush timeout
|
|
64
|
+
*/
|
|
65
|
+
private _setFlushTimeout;
|
|
66
|
+
/**
|
|
67
|
+
* Clear the flush timeout
|
|
68
|
+
*/
|
|
69
|
+
private _clearFlushTimeout;
|
|
70
|
+
/**
|
|
71
|
+
* Flush all queued events now
|
|
72
|
+
*/
|
|
73
|
+
private _flushNow;
|
|
74
|
+
/**
|
|
75
|
+
* Format the queue into batched requests by URL/batchKey
|
|
76
|
+
*/
|
|
77
|
+
private _formatQueue;
|
|
78
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request utilities for vTilt tracking
|
|
3
|
+
*
|
|
4
|
+
* Handles HTTP requests with:
|
|
5
|
+
* - GZip compression (via fflate)
|
|
6
|
+
* - Multiple transport methods (fetch, XHR, sendBeacon)
|
|
7
|
+
* - Automatic fallback between transports
|
|
8
|
+
*
|
|
9
|
+
* Based on PostHog's request.ts pattern
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Compression methods supported by the SDK
|
|
13
|
+
*/
|
|
14
|
+
export declare enum Compression {
|
|
15
|
+
GZipJS = "gzip-js",
|
|
16
|
+
None = "none"
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Response from a request
|
|
20
|
+
*/
|
|
21
|
+
export interface RequestResponse {
|
|
22
|
+
statusCode: number;
|
|
23
|
+
text?: string;
|
|
24
|
+
json?: any;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Options for making a request
|
|
28
|
+
*/
|
|
29
|
+
export interface RequestOptions {
|
|
30
|
+
url: string;
|
|
31
|
+
data?: any;
|
|
32
|
+
method?: "POST" | "GET";
|
|
33
|
+
headers?: Record<string, string>;
|
|
34
|
+
transport?: "XHR" | "fetch" | "sendBeacon";
|
|
35
|
+
compression?: Compression;
|
|
36
|
+
timeout?: number;
|
|
37
|
+
callback?: (response: RequestResponse) => void;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* JSON stringify with BigInt support
|
|
41
|
+
*/
|
|
42
|
+
export declare const jsonStringify: (data: any) => string;
|
|
43
|
+
/**
|
|
44
|
+
* Main request function - handles transport selection and dispatching
|
|
45
|
+
*/
|
|
46
|
+
export declare const request: (options: RequestOptions) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Promise-based request wrapper
|
|
49
|
+
*/
|
|
50
|
+
export declare const requestAsync: (options: Omit<RequestOptions, "callback">) => Promise<RequestResponse>;
|
|
51
|
+
/**
|
|
52
|
+
* Check if compression is supported and beneficial
|
|
53
|
+
*/
|
|
54
|
+
export declare const shouldCompress: (data: any) => boolean;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry Queue - Exponential Backoff (PostHog-style)
|
|
3
|
+
*
|
|
4
|
+
* Retries failed requests with jittered exponential backoff.
|
|
5
|
+
* Detects online/offline status and pauses retries when offline.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Exponential backoff: 3s, 6s, 12s, 24s... up to 30 minutes
|
|
9
|
+
* - Jitter: +/- 50% to prevent thundering herd
|
|
10
|
+
* - Online/offline detection
|
|
11
|
+
* - Max 10 retries before giving up
|
|
12
|
+
* - Uses sendBeacon on page unload for final attempt
|
|
13
|
+
*/
|
|
14
|
+
import type { BatchedRequest } from "./request-queue";
|
|
15
|
+
/**
|
|
16
|
+
* Generates a jittered exponential backoff delay in milliseconds
|
|
17
|
+
*
|
|
18
|
+
* Base value is 3 seconds, doubled with each retry up to 30 minutes max.
|
|
19
|
+
* Each value has +/- 50% jitter.
|
|
20
|
+
*
|
|
21
|
+
* @param retriesPerformedSoFar - Number of retries already attempted
|
|
22
|
+
* @returns Delay in milliseconds
|
|
23
|
+
*/
|
|
24
|
+
export declare function pickNextRetryDelay(retriesPerformedSoFar: number): number;
|
|
25
|
+
export interface RetryQueueConfig {
|
|
26
|
+
sendRequest: (req: BatchedRequest) => Promise<{
|
|
27
|
+
statusCode: number;
|
|
28
|
+
}>;
|
|
29
|
+
sendBeacon: (req: BatchedRequest) => void;
|
|
30
|
+
}
|
|
31
|
+
export declare class RetryQueue {
|
|
32
|
+
private _isPolling;
|
|
33
|
+
private _poller?;
|
|
34
|
+
private _pollIntervalMs;
|
|
35
|
+
private _queue;
|
|
36
|
+
private _areWeOnline;
|
|
37
|
+
private _sendRequest;
|
|
38
|
+
private _sendBeacon;
|
|
39
|
+
constructor(config: RetryQueueConfig);
|
|
40
|
+
/**
|
|
41
|
+
* Get current queue length
|
|
42
|
+
*/
|
|
43
|
+
get length(): number;
|
|
44
|
+
/**
|
|
45
|
+
* Enqueue a failed request for retry
|
|
46
|
+
*/
|
|
47
|
+
enqueue(request: BatchedRequest, retriesPerformedSoFar?: number): void;
|
|
48
|
+
/**
|
|
49
|
+
* Attempt to send a request with retry on failure
|
|
50
|
+
*/
|
|
51
|
+
retriableRequest(request: BatchedRequest): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Start polling for retries
|
|
54
|
+
*/
|
|
55
|
+
private _poll;
|
|
56
|
+
/**
|
|
57
|
+
* Flush ready items from the queue
|
|
58
|
+
*/
|
|
59
|
+
private _flush;
|
|
60
|
+
/**
|
|
61
|
+
* Flush all queued requests using sendBeacon on page unload
|
|
62
|
+
*/
|
|
63
|
+
unload(): void;
|
|
64
|
+
}
|
package/dist/session.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PersistenceMethod } from "./types";
|
|
2
2
|
export declare class SessionManager {
|
|
3
3
|
private storageMethod;
|
|
4
4
|
private domain?;
|
|
5
5
|
private _windowId;
|
|
6
|
-
constructor(storageMethod?:
|
|
6
|
+
constructor(storageMethod?: PersistenceMethod, domain?: string);
|
|
7
7
|
/**
|
|
8
8
|
* Check if using web storage (localStorage or sessionStorage)
|
|
9
9
|
*/
|
package/dist/types.d.ts
CHANGED
|
@@ -1,68 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VTilt Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the VTilt tracking SDK.
|
|
5
|
+
* Following PostHog's patterns where applicable.
|
|
6
|
+
*/
|
|
7
|
+
import type { PersonProfilesMode } from './constants';
|
|
1
8
|
export interface VTiltConfig {
|
|
2
|
-
|
|
9
|
+
/** Project identifier (required) */
|
|
3
10
|
token: string;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
11
|
+
/** API host for tracking (default: https://api.vtilt.io) */
|
|
12
|
+
api_host?: string;
|
|
13
|
+
/** UI host for dashboard links */
|
|
14
|
+
ui_host?: string | null;
|
|
15
|
+
/** Proxy domain for tracking requests */
|
|
7
16
|
proxy?: string;
|
|
17
|
+
/** Full proxy URL for tracking requests */
|
|
8
18
|
proxyUrl?: string;
|
|
19
|
+
/** Instance name (for multiple instances) */
|
|
20
|
+
name?: string;
|
|
21
|
+
/** Project ID (set via init() first argument) */
|
|
22
|
+
projectId?: string;
|
|
23
|
+
/** Domain to track (auto-detected if not provided) */
|
|
9
24
|
domain?: string;
|
|
10
|
-
|
|
25
|
+
/** Storage method for session data */
|
|
26
|
+
storage?: PersistenceMethod;
|
|
27
|
+
/** Persistence method for user data */
|
|
28
|
+
persistence?: PersistenceMethod;
|
|
29
|
+
/** Persistence name prefix */
|
|
30
|
+
persistence_name?: string;
|
|
31
|
+
/** Enable cross-subdomain cookies */
|
|
32
|
+
cross_subdomain_cookie?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Person profiles mode:
|
|
35
|
+
* - 'always': Always create person profiles (default)
|
|
36
|
+
* - 'identified_only': Only create when user is identified
|
|
37
|
+
* - 'never': Never create person profiles
|
|
38
|
+
*/
|
|
39
|
+
person_profiles?: PersonProfilesMode;
|
|
40
|
+
/** Enable autocapture */
|
|
41
|
+
autocapture?: boolean;
|
|
42
|
+
/** Enable web vitals tracking */
|
|
43
|
+
capture_performance?: boolean;
|
|
44
|
+
/** Enable page view tracking */
|
|
45
|
+
capture_pageview?: boolean | 'auto';
|
|
46
|
+
/** Enable page leave tracking */
|
|
47
|
+
capture_pageleave?: boolean | 'if_capture_pageview';
|
|
48
|
+
/** Disable compression */
|
|
49
|
+
disable_compression?: boolean;
|
|
50
|
+
/** Whether to stringify payload before sending */
|
|
11
51
|
stringifyPayload?: boolean;
|
|
12
|
-
|
|
52
|
+
/** Properties to exclude from events */
|
|
53
|
+
property_denylist?: string[];
|
|
54
|
+
/** Mask text in autocapture */
|
|
55
|
+
mask_all_text?: boolean;
|
|
56
|
+
/** Mask all element attributes */
|
|
57
|
+
mask_all_element_attributes?: boolean;
|
|
58
|
+
/** Respect Do Not Track browser setting */
|
|
59
|
+
respect_dnt?: boolean;
|
|
60
|
+
/** Opt users out by default */
|
|
61
|
+
opt_out_capturing_by_default?: boolean;
|
|
62
|
+
/** Global attributes added to all events */
|
|
13
63
|
globalAttributes?: Record<string, string>;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
delta: number;
|
|
25
|
-
rating: string;
|
|
26
|
-
id: string;
|
|
27
|
-
navigationType: string;
|
|
28
|
-
}
|
|
29
|
-
export interface GeolocationData {
|
|
30
|
-
country?: string;
|
|
31
|
-
locale?: string;
|
|
64
|
+
/** Bootstrap data for initialization */
|
|
65
|
+
bootstrap?: {
|
|
66
|
+
distinctID?: string;
|
|
67
|
+
isIdentifiedID?: boolean;
|
|
68
|
+
featureFlags?: Record<string, boolean | string>;
|
|
69
|
+
};
|
|
70
|
+
/** Before send hook for modifying events */
|
|
71
|
+
before_send?: (event: CaptureResult) => CaptureResult | null;
|
|
72
|
+
/** Loaded callback */
|
|
73
|
+
loaded?: (vtilt: any) => void;
|
|
32
74
|
}
|
|
33
75
|
export interface EventPayload {
|
|
34
76
|
[key: string]: any;
|
|
35
77
|
}
|
|
78
|
+
export interface CaptureResult {
|
|
79
|
+
uuid: string;
|
|
80
|
+
event: string;
|
|
81
|
+
properties: Properties;
|
|
82
|
+
$set?: Properties;
|
|
83
|
+
$set_once?: Properties;
|
|
84
|
+
timestamp?: string;
|
|
85
|
+
}
|
|
86
|
+
export interface CaptureOptions {
|
|
87
|
+
/** Override timestamp */
|
|
88
|
+
timestamp?: Date;
|
|
89
|
+
/** Properties to $set on person */
|
|
90
|
+
$set?: Properties;
|
|
91
|
+
/** Properties to $set_once on person */
|
|
92
|
+
$set_once?: Properties;
|
|
93
|
+
/** Send immediately (skip batching) */
|
|
94
|
+
send_instantly?: boolean;
|
|
95
|
+
}
|
|
36
96
|
export interface TrackingEvent {
|
|
37
97
|
timestamp: string;
|
|
38
98
|
event: string;
|
|
39
99
|
project_id: string;
|
|
40
100
|
domain: string;
|
|
41
|
-
|
|
42
|
-
distinct_id?: string;
|
|
101
|
+
distinct_id: string;
|
|
43
102
|
anonymous_id?: string;
|
|
103
|
+
payload: EventPayload;
|
|
44
104
|
}
|
|
45
|
-
export type
|
|
46
|
-
export interface
|
|
47
|
-
|
|
48
|
-
localStorage: "localStorage";
|
|
49
|
-
sessionStorage: "sessionStorage";
|
|
105
|
+
export type Property = string | number | boolean | null | undefined | Date | any[] | Record<string, any>;
|
|
106
|
+
export interface Properties {
|
|
107
|
+
[key: string]: Property;
|
|
50
108
|
}
|
|
109
|
+
export interface PropertyOperations {
|
|
110
|
+
$set?: Properties;
|
|
111
|
+
$set_once?: Properties;
|
|
112
|
+
$unset?: string[];
|
|
113
|
+
}
|
|
114
|
+
export interface SessionData {
|
|
115
|
+
value: string;
|
|
116
|
+
expiry: number;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Persistence method for user/session data
|
|
120
|
+
* Following PostHog's approach:
|
|
121
|
+
* - 'localStorage+cookie': Stores limited data in cookies, rest in localStorage (default)
|
|
122
|
+
* - 'cookie': Stores all data in cookies
|
|
123
|
+
* - 'localStorage': Stores all data in localStorage
|
|
124
|
+
* - 'sessionStorage': Stores all data in sessionStorage
|
|
125
|
+
* - 'memory': Stores all data in memory only (no persistence)
|
|
126
|
+
*/
|
|
127
|
+
export type PersistenceMethod = 'localStorage+cookie' | 'cookie' | 'localStorage' | 'sessionStorage' | 'memory';
|
|
128
|
+
/** User identity state */
|
|
51
129
|
export interface UserIdentity {
|
|
130
|
+
/** Current distinct ID (null if anonymous) */
|
|
52
131
|
distinct_id: string | null;
|
|
132
|
+
/** Anonymous ID (always present) */
|
|
53
133
|
anonymous_id: string;
|
|
134
|
+
/** Device ID (persists across sessions) */
|
|
54
135
|
device_id: string;
|
|
55
|
-
properties
|
|
56
|
-
|
|
136
|
+
/** User properties */
|
|
137
|
+
properties: Properties;
|
|
138
|
+
/** Identity state */
|
|
139
|
+
user_state: 'anonymous' | 'identified';
|
|
57
140
|
}
|
|
58
141
|
export interface UserProperties {
|
|
59
142
|
[key: string]: any;
|
|
60
143
|
}
|
|
61
|
-
export interface PropertyOperations {
|
|
62
|
-
$set?: Record<string, any>;
|
|
63
|
-
$set_once?: Record<string, any>;
|
|
64
|
-
}
|
|
65
144
|
export interface AliasEvent {
|
|
66
145
|
distinct_id: string;
|
|
67
146
|
original: string;
|
|
68
147
|
}
|
|
148
|
+
export interface WebVitalMetric {
|
|
149
|
+
name: string;
|
|
150
|
+
value: number;
|
|
151
|
+
delta: number;
|
|
152
|
+
rating: 'good' | 'needs-improvement' | 'poor';
|
|
153
|
+
id: string;
|
|
154
|
+
navigationType: string;
|
|
155
|
+
}
|
|
156
|
+
export interface GeolocationData {
|
|
157
|
+
country?: string;
|
|
158
|
+
locale?: string;
|
|
159
|
+
}
|
|
160
|
+
export interface GroupsConfig {
|
|
161
|
+
[groupType: string]: string;
|
|
162
|
+
}
|
|
163
|
+
export interface FeatureFlagsConfig {
|
|
164
|
+
[flagKey: string]: boolean | string;
|
|
165
|
+
}
|
|
166
|
+
export type SessionIdChangedCallback = (newSessionId: string, previousSessionId: string | null, changeInfo: {
|
|
167
|
+
reason: 'timeout' | 'new_session' | 'reset';
|
|
168
|
+
}) => void;
|
|
169
|
+
export interface RequestOptions {
|
|
170
|
+
method?: 'POST' | 'GET';
|
|
171
|
+
headers?: Record<string, string>;
|
|
172
|
+
timeout?: number;
|
|
173
|
+
retry?: boolean;
|
|
174
|
+
}
|
|
175
|
+
export interface RemoteConfig {
|
|
176
|
+
/** Default to identified_only mode */
|
|
177
|
+
defaultIdentifiedOnly?: boolean;
|
|
178
|
+
/** Feature flags */
|
|
179
|
+
featureFlags?: FeatureFlagsConfig;
|
|
180
|
+
/** Session recording config */
|
|
181
|
+
sessionRecording?: {
|
|
182
|
+
enabled?: boolean;
|
|
183
|
+
sampleRate?: number;
|
|
184
|
+
};
|
|
185
|
+
}
|
package/dist/user-manager.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { UserIdentity, AliasEvent,
|
|
1
|
+
import { UserIdentity, AliasEvent, PersistenceMethod } from "./types";
|
|
2
2
|
export declare class UserManager {
|
|
3
3
|
private storageMethod;
|
|
4
4
|
private domain?;
|
|
5
5
|
private userIdentity;
|
|
6
6
|
private _cachedPersonProperties;
|
|
7
|
-
constructor(storageMethod?:
|
|
7
|
+
constructor(storageMethod?: PersistenceMethod, domain?: string);
|
|
8
8
|
/**
|
|
9
9
|
* Get current user identity
|
|
10
10
|
*/
|
package/dist/vtilt.d.ts
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { VTiltConfig, EventPayload } from "./types";
|
|
2
2
|
import { HistoryAutocapture } from "./extensions/history-autocapture";
|
|
3
|
-
|
|
4
|
-
url: string;
|
|
5
|
-
event: any;
|
|
6
|
-
}
|
|
3
|
+
import { type QueuedRequest } from "./request-queue";
|
|
7
4
|
export declare class VTilt {
|
|
8
5
|
private configManager;
|
|
9
6
|
private sessionManager;
|
|
10
7
|
private userManager;
|
|
11
8
|
private webVitalsManager;
|
|
9
|
+
private requestQueue;
|
|
10
|
+
private retryQueue;
|
|
11
|
+
private rateLimiter;
|
|
12
12
|
historyAutocapture?: HistoryAutocapture;
|
|
13
13
|
__loaded: boolean;
|
|
14
|
-
private
|
|
15
|
-
private
|
|
14
|
+
private _initial_pageview_captured;
|
|
15
|
+
private _visibility_state_listener;
|
|
16
16
|
__request_queue: QueuedRequest[];
|
|
17
|
-
private
|
|
17
|
+
private _has_warned_about_config;
|
|
18
|
+
private _set_once_properties_sent;
|
|
18
19
|
constructor(config?: Partial<VTiltConfig>);
|
|
19
20
|
/**
|
|
20
21
|
* Initializes a new instance of the VTilt tracking object.
|
|
@@ -52,6 +53,17 @@ export declare class VTilt {
|
|
|
52
53
|
* This internal method should only be called by `init()`.
|
|
53
54
|
*/
|
|
54
55
|
private _init;
|
|
56
|
+
/**
|
|
57
|
+
* Start the request queue if user hasn't opted out
|
|
58
|
+
* Following PostHog's pattern - called from both _init() and _dom_loaded()
|
|
59
|
+
* Safe to call multiple times as enable() is idempotent
|
|
60
|
+
*/
|
|
61
|
+
private _start_queue_if_opted_in;
|
|
62
|
+
/**
|
|
63
|
+
* Set up handler to flush event queue on page unload
|
|
64
|
+
* Uses both beforeunload and pagehide for maximum compatibility
|
|
65
|
+
*/
|
|
66
|
+
private _setup_unload_handler;
|
|
55
67
|
/**
|
|
56
68
|
* Returns a string representation of the instance name
|
|
57
69
|
* Used for debugging and logging
|
|
@@ -69,7 +81,7 @@ export declare class VTilt {
|
|
|
69
81
|
* Returns true if projectId and token are present, false otherwise
|
|
70
82
|
* Logs a warning only once per instance if not configured
|
|
71
83
|
*/
|
|
72
|
-
private
|
|
84
|
+
private _is_configured;
|
|
73
85
|
/**
|
|
74
86
|
* Build the tracking URL with token in query parameters
|
|
75
87
|
*/
|
|
@@ -77,8 +89,26 @@ export declare class VTilt {
|
|
|
77
89
|
/**
|
|
78
90
|
* Send HTTP request
|
|
79
91
|
* This is the central entry point for all tracking requests
|
|
92
|
+
* Events are batched and sent every 3 seconds for better performance
|
|
80
93
|
*/
|
|
81
94
|
private sendRequest;
|
|
95
|
+
/**
|
|
96
|
+
* Send a batched request with multiple events
|
|
97
|
+
* Called by RequestQueue when flushing
|
|
98
|
+
* Uses RetryQueue for automatic retry on failure
|
|
99
|
+
*/
|
|
100
|
+
private _send_batched_request;
|
|
101
|
+
/**
|
|
102
|
+
* Send HTTP request and return status code
|
|
103
|
+
* Uses GZip compression for payloads > 1KB
|
|
104
|
+
* Used by RetryQueue for retryable requests
|
|
105
|
+
*/
|
|
106
|
+
private _send_http_request;
|
|
107
|
+
/**
|
|
108
|
+
* Send request using sendBeacon for reliable delivery on page unload
|
|
109
|
+
* Uses GZip compression for payloads > 1KB
|
|
110
|
+
*/
|
|
111
|
+
private _send_beacon_request;
|
|
82
112
|
/**
|
|
83
113
|
* Send a queued request (called after DOM is loaded)
|
|
84
114
|
*/
|
|
@@ -92,8 +122,16 @@ export declare class VTilt {
|
|
|
92
122
|
*
|
|
93
123
|
* @param name - Event name
|
|
94
124
|
* @param payload - Event payload
|
|
125
|
+
* @param options - Optional capture options
|
|
126
|
+
*/
|
|
127
|
+
capture(name: string, payload: EventPayload, options?: {
|
|
128
|
+
skip_client_rate_limiting?: boolean;
|
|
129
|
+
}): void;
|
|
130
|
+
/**
|
|
131
|
+
* Internal capture method that bypasses rate limiting
|
|
132
|
+
* Used for system events like rate limit warnings
|
|
95
133
|
*/
|
|
96
|
-
|
|
134
|
+
private _capture_internal;
|
|
97
135
|
/**
|
|
98
136
|
* Track a custom event (alias for capture)
|
|
99
137
|
*/
|
|
@@ -187,8 +225,9 @@ export declare class VTilt {
|
|
|
187
225
|
createAlias(alias: string, original?: string): void;
|
|
188
226
|
/**
|
|
189
227
|
* Capture initial pageview with visibility check
|
|
228
|
+
* Note: The capture_pageview config check happens at the call site (in _init)
|
|
190
229
|
*/
|
|
191
|
-
private
|
|
230
|
+
private _capture_initial_pageview;
|
|
192
231
|
/**
|
|
193
232
|
* Get current configuration
|
|
194
233
|
*/
|
|
@@ -214,7 +253,8 @@ export declare class VTilt {
|
|
|
214
253
|
*/
|
|
215
254
|
_execute_array(array: any[]): void;
|
|
216
255
|
/**
|
|
217
|
-
* Called when DOM is loaded - processes queued requests
|
|
256
|
+
* Called when DOM is loaded - processes queued requests and enables batching
|
|
257
|
+
* Following PostHog's pattern in _dom_loaded()
|
|
218
258
|
*/
|
|
219
259
|
_dom_loaded(): void;
|
|
220
260
|
}
|
|
@@ -254,4 +294,3 @@ export declare function init_as_module(): VTilt;
|
|
|
254
294
|
* ]
|
|
255
295
|
*/
|
|
256
296
|
export declare function init_from_snippet(): void;
|
|
257
|
-
export {};
|
package/lib/config.js
CHANGED
|
@@ -11,19 +11,17 @@ class ConfigManager {
|
|
|
11
11
|
parseConfigFromScript(initialConfig) {
|
|
12
12
|
if (!document.currentScript) {
|
|
13
13
|
return {
|
|
14
|
-
projectId: initialConfig.projectId || "",
|
|
15
14
|
token: initialConfig.token || "",
|
|
16
15
|
...initialConfig,
|
|
17
16
|
};
|
|
18
17
|
}
|
|
19
18
|
const script = document.currentScript;
|
|
20
19
|
const config = {
|
|
21
|
-
projectId: "", // Required field with default
|
|
22
20
|
token: "", // Required field with default
|
|
23
21
|
...initialConfig,
|
|
24
22
|
};
|
|
25
23
|
// Parse basic attributes
|
|
26
|
-
config.
|
|
24
|
+
config.api_host = script.getAttribute("data-api-host") || script.getAttribute("data-host") || initialConfig.api_host;
|
|
27
25
|
config.proxy = script.getAttribute("data-proxy") || initialConfig.proxy;
|
|
28
26
|
config.proxyUrl =
|
|
29
27
|
script.getAttribute("data-proxy-url") || initialConfig.proxyUrl;
|
|
@@ -36,24 +34,19 @@ class ConfigManager {
|
|
|
36
34
|
script.getAttribute("data-storage") || initialConfig.storage;
|
|
37
35
|
config.stringifyPayload =
|
|
38
36
|
script.getAttribute("data-stringify-payload") !== "false";
|
|
39
|
-
config.
|
|
40
|
-
script.getAttribute("
|
|
41
|
-
|
|
42
|
-
initialConfig.webVitals;
|
|
37
|
+
config.capture_performance =
|
|
38
|
+
script.getAttribute("data-capture-performance") === "true" ||
|
|
39
|
+
initialConfig.capture_performance;
|
|
43
40
|
// Check for conflicting proxy configurations
|
|
44
41
|
if (config.proxy && config.proxyUrl) {
|
|
45
42
|
console.error("Error: Both data-proxy and data-proxy-url are specified. Please use only one of them.");
|
|
46
43
|
throw new Error("Both data-proxy and data-proxy-url are specified. Please use only one of them.");
|
|
47
44
|
}
|
|
48
|
-
// Parse global attributes
|
|
45
|
+
// Parse global attributes (data-vt-* attributes)
|
|
49
46
|
config.globalAttributes = { ...initialConfig.globalAttributes };
|
|
50
47
|
// NamedNodeMap is not iterable, so use Array.from to iterate over attributes
|
|
51
48
|
for (const attr of Array.from(script.attributes)) {
|
|
52
|
-
if (attr.name.startsWith("
|
|
53
|
-
config.globalAttributes[attr.name.slice(3).replace(/-/g, "_")] =
|
|
54
|
-
attr.value;
|
|
55
|
-
}
|
|
56
|
-
if (attr.name.startsWith("data-tb-")) {
|
|
49
|
+
if (attr.name.startsWith("data-vt-")) {
|
|
57
50
|
config.globalAttributes[attr.name.slice(8).replace(/-/g, "_")] =
|
|
58
51
|
attr.value;
|
|
59
52
|
}
|