@v-tilt/browser 1.0.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 +2 -0
- package/dist/array.js.map +1 -0
- package/dist/array.no-external.js +2 -0
- package/dist/array.no-external.js.map +1 -0
- package/dist/config.d.ts +17 -0
- package/dist/constants.d.ts +10 -0
- package/dist/entrypoints/array.d.ts +1 -0
- package/dist/entrypoints/array.no-external.d.ts +1 -0
- package/dist/entrypoints/main.cjs.d.ts +4 -0
- package/dist/entrypoints/module.es.d.ts +3 -0
- package/dist/entrypoints/module.no-external.es.d.ts +4 -0
- package/dist/geolocation.d.ts +5 -0
- package/dist/main.js +2 -0
- package/dist/main.js.map +1 -0
- package/dist/module.d.ts +214 -0
- package/dist/module.js +2 -0
- package/dist/module.js.map +1 -0
- package/dist/module.no-external.d.ts +214 -0
- package/dist/module.no-external.js +2 -0
- package/dist/module.no-external.js.map +1 -0
- package/dist/session.d.ts +26 -0
- package/dist/tracking.d.ts +112 -0
- package/dist/types.d.ts +67 -0
- package/dist/user-manager.d.ts +152 -0
- package/dist/utils/globals.d.ts +4 -0
- package/dist/utils/index.d.ts +30 -0
- package/dist/utils.d.ts +21 -0
- package/dist/vtilt.d.ts +178 -0
- package/dist/web-vitals.d.ts +11 -0
- package/lib/config.d.ts +17 -0
- package/lib/config.js +76 -0
- package/lib/constants.d.ts +10 -0
- package/lib/constants.js +463 -0
- package/lib/entrypoints/array.d.ts +1 -0
- package/lib/entrypoints/array.js +3 -0
- package/lib/entrypoints/array.no-external.d.ts +1 -0
- package/lib/entrypoints/array.no-external.js +4 -0
- package/lib/entrypoints/main.cjs.d.ts +4 -0
- package/lib/entrypoints/main.cjs.js +29 -0
- package/lib/entrypoints/module.es.d.ts +3 -0
- package/lib/entrypoints/module.es.js +22 -0
- package/lib/entrypoints/module.no-external.es.d.ts +4 -0
- package/lib/entrypoints/module.no-external.es.js +23 -0
- package/lib/geolocation.d.ts +5 -0
- package/lib/geolocation.js +26 -0
- package/lib/session.d.ts +26 -0
- package/lib/session.js +115 -0
- package/lib/tracking.d.ts +112 -0
- package/lib/tracking.js +326 -0
- package/lib/types.d.ts +67 -0
- package/lib/types.js +2 -0
- package/lib/user-manager.d.ts +152 -0
- package/lib/user-manager.js +565 -0
- package/lib/utils/globals.d.ts +4 -0
- package/lib/utils/globals.js +5 -0
- package/lib/utils/index.d.ts +30 -0
- package/lib/utils/index.js +89 -0
- package/lib/utils.d.ts +21 -0
- package/lib/utils.js +57 -0
- package/lib/vtilt.d.ts +178 -0
- package/lib/vtilt.js +403 -0
- package/lib/web-vitals.d.ts +11 -0
- package/lib/web-vitals.js +67 -0
- package/package.json +61 -0
package/lib/utils.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { EventPayload } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Generate uuid to identify the session. Random, not data-derived
|
|
4
|
+
*/
|
|
5
|
+
export declare function uuidv4(): string;
|
|
6
|
+
/**
|
|
7
|
+
* Validate user agent string
|
|
8
|
+
*/
|
|
9
|
+
export declare function isValidUserAgent(userAgent: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Validate payload string
|
|
12
|
+
*/
|
|
13
|
+
export declare function isValidPayload(payloadStr: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Try to mask PPI and potential sensible attributes
|
|
16
|
+
*/
|
|
17
|
+
export declare function maskSuspiciousAttributes(payload: EventPayload): string;
|
|
18
|
+
/**
|
|
19
|
+
* Check if current environment is a test environment
|
|
20
|
+
*/
|
|
21
|
+
export declare function isTestEnvironment(): boolean;
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uuidv4 = uuidv4;
|
|
4
|
+
exports.isValidUserAgent = isValidUserAgent;
|
|
5
|
+
exports.isValidPayload = isValidPayload;
|
|
6
|
+
exports.maskSuspiciousAttributes = maskSuspiciousAttributes;
|
|
7
|
+
exports.isTestEnvironment = isTestEnvironment;
|
|
8
|
+
const constants_1 = require("./constants");
|
|
9
|
+
/**
|
|
10
|
+
* Generate uuid to identify the session. Random, not data-derived
|
|
11
|
+
*/
|
|
12
|
+
function uuidv4() {
|
|
13
|
+
return (`${1e7}-${1e3}-${4e3}-${8e3}-${1e11}`).replace(/[018]/g, (c) => (+c ^
|
|
14
|
+
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (+c / 4)))).toString(16));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Validate user agent string
|
|
18
|
+
*/
|
|
19
|
+
function isValidUserAgent(userAgent) {
|
|
20
|
+
// empty is fine
|
|
21
|
+
if (!userAgent || typeof userAgent !== 'string') {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
if (userAgent.length > 500) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate payload string
|
|
31
|
+
*/
|
|
32
|
+
function isValidPayload(payloadStr) {
|
|
33
|
+
if (!payloadStr || typeof payloadStr !== 'string') {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (payloadStr.length < 2 || payloadStr.length > 10240) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Try to mask PPI and potential sensible attributes
|
|
43
|
+
*/
|
|
44
|
+
function maskSuspiciousAttributes(payload) {
|
|
45
|
+
// Deep copy
|
|
46
|
+
let _payload = JSON.stringify(payload);
|
|
47
|
+
constants_1.ATTRIBUTES_TO_MASK.forEach((attr) => {
|
|
48
|
+
_payload = _payload.replace(new RegExp(`("${attr}"):(".+?"|\\d+)`, 'gmi'), '$1:"********"');
|
|
49
|
+
});
|
|
50
|
+
return _payload;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Check if current environment is a test environment
|
|
54
|
+
*/
|
|
55
|
+
function isTestEnvironment() {
|
|
56
|
+
return !!(('__nightmare' in window) || window.navigator.webdriver || ('Cypress' in window));
|
|
57
|
+
}
|
package/lib/vtilt.d.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { VTiltConfig, EventPayload } from "./types";
|
|
2
|
+
export declare class VTilt {
|
|
3
|
+
private configManager;
|
|
4
|
+
private trackingManager;
|
|
5
|
+
private webVitalsManager;
|
|
6
|
+
private initialized;
|
|
7
|
+
constructor(config?: Partial<VTiltConfig>);
|
|
8
|
+
/**
|
|
9
|
+
* Initialize VTilt tracking
|
|
10
|
+
*/
|
|
11
|
+
init(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Track a custom event
|
|
14
|
+
*/
|
|
15
|
+
trackEvent(name: string, payload?: EventPayload): void;
|
|
16
|
+
/**
|
|
17
|
+
* Identify a user with PostHog-style property operations
|
|
18
|
+
* Copied from PostHog's identify method signature
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```js
|
|
22
|
+
* // Basic identify with properties
|
|
23
|
+
* vTilt.identify('user_123',
|
|
24
|
+
* { name: 'John Doe', email: 'john@example.com' }, // $set properties
|
|
25
|
+
* { first_login: new Date().toISOString() } // $set_once properties
|
|
26
|
+
* )
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```js
|
|
31
|
+
* // If no $set is provided, all properties are treated as $set
|
|
32
|
+
* vTilt.identify('user_123', { name: 'John Doe', email: 'john@example.com' })
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
identify(distinctId?: string, userPropertiesToSet?: Record<string, any>, userPropertiesToSetOnce?: Record<string, any>): void;
|
|
36
|
+
/**
|
|
37
|
+
* Set user properties with PostHog-style operations
|
|
38
|
+
* Sets properties on the person profile associated with the current distinct_id
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```js
|
|
42
|
+
* // Set properties that can be updated
|
|
43
|
+
* vTilt.setUserProperties({ name: 'John Doe', email: 'john@example.com' })
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```js
|
|
48
|
+
* // Set properties with $set and $set_once operations
|
|
49
|
+
* vTilt.setUserProperties(
|
|
50
|
+
* { name: 'John Doe', last_login: new Date().toISOString() }, // $set properties
|
|
51
|
+
* { first_login: new Date().toISOString() } // $set_once properties
|
|
52
|
+
* )
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @param userPropertiesToSet Optional: Properties to set (can be updated)
|
|
56
|
+
* @param userPropertiesToSetOnce Optional: Properties to set once (preserves first value)
|
|
57
|
+
*/
|
|
58
|
+
setUserProperties(userPropertiesToSet?: Record<string, any>, userPropertiesToSetOnce?: Record<string, any>): void;
|
|
59
|
+
/**
|
|
60
|
+
* Reset user identity (logout)
|
|
61
|
+
* PostHog behavior: Clears all user data, generates new anonymous ID
|
|
62
|
+
*
|
|
63
|
+
* @param reset_device_id - If true, also resets device_id. Default: false
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* // Reset on user logout
|
|
67
|
+
* vtilt.resetUser()
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // Reset and generate new device ID
|
|
71
|
+
* vtilt.resetUser(true)
|
|
72
|
+
*/
|
|
73
|
+
resetUser(reset_device_id?: boolean): void;
|
|
74
|
+
/**
|
|
75
|
+
* Get current user identity
|
|
76
|
+
*/
|
|
77
|
+
getUserIdentity(): import("./types").UserIdentity;
|
|
78
|
+
/**
|
|
79
|
+
* Get current device ID
|
|
80
|
+
*/
|
|
81
|
+
getDeviceId(): string;
|
|
82
|
+
/**
|
|
83
|
+
* Get current user state
|
|
84
|
+
*/
|
|
85
|
+
getUserState(): "anonymous" | "identified";
|
|
86
|
+
/**
|
|
87
|
+
* Create an alias to link two distinct IDs
|
|
88
|
+
* PostHog behavior: Links anonymous session to account on signup
|
|
89
|
+
*
|
|
90
|
+
* @param alias - A unique identifier that you want to use for this user in the future
|
|
91
|
+
* @param original - The current identifier being used for this user (optional, defaults to current distinct_id)
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* // Link anonymous user to account on signup
|
|
95
|
+
* vtilt.createAlias('user_12345')
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* // Explicit alias with original ID
|
|
99
|
+
* vtilt.createAlias('user_12345', 'anonymous_abc123')
|
|
100
|
+
*/
|
|
101
|
+
createAlias(alias: string, original?: string): void;
|
|
102
|
+
/**
|
|
103
|
+
* Setup page tracking with history API support
|
|
104
|
+
*/
|
|
105
|
+
private setupPageTracking;
|
|
106
|
+
/**
|
|
107
|
+
* Track page hit
|
|
108
|
+
*/
|
|
109
|
+
private trackPageHit;
|
|
110
|
+
/**
|
|
111
|
+
* Setup visibility change tracking for prerendered pages
|
|
112
|
+
*/
|
|
113
|
+
private setupVisibilityTracking;
|
|
114
|
+
/**
|
|
115
|
+
* Get current configuration
|
|
116
|
+
*/
|
|
117
|
+
getConfig(): VTiltConfig;
|
|
118
|
+
/**
|
|
119
|
+
* Get current session ID
|
|
120
|
+
*/
|
|
121
|
+
getSessionId(): string | null;
|
|
122
|
+
/**
|
|
123
|
+
* Update configuration
|
|
124
|
+
*/
|
|
125
|
+
updateConfig(config: Partial<VTiltConfig>): void;
|
|
126
|
+
/**
|
|
127
|
+
* _execute_array() deals with processing any VTilt function
|
|
128
|
+
* calls that were called before the VTilt library was loaded
|
|
129
|
+
* (and are thus stored in an array so they can be called later)
|
|
130
|
+
*
|
|
131
|
+
* Note: we fire off all the VTilt function calls BEFORE we fire off
|
|
132
|
+
* tracking calls. This is so identify/setUserProperties/updateConfig calls
|
|
133
|
+
* can properly modify early tracking calls.
|
|
134
|
+
*
|
|
135
|
+
* @param {Array} array Array of queued calls in format [methodName, ...args]
|
|
136
|
+
*/
|
|
137
|
+
_execute_array(array: any[]): void;
|
|
138
|
+
/**
|
|
139
|
+
* Called when DOM is loaded - processes queued requests
|
|
140
|
+
*/
|
|
141
|
+
_dom_loaded(): void;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Initialize VTilt as a module (similar to PostHog's init_as_module)
|
|
145
|
+
* Returns an uninitialized VTilt instance that the user must call init() on
|
|
146
|
+
*/
|
|
147
|
+
export declare function init_as_module(): VTilt;
|
|
148
|
+
/**
|
|
149
|
+
* Initialize VTilt from snippet (similar to PostHog's init_from_snippet)
|
|
150
|
+
* Processes queued calls from the snippet stub and replaces it with real instance
|
|
151
|
+
*
|
|
152
|
+
* The snippet uses some clever tricks to allow deferred loading of array.js (this code)
|
|
153
|
+
*
|
|
154
|
+
* window.vt is an array which the queue of calls made before the lib is loaded
|
|
155
|
+
* It has methods attached to it to simulate the vt object so for instance
|
|
156
|
+
*
|
|
157
|
+
* window.vt.init("projectId", {token: "token", host: "host"})
|
|
158
|
+
* window.vt.trackEvent("my-event", {foo: "bar"})
|
|
159
|
+
*
|
|
160
|
+
* ... will mean that window.vt will look like this:
|
|
161
|
+
* window.vt == [
|
|
162
|
+
* ["trackEvent", "my-event", {foo: "bar"}]
|
|
163
|
+
* ]
|
|
164
|
+
*
|
|
165
|
+
* window.vt._i == [
|
|
166
|
+
* ["projectId", {token: "token", host: "host"}, "vt"]
|
|
167
|
+
* ]
|
|
168
|
+
*
|
|
169
|
+
* If a name is given to the init function then the same as above is true but as a sub-property on the object:
|
|
170
|
+
*
|
|
171
|
+
* window.vt.init("projectId", {token: "token"}, "vt2")
|
|
172
|
+
* window.vt.vt2.trackEvent("my-event", {foo: "bar"})
|
|
173
|
+
*
|
|
174
|
+
* window.vt.vt2 == [
|
|
175
|
+
* ["trackEvent", "my-event", {foo: "bar"}]
|
|
176
|
+
* ]
|
|
177
|
+
*/
|
|
178
|
+
export declare function init_from_snippet(): void;
|
package/lib/vtilt.js
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.VTilt = void 0;
|
|
5
|
+
exports.init_as_module = init_as_module;
|
|
6
|
+
exports.init_from_snippet = init_from_snippet;
|
|
7
|
+
const config_1 = require("./config");
|
|
8
|
+
const tracking_1 = require("./tracking");
|
|
9
|
+
const web_vitals_1 = require("./web-vitals");
|
|
10
|
+
const utils_1 = require("./utils");
|
|
11
|
+
const globals_1 = require("./utils/globals");
|
|
12
|
+
// Helper to check if value is an array
|
|
13
|
+
const isArray = Array.isArray;
|
|
14
|
+
class VTilt {
|
|
15
|
+
constructor(config = {}) {
|
|
16
|
+
this.initialized = false;
|
|
17
|
+
this.configManager = new config_1.ConfigManager(config);
|
|
18
|
+
this.trackingManager = new tracking_1.TrackingManager(this.configManager.getConfig());
|
|
19
|
+
this.webVitalsManager = new web_vitals_1.WebVitalsManager(this.configManager.getConfig(), this.trackingManager);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Initialize VTilt tracking
|
|
23
|
+
*/
|
|
24
|
+
init() {
|
|
25
|
+
if (this.initialized) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
this.setupPageTracking();
|
|
29
|
+
this.initialized = true;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Track a custom event
|
|
33
|
+
*/
|
|
34
|
+
trackEvent(name, payload = {}) {
|
|
35
|
+
this.trackingManager.sendEvent(name, payload);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Identify a user with PostHog-style property operations
|
|
39
|
+
* Copied from PostHog's identify method signature
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```js
|
|
43
|
+
* // Basic identify with properties
|
|
44
|
+
* vTilt.identify('user_123',
|
|
45
|
+
* { name: 'John Doe', email: 'john@example.com' }, // $set properties
|
|
46
|
+
* { first_login: new Date().toISOString() } // $set_once properties
|
|
47
|
+
* )
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```js
|
|
52
|
+
* // If no $set is provided, all properties are treated as $set
|
|
53
|
+
* vTilt.identify('user_123', { name: 'John Doe', email: 'john@example.com' })
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
identify(distinctId, userPropertiesToSet, userPropertiesToSetOnce) {
|
|
57
|
+
this.trackingManager.identify(distinctId, userPropertiesToSet, userPropertiesToSetOnce);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Set user properties with PostHog-style operations
|
|
61
|
+
* Sets properties on the person profile associated with the current distinct_id
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```js
|
|
65
|
+
* // Set properties that can be updated
|
|
66
|
+
* vTilt.setUserProperties({ name: 'John Doe', email: 'john@example.com' })
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```js
|
|
71
|
+
* // Set properties with $set and $set_once operations
|
|
72
|
+
* vTilt.setUserProperties(
|
|
73
|
+
* { name: 'John Doe', last_login: new Date().toISOString() }, // $set properties
|
|
74
|
+
* { first_login: new Date().toISOString() } // $set_once properties
|
|
75
|
+
* )
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @param userPropertiesToSet Optional: Properties to set (can be updated)
|
|
79
|
+
* @param userPropertiesToSetOnce Optional: Properties to set once (preserves first value)
|
|
80
|
+
*/
|
|
81
|
+
setUserProperties(userPropertiesToSet, userPropertiesToSetOnce) {
|
|
82
|
+
this.trackingManager.setUserProperties(userPropertiesToSet, userPropertiesToSetOnce);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Reset user identity (logout)
|
|
86
|
+
* PostHog behavior: Clears all user data, generates new anonymous ID
|
|
87
|
+
*
|
|
88
|
+
* @param reset_device_id - If true, also resets device_id. Default: false
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* // Reset on user logout
|
|
92
|
+
* vtilt.resetUser()
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* // Reset and generate new device ID
|
|
96
|
+
* vtilt.resetUser(true)
|
|
97
|
+
*/
|
|
98
|
+
resetUser(reset_device_id) {
|
|
99
|
+
this.trackingManager.resetUser(reset_device_id);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get current user identity
|
|
103
|
+
*/
|
|
104
|
+
getUserIdentity() {
|
|
105
|
+
return this.trackingManager.getUserIdentity();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get current device ID
|
|
109
|
+
*/
|
|
110
|
+
getDeviceId() {
|
|
111
|
+
return this.trackingManager.getDeviceId();
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get current user state
|
|
115
|
+
*/
|
|
116
|
+
getUserState() {
|
|
117
|
+
return this.trackingManager.getUserState();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Create an alias to link two distinct IDs
|
|
121
|
+
* PostHog behavior: Links anonymous session to account on signup
|
|
122
|
+
*
|
|
123
|
+
* @param alias - A unique identifier that you want to use for this user in the future
|
|
124
|
+
* @param original - The current identifier being used for this user (optional, defaults to current distinct_id)
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* // Link anonymous user to account on signup
|
|
128
|
+
* vtilt.createAlias('user_12345')
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* // Explicit alias with original ID
|
|
132
|
+
* vtilt.createAlias('user_12345', 'anonymous_abc123')
|
|
133
|
+
*/
|
|
134
|
+
createAlias(alias, original) {
|
|
135
|
+
this.trackingManager.createAlias(alias, original);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Setup page tracking with history API support
|
|
139
|
+
*/
|
|
140
|
+
setupPageTracking() {
|
|
141
|
+
// Track initial page load
|
|
142
|
+
this.trackPageHit();
|
|
143
|
+
// Track hash changes
|
|
144
|
+
window.addEventListener("hashchange", () => this.trackPageHit());
|
|
145
|
+
// Track history API changes
|
|
146
|
+
const history = window.history;
|
|
147
|
+
if (history.pushState) {
|
|
148
|
+
const originalPushState = history.pushState;
|
|
149
|
+
history.pushState = (...args) => {
|
|
150
|
+
originalPushState.apply(this, args);
|
|
151
|
+
this.trackPageHit();
|
|
152
|
+
};
|
|
153
|
+
window.addEventListener("popstate", () => this.trackPageHit());
|
|
154
|
+
}
|
|
155
|
+
// Handle visibility changes for prerendered pages
|
|
156
|
+
this.setupVisibilityTracking();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Track page hit
|
|
160
|
+
*/
|
|
161
|
+
trackPageHit() {
|
|
162
|
+
if ((0, utils_1.isTestEnvironment)()) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
this.trackingManager.trackPageHit();
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Setup visibility change tracking for prerendered pages
|
|
169
|
+
*/
|
|
170
|
+
setupVisibilityTracking() {
|
|
171
|
+
const lastPage = null;
|
|
172
|
+
const handleVisibilityChange = () => {
|
|
173
|
+
if (!lastPage && document.visibilityState === "visible") {
|
|
174
|
+
this.trackPageHit();
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
// Only track if page was prerendered and is now becoming visible
|
|
178
|
+
// For normal page loads, trackPageHit() is already called in setupPageTracking()
|
|
179
|
+
if (document.visibilityState === "prerender") {
|
|
180
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get current configuration
|
|
185
|
+
*/
|
|
186
|
+
getConfig() {
|
|
187
|
+
return this.configManager.getConfig();
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Get current session ID
|
|
191
|
+
*/
|
|
192
|
+
getSessionId() {
|
|
193
|
+
return this.trackingManager.getSessionId();
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Update configuration
|
|
197
|
+
*/
|
|
198
|
+
updateConfig(config) {
|
|
199
|
+
this.configManager.updateConfig(config);
|
|
200
|
+
// Recreate managers with new config
|
|
201
|
+
this.trackingManager = new tracking_1.TrackingManager(this.configManager.getConfig());
|
|
202
|
+
this.webVitalsManager = new web_vitals_1.WebVitalsManager(this.configManager.getConfig(), this.trackingManager);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* _execute_array() deals with processing any VTilt function
|
|
206
|
+
* calls that were called before the VTilt library was loaded
|
|
207
|
+
* (and are thus stored in an array so they can be called later)
|
|
208
|
+
*
|
|
209
|
+
* Note: we fire off all the VTilt function calls BEFORE we fire off
|
|
210
|
+
* tracking calls. This is so identify/setUserProperties/updateConfig calls
|
|
211
|
+
* can properly modify early tracking calls.
|
|
212
|
+
*
|
|
213
|
+
* @param {Array} array Array of queued calls in format [methodName, ...args]
|
|
214
|
+
*/
|
|
215
|
+
_execute_array(array) {
|
|
216
|
+
if (!Array.isArray(array)) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
array.forEach((item) => {
|
|
220
|
+
if (item && Array.isArray(item) && item.length > 0) {
|
|
221
|
+
const methodName = item[0];
|
|
222
|
+
const args = item.slice(1);
|
|
223
|
+
if (typeof this[methodName] === "function") {
|
|
224
|
+
try {
|
|
225
|
+
this[methodName](...args);
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
console.error(`VTilt: Error executing queued call ${methodName}:`, error);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Called when DOM is loaded - processes queued requests
|
|
236
|
+
*/
|
|
237
|
+
_dom_loaded() {
|
|
238
|
+
if (this.trackingManager) {
|
|
239
|
+
// Process all queued requests
|
|
240
|
+
this.trackingManager.__request_queue.forEach((item) => {
|
|
241
|
+
this.trackingManager._send_retriable_request(item);
|
|
242
|
+
});
|
|
243
|
+
// Clear the queue
|
|
244
|
+
this.trackingManager.__request_queue = [];
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
exports.VTilt = VTilt;
|
|
249
|
+
const instances = {};
|
|
250
|
+
const PRIMARY_INSTANCE_NAME = "vTilt";
|
|
251
|
+
// Browser support detection for request queuing
|
|
252
|
+
// IE<10 does not support cross-origin XHR's but script tags
|
|
253
|
+
// with defer won't block window.onload; ENQUEUE_REQUESTS
|
|
254
|
+
// should only be true for Opera<12
|
|
255
|
+
const SUPPORTS_REQUEST = typeof XMLHttpRequest !== "undefined" || typeof fetch !== "undefined";
|
|
256
|
+
const userAgent = typeof window !== "undefined" ? (_a = window.navigator) === null || _a === void 0 ? void 0 : _a.userAgent : undefined;
|
|
257
|
+
let ENQUEUE_REQUESTS = !SUPPORTS_REQUEST &&
|
|
258
|
+
(userAgent === null || userAgent === void 0 ? void 0 : userAgent.indexOf("MSIE")) === -1 &&
|
|
259
|
+
(userAgent === null || userAgent === void 0 ? void 0 : userAgent.indexOf("Mozilla")) === -1;
|
|
260
|
+
// Expose ENQUEUE_REQUESTS to window for TrackingManager to access
|
|
261
|
+
if (typeof window !== "undefined") {
|
|
262
|
+
window.__VTILT_ENQUEUE_REQUESTS = ENQUEUE_REQUESTS;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Add DOM loaded handler to process queued requests
|
|
266
|
+
* Similar to PostHog's add_dom_loaded_handler
|
|
267
|
+
*/
|
|
268
|
+
const add_dom_loaded_handler = function () {
|
|
269
|
+
// Cross browser DOM Loaded support
|
|
270
|
+
function dom_loaded_handler() {
|
|
271
|
+
// function flag since we only want to execute this once
|
|
272
|
+
if (dom_loaded_handler.done) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
dom_loaded_handler.done = true;
|
|
276
|
+
// Disable request queuing now that DOM is loaded
|
|
277
|
+
ENQUEUE_REQUESTS = false;
|
|
278
|
+
if (typeof window !== "undefined") {
|
|
279
|
+
window.__VTILT_ENQUEUE_REQUESTS = false;
|
|
280
|
+
}
|
|
281
|
+
// Process queued requests for all instances
|
|
282
|
+
(0, utils_1.each)(instances, function (inst) {
|
|
283
|
+
inst._dom_loaded();
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
if (typeof document !== "undefined" &&
|
|
287
|
+
typeof document.addEventListener === "function") {
|
|
288
|
+
if (document.readyState === "complete") {
|
|
289
|
+
// Safari 4 can fire the DOMContentLoaded event before loading all
|
|
290
|
+
// external JS (including this file). you will see some copypasta
|
|
291
|
+
// on the internet that checks for 'complete' and 'loaded', but
|
|
292
|
+
// 'loaded' is an IE thing
|
|
293
|
+
dom_loaded_handler();
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
(0, utils_1.addEventListener)(document, "DOMContentLoaded", dom_loaded_handler, {
|
|
297
|
+
capture: false,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
// Only IE6-8 don't support `document.addEventListener` and we don't support them
|
|
303
|
+
// so let's simply log an error stating VTilt couldn't be initialized
|
|
304
|
+
// We're checking for `window` to avoid erroring out on a SSR context
|
|
305
|
+
if (typeof window !== "undefined") {
|
|
306
|
+
console.error("Browser doesn't support `document.addEventListener` so VTilt couldn't be initialized");
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* Initialize VTilt as a module (similar to PostHog's init_as_module)
|
|
311
|
+
* Returns an uninitialized VTilt instance that the user must call init() on
|
|
312
|
+
*/
|
|
313
|
+
function init_as_module() {
|
|
314
|
+
const vTiltMain = (instances[PRIMARY_INSTANCE_NAME] = new VTilt());
|
|
315
|
+
add_dom_loaded_handler();
|
|
316
|
+
return vTiltMain;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Initialize VTilt from snippet (similar to PostHog's init_from_snippet)
|
|
320
|
+
* Processes queued calls from the snippet stub and replaces it with real instance
|
|
321
|
+
*
|
|
322
|
+
* The snippet uses some clever tricks to allow deferred loading of array.js (this code)
|
|
323
|
+
*
|
|
324
|
+
* window.vt is an array which the queue of calls made before the lib is loaded
|
|
325
|
+
* It has methods attached to it to simulate the vt object so for instance
|
|
326
|
+
*
|
|
327
|
+
* window.vt.init("projectId", {token: "token", host: "host"})
|
|
328
|
+
* window.vt.trackEvent("my-event", {foo: "bar"})
|
|
329
|
+
*
|
|
330
|
+
* ... will mean that window.vt will look like this:
|
|
331
|
+
* window.vt == [
|
|
332
|
+
* ["trackEvent", "my-event", {foo: "bar"}]
|
|
333
|
+
* ]
|
|
334
|
+
*
|
|
335
|
+
* window.vt._i == [
|
|
336
|
+
* ["projectId", {token: "token", host: "host"}, "vt"]
|
|
337
|
+
* ]
|
|
338
|
+
*
|
|
339
|
+
* If a name is given to the init function then the same as above is true but as a sub-property on the object:
|
|
340
|
+
*
|
|
341
|
+
* window.vt.init("projectId", {token: "token"}, "vt2")
|
|
342
|
+
* window.vt.vt2.trackEvent("my-event", {foo: "bar"})
|
|
343
|
+
*
|
|
344
|
+
* window.vt.vt2 == [
|
|
345
|
+
* ["trackEvent", "my-event", {foo: "bar"}]
|
|
346
|
+
* ]
|
|
347
|
+
*/
|
|
348
|
+
function init_from_snippet() {
|
|
349
|
+
const snippetVT = globals_1.assignableWindow["vt"];
|
|
350
|
+
if (!snippetVT || !isArray(snippetVT)) {
|
|
351
|
+
add_dom_loaded_handler();
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
// Process all init calls from the queue
|
|
355
|
+
const initQueue = snippetVT._i;
|
|
356
|
+
if (isArray(initQueue) && initQueue.length > 0) {
|
|
357
|
+
(0, utils_1.each)(initQueue, function (item) {
|
|
358
|
+
if (!item || !isArray(item)) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const projectId = item[0];
|
|
362
|
+
const config = item[1] || {};
|
|
363
|
+
const name = item[2] || "vt";
|
|
364
|
+
// Build init config with projectId and token
|
|
365
|
+
const initConfig = {
|
|
366
|
+
...config,
|
|
367
|
+
projectId: projectId || config.projectId,
|
|
368
|
+
token: config.token,
|
|
369
|
+
};
|
|
370
|
+
// Warn if required fields are missing (but allow instance creation like PostHog)
|
|
371
|
+
if (!initConfig.projectId || !initConfig.token) {
|
|
372
|
+
console.warn("VTilt: init() called without required projectId or token. " +
|
|
373
|
+
"Tracking will be disabled until these are provided via updateConfig().", {
|
|
374
|
+
projectId: initConfig.projectId || "missing",
|
|
375
|
+
token: initConfig.token ? "present" : "missing",
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
// Create and initialize instance (even if config is incomplete)
|
|
379
|
+
// Validation will happen in tracking methods when events are sent
|
|
380
|
+
const instance = new VTilt(initConfig);
|
|
381
|
+
instance.init();
|
|
382
|
+
// Store instance
|
|
383
|
+
instances[name] = instance;
|
|
384
|
+
// Set as primary instance if it's the default name
|
|
385
|
+
if (name === "vt" || name === PRIMARY_INSTANCE_NAME) {
|
|
386
|
+
instances[PRIMARY_INSTANCE_NAME] = instance;
|
|
387
|
+
}
|
|
388
|
+
// Add named instance as property to primary instance (for PostHog compatibility)
|
|
389
|
+
if (name !== PRIMARY_INSTANCE_NAME && instances[PRIMARY_INSTANCE_NAME]) {
|
|
390
|
+
instances[PRIMARY_INSTANCE_NAME][name] = instance;
|
|
391
|
+
}
|
|
392
|
+
// Get the snippet queue for this instance name
|
|
393
|
+
const instanceSnippet = snippetVT[name] || snippetVT;
|
|
394
|
+
// Execute all queued calls for this instance
|
|
395
|
+
instance._execute_array(instanceSnippet);
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
// Replace stub with main instance (if initialized)
|
|
399
|
+
if (instances[PRIMARY_INSTANCE_NAME] && globals_1.assignableWindow) {
|
|
400
|
+
globals_1.assignableWindow["vt"] = instances[PRIMARY_INSTANCE_NAME];
|
|
401
|
+
}
|
|
402
|
+
add_dom_loaded_handler();
|
|
403
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { VTiltConfig } from "./types";
|
|
2
|
+
import { TrackingManager } from "./tracking";
|
|
3
|
+
export declare class WebVitalsManager {
|
|
4
|
+
private trackingManager;
|
|
5
|
+
private webVitals;
|
|
6
|
+
constructor(config: VTiltConfig, trackingManager: TrackingManager);
|
|
7
|
+
/**
|
|
8
|
+
* Initialize web vitals tracking
|
|
9
|
+
*/
|
|
10
|
+
private initializeWebVitals;
|
|
11
|
+
}
|