@v-tilt/browser 1.0.7 → 1.0.9

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.
Files changed (50) hide show
  1. package/dist/array.js +1 -1
  2. package/dist/array.js.map +1 -1
  3. package/dist/array.no-external.js +1 -1
  4. package/dist/array.no-external.js.map +1 -1
  5. package/dist/constants.d.ts +0 -1
  6. package/dist/extensions/history-autocapture.d.ts +0 -2
  7. package/dist/main.js +1 -1
  8. package/dist/main.js.map +1 -1
  9. package/dist/module.d.ts +52 -132
  10. package/dist/module.js +1 -1
  11. package/dist/module.js.map +1 -1
  12. package/dist/module.no-external.d.ts +52 -132
  13. package/dist/module.no-external.js +1 -1
  14. package/dist/module.no-external.js.map +1 -1
  15. package/dist/session.d.ts +5 -5
  16. package/dist/types.d.ts +1 -0
  17. package/dist/user-manager.d.ts +30 -20
  18. package/dist/utils/event-utils.d.ts +7 -8
  19. package/dist/utils/index.d.ts +0 -5
  20. package/dist/utils/patch.d.ts +0 -2
  21. package/dist/utils/type-utils.d.ts +4 -0
  22. package/dist/vtilt.d.ts +54 -14
  23. package/dist/web-vitals.d.ts +3 -3
  24. package/lib/constants.d.ts +0 -1
  25. package/lib/constants.js +1 -23
  26. package/lib/extensions/history-autocapture.d.ts +0 -2
  27. package/lib/extensions/history-autocapture.js +3 -5
  28. package/lib/session.d.ts +5 -5
  29. package/lib/session.js +8 -8
  30. package/lib/types.d.ts +1 -0
  31. package/lib/user-manager.d.ts +30 -20
  32. package/lib/user-manager.js +103 -92
  33. package/lib/utils/event-utils.d.ts +7 -8
  34. package/lib/utils/event-utils.js +8 -9
  35. package/lib/utils/index.d.ts +0 -5
  36. package/lib/utils/index.js +0 -13
  37. package/lib/utils/patch.d.ts +0 -2
  38. package/lib/utils/patch.js +2 -7
  39. package/lib/utils/type-utils.d.ts +4 -0
  40. package/lib/utils/type-utils.js +9 -0
  41. package/lib/utils/user-agent-utils.js +5 -17
  42. package/lib/vtilt.d.ts +54 -14
  43. package/lib/vtilt.js +328 -45
  44. package/lib/web-vitals.d.ts +3 -3
  45. package/lib/web-vitals.js +3 -3
  46. package/package.json +13 -12
  47. package/LICENSE +0 -21
  48. package/dist/tracking.d.ts +0 -120
  49. package/lib/tracking.d.ts +0 -120
  50. package/lib/tracking.js +0 -338
package/lib/vtilt.js CHANGED
@@ -4,10 +4,13 @@ exports.VTilt = void 0;
4
4
  exports.init_as_module = init_as_module;
5
5
  exports.init_from_snippet = init_from_snippet;
6
6
  const config_1 = require("./config");
7
- const tracking_1 = require("./tracking");
7
+ const session_1 = require("./session");
8
+ const user_manager_1 = require("./user-manager");
8
9
  const web_vitals_1 = require("./web-vitals");
9
10
  const history_autocapture_1 = require("./extensions/history-autocapture");
10
11
  const utils_1 = require("./utils");
12
+ const event_utils_1 = require("./utils/event-utils");
13
+ const utils_2 = require("./utils");
11
14
  const globals_1 = require("./utils/globals");
12
15
  // Helper to check if value is an array
13
16
  const isArray = Array.isArray;
