@grainql/analytics-web 2.3.0 → 2.5.0

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 (66) hide show
  1. package/dist/cjs/countries.d.ts +13 -0
  2. package/dist/cjs/countries.d.ts.map +1 -0
  3. package/dist/cjs/countries.js +2907 -0
  4. package/dist/cjs/countries.js.map +1 -0
  5. package/dist/cjs/index.d.ts +29 -1
  6. package/dist/cjs/index.d.ts.map +1 -1
  7. package/dist/cjs/index.js.map +1 -1
  8. package/dist/cjs/interaction-tracking.d.ts +71 -0
  9. package/dist/cjs/interaction-tracking.d.ts.map +1 -0
  10. package/dist/cjs/interaction-tracking.js +270 -0
  11. package/dist/cjs/interaction-tracking.js.map +1 -0
  12. package/dist/cjs/page-tracking.d.ts.map +1 -1
  13. package/dist/cjs/page-tracking.js +5 -1
  14. package/dist/cjs/page-tracking.js.map +1 -1
  15. package/dist/cjs/section-tracking.d.ts +91 -0
  16. package/dist/cjs/section-tracking.d.ts.map +1 -0
  17. package/dist/cjs/section-tracking.js +373 -0
  18. package/dist/cjs/section-tracking.js.map +1 -0
  19. package/dist/cjs/types/auto-tracking.d.ts +55 -0
  20. package/dist/cjs/types/auto-tracking.d.ts.map +1 -0
  21. package/dist/cjs/types/auto-tracking.js +6 -0
  22. package/dist/cjs/types/auto-tracking.js.map +1 -0
  23. package/dist/countries.d.ts +13 -0
  24. package/dist/countries.d.ts.map +1 -0
  25. package/dist/countries.js +2907 -0
  26. package/dist/esm/countries.d.ts +13 -0
  27. package/dist/esm/countries.d.ts.map +1 -0
  28. package/dist/esm/countries.js +2902 -0
  29. package/dist/esm/countries.js.map +1 -0
  30. package/dist/esm/index.d.ts +29 -1
  31. package/dist/esm/index.d.ts.map +1 -1
  32. package/dist/esm/index.js.map +1 -1
  33. package/dist/esm/interaction-tracking.d.ts +71 -0
  34. package/dist/esm/interaction-tracking.d.ts.map +1 -0
  35. package/dist/esm/interaction-tracking.js +266 -0
  36. package/dist/esm/interaction-tracking.js.map +1 -0
  37. package/dist/esm/page-tracking.d.ts.map +1 -1
  38. package/dist/esm/page-tracking.js +5 -1
  39. package/dist/esm/page-tracking.js.map +1 -1
  40. package/dist/esm/section-tracking.d.ts +91 -0
  41. package/dist/esm/section-tracking.d.ts.map +1 -0
  42. package/dist/esm/section-tracking.js +369 -0
  43. package/dist/esm/section-tracking.js.map +1 -0
  44. package/dist/esm/types/auto-tracking.d.ts +55 -0
  45. package/dist/esm/types/auto-tracking.d.ts.map +1 -0
  46. package/dist/esm/types/auto-tracking.js +5 -0
  47. package/dist/esm/types/auto-tracking.js.map +1 -0
  48. package/dist/index.d.ts +29 -1
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.global.dev.js +3609 -2
  51. package/dist/index.global.dev.js.map +4 -4
  52. package/dist/index.global.js +2 -2
  53. package/dist/index.global.js.map +4 -4
  54. package/dist/index.js +130 -1
  55. package/dist/index.mjs +93 -0
  56. package/dist/interaction-tracking.d.ts +71 -0
  57. package/dist/interaction-tracking.d.ts.map +1 -0
  58. package/dist/interaction-tracking.js +270 -0
  59. package/dist/page-tracking.d.ts.map +1 -1
  60. package/dist/page-tracking.js +5 -1
  61. package/dist/section-tracking.d.ts +91 -0
  62. package/dist/section-tracking.d.ts.map +1 -0
  63. package/dist/section-tracking.js +373 -0
  64. package/dist/types/auto-tracking.d.ts +55 -0
  65. package/dist/types/auto-tracking.d.ts.map +1 -0
  66. package/package.json +1 -1
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Section Tracking Manager for Grain Analytics
3
+ * Intelligent scroll tracking with viewport metrics, visible sections, and engagement analysis
4
+ */
5
+ import type { SectionConfig, SectionTrackingOptions } from './types/auto-tracking';
6
+ export interface SectionTracker {
7
+ trackSystemEvent(eventName: string, properties: Record<string, unknown>): void;
8
+ hasConsent(category: 'analytics' | 'marketing' | 'functional'): boolean;
9
+ log(...args: unknown[]): void;
10
+ }
11
+ export declare class SectionTrackingManager {
12
+ private tracker;
13
+ private sections;
14
+ private options;
15
+ private isDestroyed;
16
+ private sectionStates;
17
+ private intersectionObserver;
18
+ private xpathCache;
19
+ private lastScrollPosition;
20
+ private lastScrollTime;
21
+ private scrollVelocity;
22
+ private scrollDebounceTimer;
23
+ private pendingEvents;
24
+ private batchTimer;
25
+ constructor(tracker: SectionTracker, sections: SectionConfig[], options?: Partial<SectionTrackingOptions>);
26
+ /**
27
+ * Initialize section tracking
28
+ */
29
+ private initialize;
30
+ /**
31
+ * Setup IntersectionObserver for section visibility
32
+ */
33
+ private setupIntersectionObserver;
34
+ /**
35
+ * Setup scroll listener for velocity calculation
36
+ */
37
+ private setupScrollListener;
38
+ /**
39
+ * Initialize sections and start observing
40
+ */
41
+ private initializeSections;
42
+ /**
43
+ * Handle intersection observer entry
44
+ */
45
+ private handleIntersection;
46
+ /**
47
+ * Handle section entry (became visible)
48
+ */
49
+ private handleSectionEntry;
50
+ /**
51
+ * Handle section exit (became invisible)
52
+ */
53
+ private handleSectionExit;
54
+ /**
55
+ * Update scroll velocity
56
+ */
57
+ private updateScrollVelocity;
58
+ /**
59
+ * Calculate current scroll depth as percentage
60
+ */
61
+ private calculateScrollDepth;
62
+ /**
63
+ * Determine if section view should be tracked (sanitization)
64
+ */
65
+ private shouldTrackSection;
66
+ /**
67
+ * Queue section view for batching
68
+ */
69
+ private queueSectionView;
70
+ /**
71
+ * Flush pending section view events
72
+ */
73
+ private flushPendingEvents;
74
+ /**
75
+ * Find element by XPath selector
76
+ */
77
+ private findElementByXPath;
78
+ /**
79
+ * Log debug messages
80
+ */
81
+ private log;
82
+ /**
83
+ * Update sections configuration
84
+ */
85
+ updateSections(sections: SectionConfig[]): void;
86
+ /**
87
+ * Cleanup and destroy
88
+ */
89
+ destroy(): void;
90
+ }
91
+ //# sourceMappingURL=section-tracking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"section-tracking.d.ts","sourceRoot":"","sources":["../src/section-tracking.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAmB,sBAAsB,EAAwB,MAAM,uBAAuB,CAAC;AAE1H,MAAM,WAAW,cAAc;IAC7B,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/E,UAAU,CAAC,QAAQ,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,GAAG,OAAO,CAAC;IACxE,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAC/B;AAWD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,aAAa,CAAgD;IACrE,OAAO,CAAC,oBAAoB,CAAqC;IACjE,OAAO,CAAC,UAAU,CAA0C;IAG5D,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,mBAAmB,CAAuB;IAGlD,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,UAAU,CAAuB;gBAGvC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,aAAa,EAAE,EACzB,OAAO,GAAE,OAAO,CAAC,sBAAsB,CAAM;IAgB/C;;OAEG;IACH,OAAO,CAAC,UAAU;IAelB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAqBjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAkB3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkC1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA8B1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoCzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAe5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA+B1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAgC1B;;OAEG;IACH,OAAO,CAAC,GAAG;IAMX;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI;IAsB/C;;OAEG;IACH,OAAO,IAAI,IAAI;CAgChB"}
@@ -0,0 +1,373 @@
1
+ "use strict";
2
+ /**
3
+ * Section Tracking Manager for Grain Analytics
4
+ * Intelligent scroll tracking with viewport metrics, visible sections, and engagement analysis
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SectionTrackingManager = void 0;
8
+ const DEFAULT_OPTIONS = {
9
+ minDwellTime: 1000, // 1 second minimum
10
+ scrollVelocityThreshold: 500, // 500px/s
11
+ intersectionThreshold: 0.1, // 10% visible
12
+ debounceDelay: 100,
13
+ batchDelay: 2000, // 2 seconds
14
+ debug: false,
15
+ };
16
+ class SectionTrackingManager {
17
+ constructor(tracker, sections, options = {}) {
18
+ this.isDestroyed = false;
19
+ // Tracking state
20
+ this.sectionStates = new Map();
21
+ this.intersectionObserver = null;
22
+ this.xpathCache = new Map();
23
+ // Scroll tracking
24
+ this.lastScrollPosition = 0;
25
+ this.lastScrollTime = Date.now();
26
+ this.scrollVelocity = 0;
27
+ this.scrollDebounceTimer = null;
28
+ // Event batching
29
+ this.pendingEvents = [];
30
+ this.batchTimer = null;
31
+ this.tracker = tracker;
32
+ this.sections = sections;
33
+ this.options = { ...DEFAULT_OPTIONS, ...options };
34
+ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
35
+ // Initialize after DOM is ready
36
+ if (document.readyState === 'loading') {
37
+ document.addEventListener('DOMContentLoaded', () => this.initialize());
38
+ }
39
+ else {
40
+ setTimeout(() => this.initialize(), 0);
41
+ }
42
+ }
43
+ }
44
+ /**
45
+ * Initialize section tracking
46
+ */
47
+ initialize() {
48
+ if (this.isDestroyed)
49
+ return;
50
+ this.log('Initializing section tracking for', this.sections.length, 'sections');
51
+ // Setup intersection observer
52
+ this.setupIntersectionObserver();
53
+ // Setup scroll listener for velocity tracking
54
+ this.setupScrollListener();
55
+ // Initialize sections
56
+ this.initializeSections();
57
+ }
58
+ /**
59
+ * Setup IntersectionObserver for section visibility
60
+ */
61
+ setupIntersectionObserver() {
62
+ if (typeof IntersectionObserver === 'undefined') {
63
+ this.log('IntersectionObserver not supported');
64
+ return;
65
+ }
66
+ this.intersectionObserver = new IntersectionObserver((entries) => {
67
+ entries.forEach((entry) => {
68
+ this.handleIntersection(entry);
69
+ });
70
+ }, {
71
+ threshold: [0, 0.1, 0.25, 0.5, 0.75, 1.0],
72
+ rootMargin: '0px',
73
+ });
74
+ this.log('IntersectionObserver created');
75
+ }
76
+ /**
77
+ * Setup scroll listener for velocity calculation
78
+ */
79
+ setupScrollListener() {
80
+ if (typeof window === 'undefined')
81
+ return;
82
+ const scrollHandler = () => {
83
+ if (this.scrollDebounceTimer !== null) {
84
+ clearTimeout(this.scrollDebounceTimer);
85
+ }
86
+ this.scrollDebounceTimer = window.setTimeout(() => {
87
+ this.updateScrollVelocity();
88
+ this.scrollDebounceTimer = null;
89
+ }, this.options.debounceDelay);
90
+ };
91
+ window.addEventListener('scroll', scrollHandler, { passive: true });
92
+ this.log('Scroll listener attached');
93
+ }
94
+ /**
95
+ * Initialize sections and start observing
96
+ */
97
+ initializeSections() {
98
+ for (const section of this.sections) {
99
+ const element = this.findElementByXPath(section.selector);
100
+ if (!element) {
101
+ this.log('Section element not found:', section.sectionName, 'selector:', section.selector);
102
+ continue;
103
+ }
104
+ // Initialize state
105
+ const state = {
106
+ element,
107
+ config: section,
108
+ entryTime: null,
109
+ exitTime: null,
110
+ isVisible: false,
111
+ lastScrollPosition: window.scrollY,
112
+ lastScrollTime: Date.now(),
113
+ entryScrollSpeed: 0,
114
+ exitScrollSpeed: 0,
115
+ maxVisibleArea: 0,
116
+ };
117
+ this.sectionStates.set(section.sectionName, state);
118
+ // Start observing
119
+ if (this.intersectionObserver) {
120
+ this.intersectionObserver.observe(element);
121
+ }
122
+ this.log('Section initialized and observed:', section.sectionName);
123
+ }
124
+ }
125
+ /**
126
+ * Handle intersection observer entry
127
+ */
128
+ handleIntersection(entry) {
129
+ if (this.isDestroyed)
130
+ return;
131
+ // Find which section this element belongs to
132
+ const state = Array.from(this.sectionStates.values()).find((s) => s.element === entry.target);
133
+ if (!state)
134
+ return;
135
+ const isVisible = entry.isIntersecting && entry.intersectionRatio >= this.options.intersectionThreshold;
136
+ const visibleArea = entry.intersectionRatio;
137
+ // Update max visible area
138
+ if (visibleArea > state.maxVisibleArea) {
139
+ state.maxVisibleArea = visibleArea;
140
+ }
141
+ // Handle visibility change
142
+ if (isVisible && !state.isVisible) {
143
+ // Section became visible
144
+ this.handleSectionEntry(state);
145
+ }
146
+ else if (!isVisible && state.isVisible) {
147
+ // Section became invisible
148
+ this.handleSectionExit(state);
149
+ }
150
+ state.isVisible = isVisible;
151
+ }
152
+ /**
153
+ * Handle section entry (became visible)
154
+ */
155
+ handleSectionEntry(state) {
156
+ this.log('Section entered view:', state.config.sectionName);
157
+ state.entryTime = Date.now();
158
+ state.entryScrollSpeed = this.scrollVelocity;
159
+ state.lastScrollPosition = window.scrollY;
160
+ state.lastScrollTime = Date.now();
161
+ state.maxVisibleArea = 0;
162
+ }
163
+ /**
164
+ * Handle section exit (became invisible)
165
+ */
166
+ handleSectionExit(state) {
167
+ this.log('Section exited view:', state.config.sectionName);
168
+ if (state.entryTime === null)
169
+ return;
170
+ state.exitTime = Date.now();
171
+ state.exitScrollSpeed = this.scrollVelocity;
172
+ const duration = state.exitTime - state.entryTime;
173
+ // Create section view data
174
+ const viewData = {
175
+ sectionName: state.config.sectionName,
176
+ sectionType: state.config.sectionType,
177
+ entryTime: state.entryTime,
178
+ exitTime: state.exitTime,
179
+ duration,
180
+ viewportWidth: window.innerWidth,
181
+ viewportHeight: window.innerHeight,
182
+ scrollDepth: this.calculateScrollDepth(),
183
+ visibleAreaPercentage: Math.round(state.maxVisibleArea * 100),
184
+ scrollSpeedAtEntry: state.entryScrollSpeed,
185
+ scrollSpeedAtExit: state.exitScrollSpeed,
186
+ };
187
+ // Apply sanitization and track if valid
188
+ if (this.shouldTrackSection(viewData)) {
189
+ this.queueSectionView(viewData);
190
+ }
191
+ else {
192
+ this.log('Section view filtered out:', state.config.sectionName, 'duration:', duration);
193
+ }
194
+ // Reset entry time
195
+ state.entryTime = null;
196
+ }
197
+ /**
198
+ * Update scroll velocity
199
+ */
200
+ updateScrollVelocity() {
201
+ const now = Date.now();
202
+ const currentPosition = window.scrollY;
203
+ const timeDelta = now - this.lastScrollTime;
204
+ const positionDelta = Math.abs(currentPosition - this.lastScrollPosition);
205
+ if (timeDelta > 0) {
206
+ this.scrollVelocity = (positionDelta / timeDelta) * 1000; // pixels per second
207
+ }
208
+ this.lastScrollPosition = currentPosition;
209
+ this.lastScrollTime = now;
210
+ }
211
+ /**
212
+ * Calculate current scroll depth as percentage
213
+ */
214
+ calculateScrollDepth() {
215
+ if (typeof window === 'undefined' || typeof document === 'undefined')
216
+ return 0;
217
+ const windowHeight = window.innerHeight;
218
+ const documentHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
219
+ const scrollTop = window.scrollY;
220
+ const scrollableHeight = documentHeight - windowHeight;
221
+ if (scrollableHeight <= 0)
222
+ return 100;
223
+ return Math.round((scrollTop / scrollableHeight) * 100);
224
+ }
225
+ /**
226
+ * Determine if section view should be tracked (sanitization)
227
+ */
228
+ shouldTrackSection(viewData) {
229
+ // Minimum dwell time check
230
+ if (viewData.duration < this.options.minDwellTime) {
231
+ return false;
232
+ }
233
+ // Check if user was rapidly scrolling through
234
+ const avgScrollSpeed = (viewData.scrollSpeedAtEntry + viewData.scrollSpeedAtExit) / 2;
235
+ if (avgScrollSpeed > this.options.scrollVelocityThreshold * 2) {
236
+ // Very fast scroll - likely not engaged
237
+ return false;
238
+ }
239
+ // Must have had some meaningful visible area
240
+ if (viewData.visibleAreaPercentage < 10) {
241
+ return false;
242
+ }
243
+ return true;
244
+ }
245
+ /**
246
+ * Queue section view for batching
247
+ */
248
+ queueSectionView(viewData) {
249
+ this.pendingEvents.push(viewData);
250
+ this.log('Queued section view:', viewData.sectionName, 'duration:', viewData.duration);
251
+ // Setup batch timer if not already set
252
+ if (this.batchTimer === null) {
253
+ this.batchTimer = window.setTimeout(() => {
254
+ this.flushPendingEvents();
255
+ }, this.options.batchDelay);
256
+ }
257
+ }
258
+ /**
259
+ * Flush pending section view events
260
+ */
261
+ flushPendingEvents() {
262
+ if (this.isDestroyed || this.pendingEvents.length === 0)
263
+ return;
264
+ if (!this.tracker.hasConsent('analytics')) {
265
+ this.pendingEvents = [];
266
+ return;
267
+ }
268
+ this.log('Flushing', this.pendingEvents.length, 'section view events');
269
+ // Track each section view
270
+ for (const viewData of this.pendingEvents) {
271
+ this.tracker.trackSystemEvent('_grain_section_view', {
272
+ section_name: viewData.sectionName,
273
+ section_type: viewData.sectionType,
274
+ duration_ms: viewData.duration,
275
+ viewport_width: viewData.viewportWidth,
276
+ viewport_height: viewData.viewportHeight,
277
+ scroll_depth_percent: viewData.scrollDepth,
278
+ visible_area_percent: viewData.visibleAreaPercentage,
279
+ scroll_speed_entry: Math.round(viewData.scrollSpeedAtEntry || 0),
280
+ scroll_speed_exit: Math.round(viewData.scrollSpeedAtExit || 0),
281
+ entry_timestamp: viewData.entryTime,
282
+ exit_timestamp: viewData.exitTime,
283
+ });
284
+ }
285
+ // Clear pending events
286
+ this.pendingEvents = [];
287
+ this.batchTimer = null;
288
+ }
289
+ /**
290
+ * Find element by XPath selector
291
+ */
292
+ findElementByXPath(xpath) {
293
+ // Check cache first
294
+ if (this.xpathCache.has(xpath)) {
295
+ const cached = this.xpathCache.get(xpath);
296
+ if (cached && document.contains(cached)) {
297
+ return cached;
298
+ }
299
+ this.xpathCache.delete(xpath);
300
+ }
301
+ try {
302
+ const result = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
303
+ const element = result.singleNodeValue;
304
+ if (element) {
305
+ this.xpathCache.set(xpath, element);
306
+ }
307
+ return element;
308
+ }
309
+ catch (error) {
310
+ this.log('Error evaluating XPath:', xpath, error);
311
+ return null;
312
+ }
313
+ }
314
+ /**
315
+ * Log debug messages
316
+ */
317
+ log(...args) {
318
+ if (this.options.debug) {
319
+ console.log('[SectionTracking]', ...args);
320
+ }
321
+ }
322
+ /**
323
+ * Update sections configuration
324
+ */
325
+ updateSections(sections) {
326
+ if (this.isDestroyed)
327
+ return;
328
+ this.log('Updating sections configuration');
329
+ // Disconnect observer
330
+ if (this.intersectionObserver) {
331
+ this.intersectionObserver.disconnect();
332
+ }
333
+ // Clear state
334
+ this.sectionStates.clear();
335
+ this.xpathCache.clear();
336
+ // Update configuration
337
+ this.sections = sections;
338
+ // Reinitialize
339
+ this.setupIntersectionObserver();
340
+ this.initializeSections();
341
+ }
342
+ /**
343
+ * Cleanup and destroy
344
+ */
345
+ destroy() {
346
+ if (this.isDestroyed)
347
+ return;
348
+ this.log('Destroying section tracking manager');
349
+ this.isDestroyed = true;
350
+ // Flush any pending events
351
+ this.flushPendingEvents();
352
+ // Clear timers
353
+ if (this.scrollDebounceTimer !== null) {
354
+ clearTimeout(this.scrollDebounceTimer);
355
+ this.scrollDebounceTimer = null;
356
+ }
357
+ if (this.batchTimer !== null) {
358
+ clearTimeout(this.batchTimer);
359
+ this.batchTimer = null;
360
+ }
361
+ // Disconnect intersection observer
362
+ if (this.intersectionObserver) {
363
+ this.intersectionObserver.disconnect();
364
+ this.intersectionObserver = null;
365
+ }
366
+ // Clear state
367
+ this.sectionStates.clear();
368
+ this.xpathCache.clear();
369
+ this.pendingEvents = [];
370
+ }
371
+ }
372
+ exports.SectionTrackingManager = SectionTrackingManager;
373
+ //# sourceMappingURL=section-tracking.js.map
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Auto-tracking types for Grain Analytics SDK
3
+ */
4
+ export interface InteractionConfig {
5
+ eventName: string;
6
+ description: string;
7
+ selector: string;
8
+ priority: number;
9
+ label: string;
10
+ }
11
+ export interface SectionConfig {
12
+ sectionName: string;
13
+ description: string;
14
+ sectionType: string;
15
+ selector: string;
16
+ importance: number;
17
+ }
18
+ export interface AutoTrackingConfig {
19
+ interactions: InteractionConfig[];
20
+ sections: SectionConfig[];
21
+ }
22
+ export interface SectionViewData {
23
+ sectionName: string;
24
+ sectionType: string;
25
+ entryTime: number;
26
+ exitTime: number;
27
+ duration: number;
28
+ viewportWidth: number;
29
+ viewportHeight: number;
30
+ scrollDepth: number;
31
+ visibleAreaPercentage: number;
32
+ scrollSpeedAtEntry?: number;
33
+ scrollSpeedAtExit?: number;
34
+ }
35
+ export interface SectionTrackingOptions {
36
+ minDwellTime: number;
37
+ scrollVelocityThreshold: number;
38
+ intersectionThreshold: number;
39
+ debounceDelay: number;
40
+ batchDelay: number;
41
+ debug?: boolean;
42
+ }
43
+ export interface SectionTrackingState {
44
+ element: Element;
45
+ config: SectionConfig;
46
+ entryTime: number | null;
47
+ exitTime: number | null;
48
+ isVisible: boolean;
49
+ lastScrollPosition: number;
50
+ lastScrollTime: number;
51
+ entryScrollSpeed: number;
52
+ exitScrollSpeed: number;
53
+ maxVisibleArea: number;
54
+ }
55
+ //# sourceMappingURL=auto-tracking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-tracking.d.ts","sourceRoot":"","sources":["../../src/types/auto-tracking.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB,EAAE,MAAM,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grainql/analytics-web",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "description": "Lightweight TypeScript SDK for sending analytics events and managing remote configurations via Grain's REST API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",