@tracelog/lib 0.3.0 → 0.4.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/cjs/api.d.ts CHANGED
@@ -28,14 +28,14 @@ export declare const event: (name: string, metadata?: Record<string, MetadataTyp
28
28
  * @param event - Event name to listen to
29
29
  * @param callback - Function to call when event is emitted
30
30
  * @example
31
- * // Listen for real-time events
32
- * tracelog.on('realtime', (data) => {
33
- * console.log('Event tracked:', data.type, data.data);
31
+ * // Listen for tracked events
32
+ * tracelog.on('event', (data) => {
33
+ * console.log('Event tracked:', data.type);
34
34
  * });
35
35
  *
36
- * // Listen for sent events
37
- * tracelog.on('sent', (data) => {
38
- * console.log('Events sent:', data.eventCount);
36
+ * // Listen for event queues being sent
37
+ * tracelog.on('queue', (data) => {
38
+ * console.log('Events sent:', data.events.length);
39
39
  * });
40
40
  */
41
41
  export declare const on: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
@@ -45,7 +45,7 @@ export declare const on: <K extends keyof EmitterMap>(event: K, callback: Emitte
45
45
  * @param callback - The same function reference that was used in on()
46
46
  * @example
47
47
  * // Remove a specific listener
48
- * tracelog.off('realtime', myCallback);
48
+ * tracelog.off('event', myCallback);
49
49
  */
50
50
  export declare const off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
51
51
  /**
package/dist/cjs/api.js CHANGED
@@ -96,14 +96,14 @@ exports.event = event;
96
96
  * @param event - Event name to listen to
97
97
  * @param callback - Function to call when event is emitted
98
98
  * @example
99
- * // Listen for real-time events
100
- * tracelog.on('realtime', (data) => {
101
- * console.log('Event tracked:', data.type, data.data);
99
+ * // Listen for tracked events
100
+ * tracelog.on('event', (data) => {
101
+ * console.log('Event tracked:', data.type);
102
102
  * });
103
103
  *
104
- * // Listen for sent events
105
- * tracelog.on('sent', (data) => {
106
- * console.log('Events sent:', data.eventCount);
104
+ * // Listen for event queues being sent
105
+ * tracelog.on('queue', (data) => {
106
+ * console.log('Events sent:', data.events.length);
107
107
  * });
108
108
  */
109
109
  const on = (event, callback) => {
@@ -119,7 +119,7 @@ exports.on = on;
119
119
  * @param callback - The same function reference that was used in on()
120
120
  * @example
121
121
  * // Remove a specific listener
122
- * tracelog.off('realtime', myCallback);
122
+ * tracelog.off('event', myCallback);
123
123
  */
124
124
  const off = (event, callback) => {
125
125
  if (!app) {
@@ -1,2 +1,2 @@
1
1
  export { Mode, EventType, DeviceType, ScrollDirection, ErrorType, TagConditionOperator, TagLogicalOperator, TagConditionType, } from './types';
2
- export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
2
+ export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventLocation, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
@@ -10,6 +10,7 @@ export declare class ScrollHandler extends StateManager {
10
10
  constructor(eventManager: EventManager);
11
11
  startTracking(): void;
12
12
  stopTracking(): void;
13
+ private trySetupContainers;
13
14
  private setupScrollContainer;
14
15
  private processScrollEvent;
15
16
  private shouldEmitScrollEvent;
@@ -21,14 +21,11 @@ class ScrollHandler extends state_manager_1.StateManager {
21
21
  this.set('scrollEventCount', 0);
22
22
  const raw = this.get('config').scrollContainerSelectors;
23
23
  const selectors = Array.isArray(raw) ? raw : typeof raw === 'string' ? [raw] : [];
24
- const elements = selectors
25
- .map((sel) => this.safeQuerySelector(sel))
26
- .filter((element) => element instanceof HTMLElement);
27
- if (elements.length === 0) {
28
- elements.push(window);
24
+ if (selectors.length === 0) {
25
+ this.setupScrollContainer(window);
29
26
  }
30
- for (const element of elements) {
31
- this.setupScrollContainer(element);
27
+ else {
28
+ this.trySetupContainers(selectors, 0);
32
29
  }
33
30
  }
34
31
  stopTracking() {
@@ -45,6 +42,27 @@ class ScrollHandler extends state_manager_1.StateManager {
45
42
  this.set('scrollEventCount', 0);
46
43
  this.limitWarningLogged = false;
47
44
  }
45
+ trySetupContainers(selectors, attempt) {
46
+ const elements = selectors
47
+ .map((sel) => this.safeQuerySelector(sel))
48
+ .filter((element) => element instanceof HTMLElement);
49
+ if (elements.length > 0) {
50
+ for (const element of elements) {
51
+ const isAlreadyTracking = this.containers.some((c) => c.element === element);
52
+ if (!isAlreadyTracking) {
53
+ this.setupScrollContainer(element);
54
+ }
55
+ }
56
+ return;
57
+ }
58
+ if (attempt < 5) {
59
+ setTimeout(() => this.trySetupContainers(selectors, attempt + 1), 200);
60
+ return;
61
+ }
62
+ if (this.containers.length === 0) {
63
+ this.setupScrollContainer(window);
64
+ }
65
+ }
48
66
  setupScrollContainer(element) {
49
67
  // Skip setup for non-scrollable elements
50
68
  if (element !== window && !this.isElementScrollable(element)) {
@@ -30,7 +30,7 @@ export declare class EventManager extends StateManager {
30
30
  /**
31
31
  * Track user events with automatic deduplication and queueing
32
32
  */
33
- track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, session_end_reason, session_start_recovered, }: Partial<EventData>): void;
33
+ track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, session_end_reason, }: Partial<EventData>): void;
34
34
  stop(): void;
35
35
  /**
36
36
  * Flush all queued events immediately (async)
@@ -47,7 +47,7 @@ class EventManager extends state_manager_1.StateManager {
47
47
  /**
48
48
  * Track user events with automatic deduplication and queueing
49
49
  */
50
- track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, session_end_reason, session_start_recovered, }) {
50
+ track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, session_end_reason, }) {
51
51
  if (!type) {
52
52
  utils_1.debugLog.warn('EventManager', 'Event type is required');
53
53
  return;
@@ -68,7 +68,6 @@ class EventManager extends state_manager_1.StateManager {
68
68
  web_vitals,
69
69
  error_data,
70
70
  session_end_reason,
71
- session_start_recovered,
72
71
  });
73
72
  // Check URL exclusions
74
73
  if (this.isEventExcluded(payload)) {
@@ -235,7 +234,6 @@ class EventManager extends state_manager_1.StateManager {
235
234
  ...(data.web_vitals && { web_vitals: data.web_vitals }),
236
235
  ...(data.error_data && { error_data: data.error_data }),
237
236
  ...(data.session_end_reason && { session_end_reason: data.session_end_reason }),
238
- ...(data.session_start_recovered && { session_start_recovered: data.session_start_recovered }),
239
237
  ...(isSessionStart && (0, utils_1.getUTMParameters)() && { utm: (0, utils_1.getUTMParameters)() }),
240
238
  };
241
239
  // Add project tags
@@ -153,11 +153,12 @@ class SessionManager extends state_manager_1.StateManager {
153
153
  try {
154
154
  this.set('sessionId', sessionId);
155
155
  this.persistSession(sessionId);
156
- // Track session start event
157
- this.eventManager.track({
158
- type: types_1.EventType.SESSION_START,
159
- ...(isRecovered && { session_start_recovered: true }),
160
- });
156
+ // Track session start event only for new sessions
157
+ if (!isRecovered) {
158
+ this.eventManager.track({
159
+ type: types_1.EventType.SESSION_START,
160
+ });
161
+ }
161
162
  // Initialize components
162
163
  this.initCrossTabSync();
163
164
  this.shareSession(sessionId);
@@ -250,7 +251,7 @@ class SessionManager extends state_manager_1.StateManager {
250
251
  }
251
252
  };
252
253
  this.beforeUnloadHandler = () => {
253
- this.eventManager.flushImmediatelySync();
254
+ this.endSession('page_unload');
254
255
  };
255
256
  // Handle tab visibility changes
256
257
  document.addEventListener('visibilitychange', this.visibilityChangeHandler);
@@ -75,6 +75,10 @@ export interface PageViewData {
75
75
  search?: string;
76
76
  hash?: string;
77
77
  }
78
+ export interface EventLocation {
79
+ country: string;
80
+ country_code: string;
81
+ }
78
82
  export interface VitalSample {
79
83
  type: WebVitalType;
80
84
  value: number;
@@ -90,10 +94,10 @@ export interface EventData {
90
94
  custom_event?: CustomEventData;
91
95
  web_vitals?: WebVitalsData;
92
96
  page_view?: PageViewData;
93
- session_start_recovered?: boolean;
94
97
  session_end_reason?: SessionEndReason;
95
98
  error_data?: ErrorData;
96
99
  utm?: UTM;
100
+ location?: EventLocation;
97
101
  tags?: string[] | {
98
102
  id: string;
99
103
  key: string;
package/dist/esm/api.d.ts CHANGED
@@ -28,14 +28,14 @@ export declare const event: (name: string, metadata?: Record<string, MetadataTyp
28
28
  * @param event - Event name to listen to
29
29
  * @param callback - Function to call when event is emitted
30
30
  * @example
31
- * // Listen for real-time events
32
- * tracelog.on('realtime', (data) => {
33
- * console.log('Event tracked:', data.type, data.data);
31
+ * // Listen for tracked events
32
+ * tracelog.on('event', (data) => {
33
+ * console.log('Event tracked:', data.type);
34
34
  * });
35
35
  *
36
- * // Listen for sent events
37
- * tracelog.on('sent', (data) => {
38
- * console.log('Events sent:', data.eventCount);
36
+ * // Listen for event queues being sent
37
+ * tracelog.on('queue', (data) => {
38
+ * console.log('Events sent:', data.events.length);
39
39
  * });
40
40
  */
41
41
  export declare const on: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
@@ -45,7 +45,7 @@ export declare const on: <K extends keyof EmitterMap>(event: K, callback: Emitte
45
45
  * @param callback - The same function reference that was used in on()
46
46
  * @example
47
47
  * // Remove a specific listener
48
- * tracelog.off('realtime', myCallback);
48
+ * tracelog.off('event', myCallback);
49
49
  */
50
50
  export declare const off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
51
51
  /**
package/dist/esm/api.js CHANGED
@@ -91,14 +91,14 @@ export const event = (name, metadata) => {
91
91
  * @param event - Event name to listen to
92
92
  * @param callback - Function to call when event is emitted
93
93
  * @example
94
- * // Listen for real-time events
95
- * tracelog.on('realtime', (data) => {
96
- * console.log('Event tracked:', data.type, data.data);
94
+ * // Listen for tracked events
95
+ * tracelog.on('event', (data) => {
96
+ * console.log('Event tracked:', data.type);
97
97
  * });
98
98
  *
99
- * // Listen for sent events
100
- * tracelog.on('sent', (data) => {
101
- * console.log('Events sent:', data.eventCount);
99
+ * // Listen for event queues being sent
100
+ * tracelog.on('queue', (data) => {
101
+ * console.log('Events sent:', data.events.length);
102
102
  * });
103
103
  */
104
104
  export const on = (event, callback) => {
@@ -113,7 +113,7 @@ export const on = (event, callback) => {
113
113
  * @param callback - The same function reference that was used in on()
114
114
  * @example
115
115
  * // Remove a specific listener
116
- * tracelog.off('realtime', myCallback);
116
+ * tracelog.off('event', myCallback);
117
117
  */
118
118
  export const off = (event, callback) => {
119
119
  if (!app) {
@@ -1,2 +1,2 @@
1
1
  export { Mode, EventType, DeviceType, ScrollDirection, ErrorType, TagConditionOperator, TagLogicalOperator, TagConditionType, } from './types';
2
- export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
2
+ export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventLocation, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
@@ -10,6 +10,7 @@ export declare class ScrollHandler extends StateManager {
10
10
  constructor(eventManager: EventManager);
11
11
  startTracking(): void;
12
12
  stopTracking(): void;
13
+ private trySetupContainers;
13
14
  private setupScrollContainer;
14
15
  private processScrollEvent;
15
16
  private shouldEmitScrollEvent;
@@ -18,14 +18,11 @@ export class ScrollHandler extends StateManager {
18
18
  this.set('scrollEventCount', 0);
19
19
  const raw = this.get('config').scrollContainerSelectors;
20
20
  const selectors = Array.isArray(raw) ? raw : typeof raw === 'string' ? [raw] : [];
21
- const elements = selectors
22
- .map((sel) => this.safeQuerySelector(sel))
23
- .filter((element) => element instanceof HTMLElement);
24
- if (elements.length === 0) {
25
- elements.push(window);
21
+ if (selectors.length === 0) {
22
+ this.setupScrollContainer(window);
26
23
  }
27
- for (const element of elements) {
28
- this.setupScrollContainer(element);
24
+ else {
25
+ this.trySetupContainers(selectors, 0);
29
26
  }
30
27
  }
31
28
  stopTracking() {
@@ -42,6 +39,27 @@ export class ScrollHandler extends StateManager {
42
39
  this.set('scrollEventCount', 0);
43
40
  this.limitWarningLogged = false;
44
41
  }
42
+ trySetupContainers(selectors, attempt) {
43
+ const elements = selectors
44
+ .map((sel) => this.safeQuerySelector(sel))
45
+ .filter((element) => element instanceof HTMLElement);
46
+ if (elements.length > 0) {
47
+ for (const element of elements) {
48
+ const isAlreadyTracking = this.containers.some((c) => c.element === element);
49
+ if (!isAlreadyTracking) {
50
+ this.setupScrollContainer(element);
51
+ }
52
+ }
53
+ return;
54
+ }
55
+ if (attempt < 5) {
56
+ setTimeout(() => this.trySetupContainers(selectors, attempt + 1), 200);
57
+ return;
58
+ }
59
+ if (this.containers.length === 0) {
60
+ this.setupScrollContainer(window);
61
+ }
62
+ }
45
63
  setupScrollContainer(element) {
46
64
  // Skip setup for non-scrollable elements
47
65
  if (element !== window && !this.isElementScrollable(element)) {
@@ -30,7 +30,7 @@ export declare class EventManager extends StateManager {
30
30
  /**
31
31
  * Track user events with automatic deduplication and queueing
32
32
  */
33
- track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, session_end_reason, session_start_recovered, }: Partial<EventData>): void;
33
+ track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, session_end_reason, }: Partial<EventData>): void;
34
34
  stop(): void;
35
35
  /**
36
36
  * Flush all queued events immediately (async)
@@ -44,7 +44,7 @@ export class EventManager extends StateManager {
44
44
  /**
45
45
  * Track user events with automatic deduplication and queueing
46
46
  */
47
- track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, session_end_reason, session_start_recovered, }) {
47
+ track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, session_end_reason, }) {
48
48
  if (!type) {
49
49
  debugLog.warn('EventManager', 'Event type is required');
50
50
  return;
@@ -65,7 +65,6 @@ export class EventManager extends StateManager {
65
65
  web_vitals,
66
66
  error_data,
67
67
  session_end_reason,
68
- session_start_recovered,
69
68
  });
70
69
  // Check URL exclusions
71
70
  if (this.isEventExcluded(payload)) {
@@ -232,7 +231,6 @@ export class EventManager extends StateManager {
232
231
  ...(data.web_vitals && { web_vitals: data.web_vitals }),
233
232
  ...(data.error_data && { error_data: data.error_data }),
234
233
  ...(data.session_end_reason && { session_end_reason: data.session_end_reason }),
235
- ...(data.session_start_recovered && { session_start_recovered: data.session_start_recovered }),
236
234
  ...(isSessionStart && getUTMParameters() && { utm: getUTMParameters() }),
237
235
  };
238
236
  // Add project tags
@@ -150,11 +150,12 @@ export class SessionManager extends StateManager {
150
150
  try {
151
151
  this.set('sessionId', sessionId);
152
152
  this.persistSession(sessionId);
153
- // Track session start event
154
- this.eventManager.track({
155
- type: EventType.SESSION_START,
156
- ...(isRecovered && { session_start_recovered: true }),
157
- });
153
+ // Track session start event only for new sessions
154
+ if (!isRecovered) {
155
+ this.eventManager.track({
156
+ type: EventType.SESSION_START,
157
+ });
158
+ }
158
159
  // Initialize components
159
160
  this.initCrossTabSync();
160
161
  this.shareSession(sessionId);
@@ -247,7 +248,7 @@ export class SessionManager extends StateManager {
247
248
  }
248
249
  };
249
250
  this.beforeUnloadHandler = () => {
250
- this.eventManager.flushImmediatelySync();
251
+ this.endSession('page_unload');
251
252
  };
252
253
  // Handle tab visibility changes
253
254
  document.addEventListener('visibilitychange', this.visibilityChangeHandler);
@@ -75,6 +75,10 @@ export interface PageViewData {
75
75
  search?: string;
76
76
  hash?: string;
77
77
  }
78
+ export interface EventLocation {
79
+ country: string;
80
+ country_code: string;
81
+ }
78
82
  export interface VitalSample {
79
83
  type: WebVitalType;
80
84
  value: number;
@@ -90,10 +94,10 @@ export interface EventData {
90
94
  custom_event?: CustomEventData;
91
95
  web_vitals?: WebVitalsData;
92
96
  page_view?: PageViewData;
93
- session_start_recovered?: boolean;
94
97
  session_end_reason?: SessionEndReason;
95
98
  error_data?: ErrorData;
96
99
  utm?: UTM;
100
+ location?: EventLocation;
97
101
  tags?: string[] | {
98
102
  id: string;
99
103
  key: string;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@tracelog/lib",
3
3
  "description": "JavaScript library for web analytics and real-time event tracking",
4
4
  "license": "MIT",
5
- "version": "0.3.0",
5
+ "version": "0.4.1",
6
6
  "main": "./dist/cjs/public-api.js",
7
7
  "module": "./dist/esm/public-api.js",
8
8
  "types": "./dist/esm/public-api.d.ts",