@@ -16,9 +19,18 @@ class VTilt {
16
19
  this.__loaded = false; // Matches snippet's window.vt.__loaded check
17
20
  this._initialPageviewCaptured = false;
18
21
  this._visibilityStateListener = null;
22
+ this.__request_queue = []; // Public for DOM loaded handler
23
+ this._hasWarnedAboutConfig = false; // Track if we've already warned about missing config
19
24
  this.configManager = new config_1.ConfigManager(config);
20
- this.trackingManager = new tracking_1.TrackingManager(this.configManager.getConfig());
21
- this.webVitalsManager = new web_vitals_1.WebVitalsManager(this.configManager.getConfig(), this.trackingManager);
25
+ const fullConfig = this.configManager.getConfig();
26
+ // Auto-detect domain from location if not provided
27
+ let domain = fullConfig.domain;
28
+ if (!domain && globals_1.location) {
29
+ domain = this.getCurrentDomain();
30
+ }
31
+ this.sessionManager = new session_1.SessionManager(fullConfig.storage || "cookie", domain);
32
+ this.userManager = new user_manager_1.UserManager(fullConfig.persistence || "localStorage", domain);
33
+ this.webVitalsManager = new web_vitals_1.WebVitalsManager(fullConfig, this);
22
34
  }
23
35
  /**
24
36
  * Initializes a new instance of the VTilt tracking object.
@@ -68,7 +80,6 @@ class VTilt {
68
80
  /**
69
81
  * Handles the actual initialization logic for a VTilt instance.
70
82
  * This internal method should only be called by `init()`.
71
- * Follows the PostHog convention of using a private `_init()` method for instance setup.
72
83
  */
73
84
  _init(projectId, config = {}, name) {
74
85
  // Guard: prevent re-initialization (matches snippet's __loaded check)
@@ -76,14 +87,14 @@ class VTilt {
76
87
  console.warn("vTilt: You have already initialized vTilt! Re-initializing is a no-op");
77
88
  return this;
78
89
  }
79
- // Update config with projectId, token, and name (PostHog-style)
90
+ // Update config with projectId, token, and name
80
91
  this.updateConfig({
81
92
  ...config,
82
93
  projectId: projectId || config.projectId,
83
94
  name: name,
84
95
  });
85
96
  this.__loaded = true;
86
- // Initialize history autocapture (PostHog-style)
97
+ // Initialize history autocapture
87
98
  this.historyAutocapture = new history_autocapture_1.HistoryAutocapture(this);
88
99
  this.historyAutocapture.startIfEnabled();
89
100
  // Capture initial pageview (with visibility check)
@@ -91,7 +102,7 @@ class VTilt {
91
102
  return this;
92
103
  }
93
104
  /**
94
- * Returns a string representation of the instance name (PostHog-style)
105
+ * Returns a string representation of the instance name
95
106
  * Used for debugging and logging
96
107
  *
97
108
  * @internal
@@ -106,14 +117,191 @@ class VTilt {
106
117
  return name;
107
118
  }
108
119
  /**
109
- * Track a custom event
120
+ * Get current domain from location
121
+ * Returns full URL format for consistency with dashboard
122
+ */
123
+ getCurrentDomain() {
124
+ if (!globals_1.location) {
125
+ return "";
126
+ }
127
+ const protocol = globals_1.location.protocol;
128
+ const hostname = globals_1.location.hostname;
129
+ const port = globals_1.location.port;
130
+ const portSuffix = port ? `:${port}` : "";
131
+ return `${protocol}//${hostname}${portSuffix}`;
132
+ }
133
+ /**
134
+ * Check if tracking is properly configured
135
+ * Returns true if projectId and token are present, false otherwise
136
+ * Logs a warning only once per instance if not configured
137
+ */
138
+ _isConfigured() {
139
+ const config = this.configManager.getConfig();
140
+ if (config.projectId && config.token) {
141
+ return true;
142
+ }
143
+ // Only warn once to avoid console spam
144
+ if (!this._hasWarnedAboutConfig) {
145
+ console.warn("VTilt: projectId and token are required for tracking. " +
146
+ "Events will be skipped until init() or updateConfig() is called with these fields.");
147
+ this._hasWarnedAboutConfig = true;
148
+ }
149
+ return false;
150
+ }
151
+ /**
152
+ * Build the tracking URL with token in query parameters
153
+ */
154
+ buildUrl() {
155
+ const config = this.configManager.getConfig();
156
+ const { proxyUrl, proxy, host, token } = config;
157
+ // Use proxy endpoint to handle Tinybird authentication
158
+ if (proxyUrl) {
159
+ // Use the full proxy URL as provided
160
+ return proxyUrl;
161
+ }
162
+ else if (proxy) {
163
+ // Construct the proxy URL from the proxy domain with token
164
+ return `${proxy}/api/tracking?token=${token}`;
165
+ }
166
+ else if (host) {
167
+ const cleanHost = host.replace(/\/+$/gm, "");
168
+ return `${cleanHost}/api/tracking?token=${token}`;
169
+ }
170
+ else {
171
+ // Use relative path to our tracking proxy endpoint
172
+ return `/api/tracking?token=${token}`;
173
+ }
174
+ }
175
+ /**
176
+ * Send HTTP request
177
+ * This is the central entry point for all tracking requests
178
+ */
179
+ sendRequest(url, event, shouldEnqueue) {
180
+ // Validate configuration (only warns once per instance)
181
+ // This is the single place where validation happens for all sending methods
182
+ if (!this._isConfigured()) {
183
+ return;
184
+ }
185
+ // Check if we should queue requests (for older browsers before DOM is loaded)
186
+ if (shouldEnqueue && typeof globals_1.window !== "undefined") {
187
+ // ENQUEUE_REQUESTS is defined in vtilt.ts as a module-level variable
188
+ const ENQUEUE_REQUESTS = globals_1.window.__VTILT_ENQUEUE_REQUESTS;
189
+ if (ENQUEUE_REQUESTS) {
190
+ this.__request_queue.push({ url, event });
191
+ return;
192
+ }
193
+ }
194
+ const request = new XMLHttpRequest();
195
+ request.open("POST", url, true);
196
+ request.setRequestHeader("Content-Type", "application/json");
197
+ request.send(JSON.stringify(event));
198
+ }
199
+ /**
200
+ * Send a queued request (called after DOM is loaded)
201
+ */
202
+ _send_retriable_request(item) {
203
+ this.sendRequest(item.url, item.event, false);
204
+ }
205
+ /**
206
+ * Capture an event
207
+ * Automatically adds common properties to all events
208
+ * ($current_url, $host, $pathname, $referrer, $referring_domain, $browser_language, etc.)
209
+ * Also adds title property for $pageview events only
210
+ *
211
+ * @param name - Event name
212
+ * @param payload - Event payload
213
+ */
214
+ capture(name, payload) {
215
+ this.sessionManager.setSessionId();
216
+ // Only send events in browser environment (not SSR)
217
+ if (!globals_1.navigator || !globals_1.navigator.userAgent) {
218
+ return;
219
+ }
220
+ if (!(0, utils_1.isValidUserAgent)(globals_1.navigator.userAgent)) {
221
+ return;
222
+ }
223
+ const url = this.buildUrl();
224
+ // Add properties to all events
225
+ // This includes: $current_url, $host, $pathname, $referrer, $referring_domain, $browser_language, etc.
226
+ const eventProperties = (0, event_utils_1.getEventProperties)();
227
+ // Get person properties (includes $device_id and other user properties)
228
+ // These are automatically included in all events
229
+ const personProperties = this.userManager.getUserProperties();
230
+ // Get session and window IDs
231
+ // Both methods ensure IDs always exist (generate if needed)
232
+ const session_id = this.sessionManager.getSessionId();
233
+ const window_id = this.sessionManager.getWindowId();
234
+ // Always include anonymous_id in properties for identity linking
235
+ // This allows linking events with different distinct_ids that share the same anonymous_id
236
+ // This is especially important for handling race conditions when $identify events arrive
237
+ const anonymousId = this.userManager.getAnonymousId();
238
+ const enrichedPayload = {
239
+ ...eventProperties, // Base properties for all events
240
+ ...personProperties, // Person properties (includes $device_id)
241
+ $session_id: session_id, // Session ID in properties
242
+ $window_id: window_id, // Window ID in properties
243
+ // Always include $anon_distinct_id for identity linking (even for identified users)
244
+ // This allows the server to merge identities proactively when events arrive out of order
245
+ ...(anonymousId ? { $anon_distinct_id: anonymousId } : {}),
246
+ ...payload, // User-provided payload (can override base and person properties)
247
+ };
248
+ // Add title only to $pageview events
249
+ if (name === "$pageview" && globals_1.document) {
250
+ enrichedPayload.title = globals_1.document.title;
251
+ }
252
+ const config = this.configManager.getConfig();
253
+ let processedPayload;
254
+ if (config.stringifyPayload !== false) {
255
+ processedPayload = Object.assign({}, enrichedPayload, config.globalAttributes);
256
+ processedPayload = JSON.stringify(processedPayload);
257
+ if (!(0, utils_1.isValidPayload)(processedPayload)) {
258
+ return;
259
+ }
260
+ }
261
+ else {
262
+ processedPayload = Object.assign({}, enrichedPayload, config.globalAttributes);
263
+ const payloadStr = JSON.stringify(processedPayload);
264
+ if (!(0, utils_1.isValidPayload)(payloadStr)) {
265
+ return;
266
+ }
267
+ }
268
+ // Use current distinct_id (or anonymous_id) for event's distinct_id
269
+ // For $identify events, use anonymous_id as the event's distinct_id (identifying FROM anonymous TO new ID)
270
+ // New distinct_id should be in payload properties (e.g., for $identify events)
271
+ let distinct_id;
272
+ if (name === "$identify") {
273
+ // For $identify events, always use anonymous_id as the event's distinct_id
274
+ // The new distinct_id is in the payload
275
+ distinct_id = this.userManager.getAnonymousId();
276
+ }
277
+ else {
278
+ // For other events, use current distinct_id or fall back to anonymous_id
279
+ distinct_id =
280
+ this.userManager.getDistinctId() || this.userManager.getAnonymousId();
281
+ }
282
+ const trackingEvent = {
283
+ timestamp: new Date().toISOString(),
284
+ event: name,
285
+ tenant_id: config.projectId || "",
286
+ domain: config.domain || this.getCurrentDomain(), // Use config domain or current domain
287
+ payload: processedPayload,
288
+ distinct_id: distinct_id,
289
+ // Always include anonymous_id in the event for identity linking
290
+ // This allows the server to merge identities proactively
291
+ anonymous_id: anonymousId,
292
+ };
293
+ this.sendRequest(url, trackingEvent, true);
294
+ }
295
+ /**
296
+ * Track a custom event (alias for capture)
110
297
  */
111
298
  trackEvent(name, payload = {}) {
112
- this.trackingManager.sendEvent(name, payload);
299
+ this.capture(name, payload);
113
300
  }
114
301
  /**
115
- * Identify a user with PostHog-style property operations
116
- * Copied from PostHog's identify method signature
302
+ * Identify a user with property operations
303
+ * Sends $identify event when transitioning from anonymous to identified
304
+ * Event's distinct_id is the previous/anonymous ID, new distinct_id is in payload
117
305
  *
118
306
  * @example
119
307
  * ```js
@@ -130,11 +318,76 @@ class VTilt {
130
318
  * vTilt.identify('user_123', { name: 'John Doe', email: 'john@example.com' })
131
319
  * ```
132
320
  */
133
- identify(distinctId, userPropertiesToSet, userPropertiesToSetOnce) {
134
- this.trackingManager.identify(distinctId, userPropertiesToSet, userPropertiesToSetOnce);
321
+ identify(newDistinctId, userPropertiesToSet, userPropertiesToSetOnce) {
322
+ // Validation: Convert number to string
323
+ if (typeof newDistinctId === "number") {
324
+ newDistinctId = String(newDistinctId);
325
+ console.warn("The first argument to vTilt.identify was a number, but it should be a string. It has been converted to a string.");
326
+ }
327
+ // Validation: Check if distinct_id is provided
328
+ if (!newDistinctId) {
329
+ console.error("Unique user id has not been set in vTilt.identify");
330
+ return;
331
+ }
332
+ // Validation: Check for hardcoded strings
333
+ if (this.userManager.isDistinctIdStringLikePublic(newDistinctId)) {
334
+ console.error(`The string "${newDistinctId}" was set in vTilt.identify which indicates an error. This ID should be unique to the user and not a hardcoded string.`);
335
+ return;
336
+ }
337
+ // Validation: Check for cookieless sentinel value
338
+ if (newDistinctId === "COOKIELESS_SENTINEL_VALUE") {
339
+ console.error(`The string "${newDistinctId}" was set in vTilt.identify which indicates an error. This ID is only used as a sentinel value.`);
340
+ return;
341
+ }
342
+ const previousDistinctId = this.userManager.getDistinctId();
343
+ const anonymousId = this.userManager.getAnonymousId();
344
+ const deviceId = this.userManager.getDeviceId();
345
+ const isKnownAnonymous = this.userManager.getUserState() === "anonymous";
346
+ // Handle device ID if not already set
347
+ if (!deviceId) {
348
+ const device_id = previousDistinctId || anonymousId;
349
+ this.userManager.ensureDeviceId(device_id);
350
+ }
351
+ // Send $identify event when distinct_id is changing AND user was anonymous
352
+ // Event's distinct_id is the previous/anonymous ID, new distinct_id goes in payload
353
+ if (newDistinctId !== previousDistinctId && isKnownAnonymous) {
354
+ // Update user state and properties BEFORE sending event
355
+ // (But don't update distinct_id yet - sendEvent needs to use previous ID)
356
+ this.userManager.setUserState("identified");
357
+ this.userManager.updateUserProperties(userPropertiesToSet, userPropertiesToSetOnce);
358
+ // Send $identify event with previous/anonymous ID as event's distinct_id
359
+ // New distinct_id and properties go in payload
360
+ this.capture("$identify", {
361
+ distinct_id: newDistinctId, // New distinct_id in payload
362
+ $anon_distinct_id: previousDistinctId || anonymousId, // Previous ID in payload
363
+ $set: userPropertiesToSet || {},
364
+ $set_once: userPropertiesToSetOnce || {},
365
+ });
366
+ // Now update distinct_id after sending the event
367
+ this.userManager.setDistinctId(newDistinctId);
368
+ }
369
+ else if (userPropertiesToSet || userPropertiesToSetOnce) {
370
+ // If distinct_id is not changing but we have properties to set
371
+ // Update user state if not already identified
372
+ if (isKnownAnonymous) {
373
+ this.userManager.setUserState("identified");
374
+ }
375
+ // Update properties
376
+ this.userManager.updateUserProperties(userPropertiesToSet, userPropertiesToSetOnce);
377
+ // Send $set event to notify server of property updates
378
+ this.capture("$set", {
379
+ $set: userPropertiesToSet || {},
380
+ $set_once: userPropertiesToSetOnce || {},
381
+ });
382
+ }
383
+ else if (newDistinctId !== previousDistinctId) {
384
+ // If distinct_id is changing but user was already identified, just update the distinct_id
385
+ this.userManager.setUserState("identified");
386
+ this.userManager.setDistinctId(newDistinctId);
387
+ }
135
388
  }
136
389
  /**
137
- * Set user properties with PostHog-style operations
390
+ * Set user properties
138
391
  * Sets properties on the person profile associated with the current distinct_id
139
392
  *
140
393
  * @example
@@ -156,11 +409,20 @@ class VTilt {
156
409
  * @param userPropertiesToSetOnce Optional: Properties to set once (preserves first value)
157
410
  */
158
411
  setUserProperties(userPropertiesToSet, userPropertiesToSetOnce) {
159
- this.trackingManager.setUserProperties(userPropertiesToSet, userPropertiesToSetOnce);
412
+ // Update user properties in UserManager
413
+ // Returns true if properties were updated (not a duplicate), false otherwise
414
+ const shouldSendEvent = this.userManager.setUserProperties(userPropertiesToSet, userPropertiesToSetOnce);
415
+ // Only send $set event if properties were actually updated (not a duplicate)
416
+ if (shouldSendEvent) {
417
+ this.capture("$set", {
418
+ $set: userPropertiesToSet || {},
419
+ $set_once: userPropertiesToSetOnce || {},
420
+ });
421
+ }
160
422
  }
161
423
  /**
162
424
  * Reset user identity (logout)
163
- * PostHog behavior: Clears all user data, generates new anonymous ID
425
+ * Clears all user data, generates new anonymous ID, resets session
164
426
  *
165
427
  * @param reset_device_id - If true, also resets device_id. Default: false
166
428
  *
@@ -173,29 +435,31 @@ class VTilt {
173
435
  * vtilt.resetUser(true)
174
436
  */
175
437
  resetUser(reset_device_id) {
176
- this.trackingManager.resetUser(reset_device_id);
438
+ // Reset session ID
439
+ this.sessionManager.resetSessionId();
440
+ this.userManager.reset(reset_device_id);
177
441
  }
178
442
  /**
179
443
  * Get current user identity
180
444
  */
181
445
  getUserIdentity() {
182
- return this.trackingManager.getUserIdentity();
446
+ return this.userManager.getUserIdentity();
183
447
  }
184
448
  /**
185
449
  * Get current device ID
186
450
  */
187
451
  getDeviceId() {
188
- return this.trackingManager.getDeviceId();
452
+ return this.userManager.getDeviceId();
189
453
  }
190
454
  /**
191
455
  * Get current user state
192
456
  */
193
457
  getUserState() {
194
- return this.trackingManager.getUserState();
458
+ return this.userManager.getUserState();
195
459
  }
196
460
  /**
197
461
  * Create an alias to link two distinct IDs
198
- * PostHog behavior: Links anonymous session to account on signup
462
+ * Links anonymous session to account on signup
199
463
  *
200
464
  * @param alias - A unique identifier that you want to use for this user in the future
201
465
  * @param original - The current identifier being used for this user (optional, defaults to current distinct_id)
@@ -209,11 +473,27 @@ class VTilt {
209
473
  * vtilt.createAlias('user_12345', 'anonymous_abc123')
210
474
  */
211
475
  createAlias(alias, original) {
212
- this.trackingManager.createAlias(alias, original);
476
+ // Get alias information from UserManager
477
+ const aliasInfo = this.userManager.createAlias(alias, original);
478
+ // If alias was created, send $alias event
479
+ if (aliasInfo) {
480
+ this.capture("$alias", {
481
+ $original_id: aliasInfo.original,
482
+ $alias_id: aliasInfo.distinct_id,
483
+ });
484
+ }
485
+ else {
486
+ // If alias matches original, use identify instead
487
+ const distinctId = original ||
488
+ this.userManager.getDistinctId() ||
489
+ this.userManager.getAnonymousId();
490
+ if (alias === distinctId) {
491
+ this.identify(alias);
492
+ }
493
+ }
213
494
  }
214
495
  /**
215
496
  * Capture initial pageview with visibility check
216
- * Based on PostHog's _captureInitialPageview implementation
217
497
  */
218
498
  _captureInitialPageview() {
219
499
  if (!globals_1.document) {
@@ -228,25 +508,25 @@ class VTilt {
228
508
  this._visibilityStateListener = () => {
229
509
  this._captureInitialPageview();
230
510
  };
231
- (0, utils_1.addEventListener)(globals_1.document, "visibilitychange", this._visibilityStateListener);
511
+ (0, utils_2.addEventListener)(globals_1.document, "visibilitychange", this._visibilityStateListener);
232
512
  }
233
513
  return;
234
514
  }
235
515
  // Extra check here to guarantee we only ever trigger a single initial pageview event
236
516
  if (!this._initialPageviewCaptured) {
237
517
  this._initialPageviewCaptured = true;
238
- // Wait a bit for SPA routers (PostHog-style delay)
518
+ // Wait a bit for SPA routers
239
519
  setTimeout(() => {
240
520
  // Double-check we're still in browser environment (defensive check)
241
521
  if (!globals_1.document || !globals_1.location) {
242
522
  return;
243
523
  }
244
524
  // Note: $current_url, $host, $pathname, $referrer, $referring_domain, title
245
- // are automatically added by sendEvent() for all events (title only for $pageview)
525
+ // are automatically added by capture() for all events (title only for $pageview)
246
526
  const payload = {
247
527
  navigation_type: "initial_load",
248
528
  };
249
- this.trackingManager.sendEvent("$pageview", payload);
529
+ this.capture("$pageview", payload);
250
530
  }, 300);
251
531
  // After we've captured the initial pageview, we can remove the listener
252
532
  if (this._visibilityStateListener) {
@@ -265,16 +545,22 @@ class VTilt {
265
545
  * Get current session ID
266
546
  */
267
547
  getSessionId() {
268
- return this.trackingManager.getSessionId();
548
+ return this.sessionManager.getSessionId();
269
549
  }
270
550
  /**
271
551
  * Update configuration
272
552
  */
273
553
  updateConfig(config) {
274
554
  this.configManager.updateConfig(config);
555
+ const fullConfig = this.configManager.getConfig();
275
556
  // Recreate managers with new config
276
- this.trackingManager = new tracking_1.TrackingManager(this.configManager.getConfig());
277
- this.webVitalsManager = new web_vitals_1.WebVitalsManager(this.configManager.getConfig(), this.trackingManager);
557
+ let domain = fullConfig.domain;
558
+ if (!domain && globals_1.location) {
559
+ domain = this.getCurrentDomain();
560
+ }
561
+ this.sessionManager = new session_1.SessionManager(fullConfig.storage || "cookie", domain);
562
+ this.userManager = new user_manager_1.UserManager(fullConfig.persistence || "localStorage", domain);
563
+ this.webVitalsManager = new web_vitals_1.WebVitalsManager(fullConfig, this);
278
564
  }
279
565
  /**
280
566
  * _execute_array() deals with processing any vTilt function
@@ -310,14 +596,12 @@ class VTilt {
310
596
  * Called when DOM is loaded - processes queued requests
311
597
  */
312
598
  _dom_loaded() {
313
- if (this.trackingManager) {
314
- // Process all queued requests
315
- this.trackingManager.__request_queue.forEach((item) => {
316
- this.trackingManager._send_retriable_request(item);
317
- });
318
- // Clear the queue
319
- this.trackingManager.__request_queue = [];
320
- }
599
+ // Process all queued requests
600
+ this.__request_queue.forEach((item) => {
601
+ this._send_retriable_request(item);
602
+ });
603
+ // Clear the queue
604
+ this.__request_queue = [];
321
605
  }
322
606
  }
323
607
  exports.VTilt = VTilt;
@@ -331,13 +615,12 @@ const SUPPORTS_REQUEST = typeof globals_1.XMLHttpRequest !== "undefined" || type
331
615
  let ENQUEUE_REQUESTS = !SUPPORTS_REQUEST &&
332
616
  (globals_1.userAgent === null || globals_1.userAgent === void 0 ? void 0 : globals_1.userAgent.indexOf("MSIE")) === -1 &&
333
617
  (globals_1.userAgent === null || globals_1.userAgent === void 0 ? void 0 : globals_1.userAgent.indexOf("Mozilla")) === -1;
334
- // Expose ENQUEUE_REQUESTS to window for TrackingManager to access
618
+ // Expose ENQUEUE_REQUESTS to window for request queuing
335
619
  if (globals_1.window) {
336
620
  globals_1.window.__VTILT_ENQUEUE_REQUESTS = ENQUEUE_REQUESTS;
337
621
  }
338
622
  /**
339
623
  * Add DOM loaded handler to process queued requests
340
- * Similar to PostHog's add_dom_loaded_handler
341
624
  */
342
625
  const add_dom_loaded_handler = function () {
343
626
  // Cross browser DOM Loaded support
@@ -353,7 +636,7 @@ const add_dom_loaded_handler = function () {
353
636
  globals_1.window.__VTILT_ENQUEUE_REQUESTS = false;
354
637
  }
355
638
  // Process queued requests for all instances
356
- (0, utils_1.each)(instances, function (inst) {
639
+ (0, utils_2.each)(instances, function (inst) {
357
640
  inst._dom_loaded();
358
641
  });
359
642
  }
@@ -366,7 +649,7 @@ const add_dom_loaded_handler = function () {
366
649
  dom_loaded_handler();
367
650
  }
368
651
  else {
369
- (0, utils_1.addEventListener)(globals_1.document, "DOMContentLoaded", dom_loaded_handler, {
652
+ (0, utils_2.addEventListener)(globals_1.document, "DOMContentLoaded", dom_loaded_handler, {
370
653
  capture: false,
371
654
  });
372
655
  }
@@ -380,7 +663,7 @@ const add_dom_loaded_handler = function () {
380
663
  }
381
664
  };
382
665
  /**
383
- * Initialize vTilt as a module (similar to PostHog's init_as_module)
666
+ * Initialize vTilt as a module
384
667
  * Returns an uninitialized vTilt instance that the user must call init() on
385
668
  */
386
669
  function init_as_module() {
@@ -389,7 +672,7 @@ function init_as_module() {
389
672
  return vTiltMain;
390
673
  }
391
674
  /**
392
- * Initialize vTilt from snippet (similar to PostHog's init_from_snippet)
675
+ * Initialize vTilt from snippet
393
676
  * Processes queued calls from the snippet stub and replaces it with real instance
394
677
  *
395
678
  * The snippet uses some clever tricks to allow deferred loading of array.js (this code)
@@ -451,7 +734,7 @@ function init_from_snippet() {
451
734
  *
452
735
  */
453
736
  // Call all pre-loaded init calls properly
454
- (0, utils_1.each)(snippetVT["_i"], function (item) {
737
+ (0, utils_2.each)(snippetVT["_i"], function (item) {
455
738
  if (item && isArray(item)) {
456
739
  const instance = vTiltMain.init(item[0], item[1], item[2]);
457
740
  const instanceSnippet = snippetVT[item[2] || "vt"] || snippetVT;
@@ -1,9 +1,9 @@
1
1
  import { VTiltConfig } from "./types";
2
- import { TrackingManager } from "./tracking";
2
+ import { VTilt } from "./vtilt";
3
3
  export declare class WebVitalsManager {
4
- private trackingManager;
4
+ private instance;
5
5
  private webVitals;
6
- constructor(config: VTiltConfig, trackingManager: TrackingManager);
6
+ constructor(config: VTiltConfig, instance: VTilt);
7
7
  /**
8
8
  * Initialize web vitals tracking
9
9
  */
package/lib/web-vitals.js CHANGED
@@ -4,8 +4,8 @@ exports.WebVitalsManager = void 0;
4
4
  const geolocation_1 = require("./geolocation");
5
5
  const globals_1 = require("./utils/globals");
6
6
  class WebVitalsManager {
7
- constructor(config, trackingManager) {
8
- this.trackingManager = trackingManager;
7
+ constructor(config, instance) {
8
+ this.instance = instance;
9
9
  // Load web-vitals if enabled and in browser environment (not SSR)
10
10
  if (config.webVitals && globals_1.window) {
11
11
  try {
@@ -33,7 +33,7 @@ class WebVitalsManager {
33
33
  return;
34
34
  }
35
35
  const { country, locale } = (0, geolocation_1.getCountryAndLocale)();
36
- this.trackingManager.sendEvent("web_vital", {
36
+ this.instance.capture("web_vital", {
37
37
  name: metric.name,
38
38
  value: metric.value,
39
39
  delta: metric.delta,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@v-tilt/browser",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "vTilt browser tracking library",
5
5
  "main": "dist/main.js",
6
6
  "module": "dist/module.js",
@@ -12,6 +12,15 @@
12
12
  "publishConfig": {
13
13
  "access": "public"
14
14
  },
15
+ "scripts": {
16
+ "build": "tsc -b && rollup -c",
17
+ "dev": "rollup -c -w",
18
+ "type-check": "tsc --noEmit",
19
+ "lint": "eslint src --ext .ts",
20
+ "lint:fix": "eslint src --ext .ts --fix",
21
+ "clean": "rimraf lib dist",
22
+ "prepublishOnly": "pnpm run build"
23
+ },
15
24
  "keywords": [
16
25
  "analytics",
17
26
  "tracking",
@@ -29,14 +38,14 @@
29
38
  "@rollup/plugin-terser": "^0.4.4",
30
39
  "@rollup/plugin-typescript": "^11.1.6",
31
40
  "@types/node": "^20.10.5",
41
+ "@v-tilt/eslint-config": "workspace:*",
32
42
  "eslint": "^9.0.0",
33
43
  "rimraf": "^5.0.5",
34
44
  "rollup": "^4.9.1",
35
45
  "rollup-plugin-dts": "^6.2.3",
36
46
  "rollup-plugin-terser": "^7.0.2",
37
47
  "rollup-plugin-visualizer": "^6.0.3",
38
- "typescript": "^5.3.3",
39
- "@v-tilt/eslint-config": "1.0.0"
48
+ "typescript": "^5.3.3"
40
49
  },
41
50
  "dependencies": {
42
51
  "web-vitals": "^3.5.0"
@@ -48,13 +57,5 @@
48
57
  "web-vitals": {
49
58
  "optional": true
50
59
  }
51
- },
52
- "scripts": {
53
- "build": "tsc -b && rollup -c",
54
- "dev": "rollup -c -w",
55
- "type-check": "tsc --noEmit",
56
- "lint": "eslint src --ext .ts",
57
- "lint:fix": "eslint src --ext .ts --fix",
58
- "clean": "rimraf lib dist"
59
60
  }
60
- }
61
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2022 Tinybird.co
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.