@grainql/analytics-web 2.5.4 → 2.7.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.
- package/README.md +3 -1
- package/dist/activity.js +1 -1
- package/dist/attention-quality.d.ts +128 -0
- package/dist/attention-quality.d.ts.map +1 -0
- package/dist/attention-quality.js +246 -0
- package/dist/cjs/activity.js +1 -1
- package/dist/cjs/activity.js.map +1 -1
- package/dist/cjs/attention-quality.d.ts +128 -0
- package/dist/cjs/attention-quality.d.ts.map +1 -0
- package/dist/cjs/attention-quality.js +246 -0
- package/dist/cjs/attention-quality.js.map +1 -0
- package/dist/cjs/consent.js +4 -4
- package/dist/cjs/consent.js.map +1 -1
- package/dist/cjs/heartbeat.d.ts.map +1 -1
- package/dist/cjs/heartbeat.js +0 -6
- package/dist/cjs/heartbeat.js.map +1 -1
- package/dist/cjs/heatmap-tracking.d.ts +93 -0
- package/dist/cjs/heatmap-tracking.d.ts.map +1 -0
- package/dist/cjs/heatmap-tracking.js +499 -0
- package/dist/cjs/heatmap-tracking.js.map +1 -0
- package/dist/cjs/index.d.ts +11 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interaction-tracking.d.ts.map +1 -1
- package/dist/cjs/interaction-tracking.js +9 -18
- package/dist/cjs/interaction-tracking.js.map +1 -1
- package/dist/cjs/page-tracking.d.ts.map +1 -1
- package/dist/cjs/page-tracking.js +0 -9
- package/dist/cjs/page-tracking.js.map +1 -1
- package/dist/cjs/section-tracking.d.ts +3 -0
- package/dist/cjs/section-tracking.d.ts.map +1 -1
- package/dist/cjs/section-tracking.js +30 -7
- package/dist/cjs/section-tracking.js.map +1 -1
- package/dist/cjs/types/auto-tracking.d.ts +3 -0
- package/dist/cjs/types/auto-tracking.d.ts.map +1 -1
- package/dist/cjs/types/heatmap-tracking.d.ts +44 -0
- package/dist/cjs/types/heatmap-tracking.d.ts.map +1 -0
- package/dist/cjs/types/heatmap-tracking.js +6 -0
- package/dist/cjs/types/heatmap-tracking.js.map +1 -0
- package/dist/consent.js +4 -4
- package/dist/esm/activity.js +1 -1
- package/dist/esm/activity.js.map +1 -1
- package/dist/esm/attention-quality.d.ts +128 -0
- package/dist/esm/attention-quality.d.ts.map +1 -0
- package/dist/esm/attention-quality.js +242 -0
- package/dist/esm/attention-quality.js.map +1 -0
- package/dist/esm/consent.js +4 -4
- package/dist/esm/consent.js.map +1 -1
- package/dist/esm/heartbeat.d.ts.map +1 -1
- package/dist/esm/heartbeat.js +0 -6
- package/dist/esm/heartbeat.js.map +1 -1
- package/dist/esm/heatmap-tracking.d.ts +93 -0
- package/dist/esm/heatmap-tracking.d.ts.map +1 -0
- package/dist/esm/heatmap-tracking.js +495 -0
- package/dist/esm/heatmap-tracking.js.map +1 -0
- package/dist/esm/index.d.ts +11 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interaction-tracking.d.ts.map +1 -1
- package/dist/esm/interaction-tracking.js +9 -18
- package/dist/esm/interaction-tracking.js.map +1 -1
- package/dist/esm/page-tracking.d.ts.map +1 -1
- package/dist/esm/page-tracking.js +0 -9
- package/dist/esm/page-tracking.js.map +1 -1
- package/dist/esm/section-tracking.d.ts +3 -0
- package/dist/esm/section-tracking.d.ts.map +1 -1
- package/dist/esm/section-tracking.js +30 -7
- package/dist/esm/section-tracking.js.map +1 -1
- package/dist/esm/types/auto-tracking.d.ts +3 -0
- package/dist/esm/types/auto-tracking.d.ts.map +1 -1
- package/dist/esm/types/heatmap-tracking.d.ts +44 -0
- package/dist/esm/types/heatmap-tracking.d.ts.map +1 -0
- package/dist/esm/types/heatmap-tracking.js +5 -0
- package/dist/esm/types/heatmap-tracking.js.map +1 -0
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +0 -6
- package/dist/heatmap-tracking.d.ts +93 -0
- package/dist/heatmap-tracking.d.ts.map +1 -0
- package/dist/heatmap-tracking.js +499 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.global.dev.js +801 -80
- package/dist/index.global.dev.js.map +4 -4
- package/dist/index.global.js +2 -2
- package/dist/index.global.js.map +4 -4
- package/dist/index.js +70 -38
- package/dist/index.mjs +70 -38
- package/dist/interaction-tracking.d.ts.map +1 -1
- package/dist/interaction-tracking.js +9 -18
- package/dist/page-tracking.d.ts.map +1 -1
- package/dist/page-tracking.js +0 -9
- package/dist/section-tracking.d.ts +3 -0
- package/dist/section-tracking.d.ts.map +1 -1
- package/dist/section-tracking.js +30 -7
- package/dist/types/auto-tracking.d.ts +3 -0
- package/dist/types/auto-tracking.d.ts.map +1 -1
- package/dist/types/heatmap-tracking.d.ts +44 -0
- package/dist/types/heatmap-tracking.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -75,6 +75,7 @@ class GrainAnalytics {
|
|
|
75
75
|
// Auto-tracking properties
|
|
76
76
|
this.interactionTrackingManager = null;
|
|
77
77
|
this.sectionTrackingManager = null;
|
|
78
|
+
this.heatmapTrackingManager = null;
|
|
78
79
|
// Session tracking
|
|
79
80
|
this.sessionStartTime = Date.now();
|
|
80
81
|
this.sessionEventCount = 0;
|
|
@@ -104,6 +105,8 @@ class GrainAnalytics {
|
|
|
104
105
|
heartbeatInactiveInterval: 300000, // 5 minutes
|
|
105
106
|
enableAutoPageView: true,
|
|
106
107
|
stripQueryParams: true,
|
|
108
|
+
// Heatmap Tracking defaults
|
|
109
|
+
enableHeatmapTracking: true,
|
|
107
110
|
...config,
|
|
108
111
|
tenantId: config.tenantId,
|
|
109
112
|
};
|
|
@@ -132,6 +135,10 @@ class GrainAnalytics {
|
|
|
132
135
|
this.initializeAutomaticTracking();
|
|
133
136
|
// Track session start
|
|
134
137
|
this.trackSessionStart();
|
|
138
|
+
// Initialize heatmap tracking if enabled
|
|
139
|
+
if (this.config.enableHeatmapTracking) {
|
|
140
|
+
this.initializeHeatmapTracking();
|
|
141
|
+
}
|
|
135
142
|
}
|
|
136
143
|
// Set up consent change listener to flush waiting events and handle consent upgrade
|
|
137
144
|
this.consentManager.addListener((state) => {
|
|
@@ -381,6 +388,9 @@ class GrainAnalytics {
|
|
|
381
388
|
* Log formatted error gracefully
|
|
382
389
|
*/
|
|
383
390
|
logError(formattedError) {
|
|
391
|
+
// Only log errors in debug mode to reduce noise in production
|
|
392
|
+
if (!this.config.debug)
|
|
393
|
+
return;
|
|
384
394
|
const { code, message, digest, timestamp, context } = formattedError;
|
|
385
395
|
const errorOutput = {
|
|
386
396
|
'🚨 Grain Analytics Error': {
|
|
@@ -398,10 +408,7 @@ class GrainAnalytics {
|
|
|
398
408
|
}
|
|
399
409
|
};
|
|
400
410
|
console.error('🚨 Grain Analytics Error:', errorOutput);
|
|
401
|
-
|
|
402
|
-
if (this.config.debug) {
|
|
403
|
-
console.error(`[Grain Analytics] ${code}: ${message} (${context}) - Events: ${digest.eventCount}, Props: ${digest.totalProperties}, Size: ${digest.totalSize}B`);
|
|
404
|
-
}
|
|
411
|
+
console.error(`[Grain Analytics] ${code}: ${message} (${context}) - Events: ${digest.eventCount}, Props: ${digest.totalProperties}, Size: ${digest.totalSize}B`);
|
|
405
412
|
}
|
|
406
413
|
/**
|
|
407
414
|
* Safely execute a function with error handling
|
|
@@ -509,7 +516,6 @@ class GrainAnalytics {
|
|
|
509
516
|
try {
|
|
510
517
|
const headers = await this.getAuthHeaders();
|
|
511
518
|
const url = `${this.config.apiUrl}/v1/events/${encodeURIComponent(this.config.tenantId)}/multi`;
|
|
512
|
-
this.log(`Sending ${events.length} events to ${url} (attempt ${attempt + 1})`);
|
|
513
519
|
const response = await fetch(url, {
|
|
514
520
|
method: 'POST',
|
|
515
521
|
headers,
|
|
@@ -582,7 +588,6 @@ class GrainAnalytics {
|
|
|
582
588
|
body,
|
|
583
589
|
keepalive: true,
|
|
584
590
|
});
|
|
585
|
-
this.log(`Successfully sent ${events.length} events via fetch (keepalive)`);
|
|
586
591
|
}
|
|
587
592
|
catch (error) {
|
|
588
593
|
// Log error gracefully for beacon failures (page unload scenarios)
|
|
@@ -654,7 +659,6 @@ class GrainAnalytics {
|
|
|
654
659
|
inactiveInterval: this.config.heartbeatInactiveInterval,
|
|
655
660
|
debug: this.config.debug,
|
|
656
661
|
});
|
|
657
|
-
this.log('Heartbeat tracking initialized');
|
|
658
662
|
}
|
|
659
663
|
catch (error) {
|
|
660
664
|
this.log('Failed to initialize heartbeat tracking:', error);
|
|
@@ -667,7 +671,6 @@ class GrainAnalytics {
|
|
|
667
671
|
debug: this.config.debug,
|
|
668
672
|
tenantId: this.config.tenantId,
|
|
669
673
|
});
|
|
670
|
-
this.log('Auto page view tracking initialized');
|
|
671
674
|
}
|
|
672
675
|
catch (error) {
|
|
673
676
|
this.log('Failed to initialize page view tracking:', error);
|
|
@@ -676,12 +679,41 @@ class GrainAnalytics {
|
|
|
676
679
|
// Initialize auto-tracking when config is available
|
|
677
680
|
this.initializeAutoTracking();
|
|
678
681
|
}
|
|
682
|
+
/**
|
|
683
|
+
* Initialize heatmap tracking
|
|
684
|
+
*/
|
|
685
|
+
initializeHeatmapTracking() {
|
|
686
|
+
if (typeof window === 'undefined')
|
|
687
|
+
return;
|
|
688
|
+
try {
|
|
689
|
+
this.log('Initializing heatmap tracking');
|
|
690
|
+
Promise.resolve().then(() => __importStar(require('./heatmap-tracking'))).then(({ HeatmapTrackingManager }) => {
|
|
691
|
+
try {
|
|
692
|
+
this.heatmapTrackingManager = new HeatmapTrackingManager(this, {
|
|
693
|
+
scrollDebounceDelay: 100,
|
|
694
|
+
batchDelay: 2000,
|
|
695
|
+
maxBatchSize: 20,
|
|
696
|
+
debug: this.config.debug,
|
|
697
|
+
});
|
|
698
|
+
this.log('Heatmap tracking initialized');
|
|
699
|
+
}
|
|
700
|
+
catch (error) {
|
|
701
|
+
this.log('Failed to initialize heatmap tracking:', error);
|
|
702
|
+
}
|
|
703
|
+
}).catch((error) => {
|
|
704
|
+
this.log('Failed to load heatmap tracking module:', error);
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
catch (error) {
|
|
708
|
+
this.log('Failed to initialize heatmap tracking:', error);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
679
711
|
/**
|
|
680
712
|
* Initialize auto-tracking (interactions and sections)
|
|
681
713
|
*/
|
|
682
714
|
async initializeAutoTracking() {
|
|
683
715
|
try {
|
|
684
|
-
this.log('Initializing auto-tracking
|
|
716
|
+
this.log('Initializing auto-tracking');
|
|
685
717
|
// Fetch remote config to get auto-tracking configuration
|
|
686
718
|
const userId = this.globalUserId || this.persistentAnonymousUserId || this.generateUUID();
|
|
687
719
|
const currentUrl = typeof window !== 'undefined' ? window.location.href : '';
|
|
@@ -694,25 +726,20 @@ class GrainAnalytics {
|
|
|
694
726
|
};
|
|
695
727
|
const headers = await this.getAuthHeaders();
|
|
696
728
|
const url = `${this.config.apiUrl}/v1/client/${encodeURIComponent(this.config.tenantId)}/config/configurations`;
|
|
697
|
-
this.log('Fetching auto-tracking config from:', url);
|
|
698
729
|
const response = await fetch(url, {
|
|
699
730
|
method: 'POST',
|
|
700
731
|
headers,
|
|
701
732
|
body: JSON.stringify(request),
|
|
702
733
|
});
|
|
703
734
|
if (!response.ok) {
|
|
704
|
-
this.log('Failed to fetch auto-tracking config:', response.status
|
|
735
|
+
this.log('Failed to fetch auto-tracking config:', response.status);
|
|
705
736
|
return;
|
|
706
737
|
}
|
|
707
738
|
const configResponse = await response.json();
|
|
708
|
-
this.log('Received config response:', configResponse);
|
|
709
739
|
if (configResponse.autoTrackingConfig) {
|
|
710
|
-
this.log('Auto-tracking config
|
|
740
|
+
this.log('Auto-tracking config loaded');
|
|
711
741
|
this.setupAutoTrackingManagers(configResponse.autoTrackingConfig);
|
|
712
742
|
}
|
|
713
|
-
else {
|
|
714
|
-
this.log('No auto-tracking config in response');
|
|
715
|
-
}
|
|
716
743
|
}
|
|
717
744
|
catch (error) {
|
|
718
745
|
this.log('Failed to initialize auto-tracking:', error);
|
|
@@ -723,10 +750,10 @@ class GrainAnalytics {
|
|
|
723
750
|
* Setup auto-tracking managers
|
|
724
751
|
*/
|
|
725
752
|
setupAutoTrackingManagers(config) {
|
|
726
|
-
this.log('Setting up auto-tracking managers
|
|
753
|
+
this.log('Setting up auto-tracking managers');
|
|
727
754
|
// Lazy load the managers to avoid bundling them if not needed
|
|
728
755
|
if (config.interactions && config.interactions.length > 0) {
|
|
729
|
-
this.log('Loading interaction tracking
|
|
756
|
+
this.log('Loading interaction tracking:', config.interactions.length, 'interactions');
|
|
730
757
|
Promise.resolve().then(() => __importStar(require('./interaction-tracking'))).then(({ InteractionTrackingManager }) => {
|
|
731
758
|
try {
|
|
732
759
|
this.interactionTrackingManager = new InteractionTrackingManager(this, config.interactions, {
|
|
@@ -734,20 +761,17 @@ class GrainAnalytics {
|
|
|
734
761
|
enableMutationObserver: true,
|
|
735
762
|
mutationDebounceDelay: 500,
|
|
736
763
|
});
|
|
737
|
-
this.log('
|
|
764
|
+
this.log('Interaction tracking initialized');
|
|
738
765
|
}
|
|
739
766
|
catch (error) {
|
|
740
|
-
this.log('
|
|
767
|
+
this.log('Failed to initialize interaction tracking:', error);
|
|
741
768
|
}
|
|
742
769
|
}).catch((error) => {
|
|
743
|
-
this.log('
|
|
770
|
+
this.log('Failed to load interaction tracking module:', error);
|
|
744
771
|
});
|
|
745
772
|
}
|
|
746
|
-
else {
|
|
747
|
-
this.log('No interactions configured for auto-tracking');
|
|
748
|
-
}
|
|
749
773
|
if (config.sections && config.sections.length > 0) {
|
|
750
|
-
this.log('Loading section tracking
|
|
774
|
+
this.log('Loading section tracking:', config.sections.length, 'sections');
|
|
751
775
|
Promise.resolve().then(() => __importStar(require('./section-tracking'))).then(({ SectionTrackingManager }) => {
|
|
752
776
|
try {
|
|
753
777
|
this.sectionTrackingManager = new SectionTrackingManager(this, config.sections, {
|
|
@@ -758,18 +782,15 @@ class GrainAnalytics {
|
|
|
758
782
|
batchDelay: 2000,
|
|
759
783
|
debug: this.config.debug,
|
|
760
784
|
});
|
|
761
|
-
this.log('
|
|
785
|
+
this.log('Section tracking initialized');
|
|
762
786
|
}
|
|
763
787
|
catch (error) {
|
|
764
|
-
this.log('
|
|
788
|
+
this.log('Failed to initialize section tracking:', error);
|
|
765
789
|
}
|
|
766
790
|
}).catch((error) => {
|
|
767
|
-
this.log('
|
|
791
|
+
this.log('Failed to load section tracking module:', error);
|
|
768
792
|
});
|
|
769
793
|
}
|
|
770
|
-
else {
|
|
771
|
-
this.log('No sections configured for auto-tracking');
|
|
772
|
-
}
|
|
773
794
|
}
|
|
774
795
|
/**
|
|
775
796
|
* Track session start event
|
|
@@ -827,7 +848,7 @@ class GrainAnalytics {
|
|
|
827
848
|
properties.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
828
849
|
}
|
|
829
850
|
this.trackSystemEvent('_grain_session_start', properties);
|
|
830
|
-
this.log('Session started
|
|
851
|
+
this.log('Session started');
|
|
831
852
|
}
|
|
832
853
|
/**
|
|
833
854
|
* Track session end event
|
|
@@ -850,7 +871,7 @@ class GrainAnalytics {
|
|
|
850
871
|
properties.page_count = pageCount; // Keep for backward compatibility
|
|
851
872
|
}
|
|
852
873
|
this.trackSystemEvent('_grain_session_end', properties);
|
|
853
|
-
this.log('Session ended
|
|
874
|
+
this.log('Session ended');
|
|
854
875
|
}
|
|
855
876
|
/**
|
|
856
877
|
* Detect browser name
|
|
@@ -954,7 +975,7 @@ class GrainAnalytics {
|
|
|
954
975
|
// Bypass consent check for necessary system events
|
|
955
976
|
this.eventQueue.push(event);
|
|
956
977
|
this.eventCountSinceLastHeartbeat++;
|
|
957
|
-
this.log(`Queued system event: ${eventName}
|
|
978
|
+
this.log(`Queued system event: ${eventName}`);
|
|
958
979
|
// Consider flushing
|
|
959
980
|
if (this.eventQueue.length >= this.config.batchSize) {
|
|
960
981
|
this.flush().catch((error) => {
|
|
@@ -990,6 +1011,15 @@ class GrainAnalytics {
|
|
|
990
1011
|
resetEventCountSinceLastHeartbeat() {
|
|
991
1012
|
this.eventCountSinceLastHeartbeat = 0;
|
|
992
1013
|
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Get the activity detector (for internal use by tracking managers)
|
|
1016
|
+
*/
|
|
1017
|
+
getActivityDetector() {
|
|
1018
|
+
if (!this.activityDetector) {
|
|
1019
|
+
throw new Error('Activity detector not initialized');
|
|
1020
|
+
}
|
|
1021
|
+
return this.activityDetector;
|
|
1022
|
+
}
|
|
993
1023
|
/**
|
|
994
1024
|
* Get the effective user ID (public method)
|
|
995
1025
|
*/
|
|
@@ -1049,7 +1079,7 @@ class GrainAnalytics {
|
|
|
1049
1079
|
this.eventQueue.push(formattedEvent);
|
|
1050
1080
|
this.eventCountSinceLastHeartbeat++;
|
|
1051
1081
|
this.sessionEventCount++;
|
|
1052
|
-
this.log(`Queued event: ${event.eventName}
|
|
1082
|
+
this.log(`Queued event: ${event.eventName}`);
|
|
1053
1083
|
// Check if we should flush immediately
|
|
1054
1084
|
if (opts.flush || this.eventQueue.length >= this.config.batchSize) {
|
|
1055
1085
|
await this.flush();
|
|
@@ -1275,7 +1305,6 @@ class GrainAnalytics {
|
|
|
1275
1305
|
try {
|
|
1276
1306
|
const headers = await this.getAuthHeaders();
|
|
1277
1307
|
const url = `${this.config.apiUrl}/v1/events/${encodeURIComponent(this.config.tenantId)}/properties`;
|
|
1278
|
-
this.log(`Setting properties for user ${payload.userId} (attempt ${attempt + 1})`);
|
|
1279
1308
|
const response = await fetch(url, {
|
|
1280
1309
|
method: 'POST',
|
|
1281
1310
|
headers,
|
|
@@ -1520,7 +1549,6 @@ class GrainAnalytics {
|
|
|
1520
1549
|
try {
|
|
1521
1550
|
const headers = await this.getAuthHeaders();
|
|
1522
1551
|
const url = `${this.config.apiUrl}/v1/client/${encodeURIComponent(this.config.tenantId)}/config/configurations`;
|
|
1523
|
-
this.log(`Fetching configurations for user ${userId} (attempt ${attempt + 1})`);
|
|
1524
1552
|
const response = await fetch(url, {
|
|
1525
1553
|
method: 'POST',
|
|
1526
1554
|
headers,
|
|
@@ -1549,7 +1577,7 @@ class GrainAnalytics {
|
|
|
1549
1577
|
if (configResponse.configurations) {
|
|
1550
1578
|
this.updateConfigCache(configResponse, userId);
|
|
1551
1579
|
}
|
|
1552
|
-
this.log(
|
|
1580
|
+
this.log('Successfully fetched configurations');
|
|
1553
1581
|
return configResponse;
|
|
1554
1582
|
}
|
|
1555
1583
|
catch (error) {
|
|
@@ -1825,6 +1853,10 @@ class GrainAnalytics {
|
|
|
1825
1853
|
this.sectionTrackingManager.destroy();
|
|
1826
1854
|
this.sectionTrackingManager = null;
|
|
1827
1855
|
}
|
|
1856
|
+
if (this.heatmapTrackingManager) {
|
|
1857
|
+
this.heatmapTrackingManager.destroy();
|
|
1858
|
+
this.heatmapTrackingManager = null;
|
|
1859
|
+
}
|
|
1828
1860
|
// Send any remaining events (in chunks if necessary)
|
|
1829
1861
|
if (this.eventQueue.length > 0) {
|
|
1830
1862
|
const eventsToSend = [...this.eventQueue];
|
package/dist/index.mjs
CHANGED
|
@@ -34,6 +34,7 @@ export class GrainAnalytics {
|
|
|
34
34
|
// Auto-tracking properties
|
|
35
35
|
this.interactionTrackingManager = null;
|
|
36
36
|
this.sectionTrackingManager = null;
|
|
37
|
+
this.heatmapTrackingManager = null;
|
|
37
38
|
// Session tracking
|
|
38
39
|
this.sessionStartTime = Date.now();
|
|
39
40
|
this.sessionEventCount = 0;
|
|
@@ -63,6 +64,8 @@ export class GrainAnalytics {
|
|
|
63
64
|
heartbeatInactiveInterval: 300000, // 5 minutes
|
|
64
65
|
enableAutoPageView: true,
|
|
65
66
|
stripQueryParams: true,
|
|
67
|
+
// Heatmap Tracking defaults
|
|
68
|
+
enableHeatmapTracking: true,
|
|
66
69
|
...config,
|
|
67
70
|
tenantId: config.tenantId,
|
|
68
71
|
};
|
|
@@ -91,6 +94,10 @@ export class GrainAnalytics {
|
|
|
91
94
|
this.initializeAutomaticTracking();
|
|
92
95
|
// Track session start
|
|
93
96
|
this.trackSessionStart();
|
|
97
|
+
// Initialize heatmap tracking if enabled
|
|
98
|
+
if (this.config.enableHeatmapTracking) {
|
|
99
|
+
this.initializeHeatmapTracking();
|
|
100
|
+
}
|
|
94
101
|
}
|
|
95
102
|
// Set up consent change listener to flush waiting events and handle consent upgrade
|
|
96
103
|
this.consentManager.addListener((state) => {
|
|
@@ -340,6 +347,9 @@ export class GrainAnalytics {
|
|
|
340
347
|
* Log formatted error gracefully
|
|
341
348
|
*/
|
|
342
349
|
logError(formattedError) {
|
|
350
|
+
// Only log errors in debug mode to reduce noise in production
|
|
351
|
+
if (!this.config.debug)
|
|
352
|
+
return;
|
|
343
353
|
const { code, message, digest, timestamp, context } = formattedError;
|
|
344
354
|
const errorOutput = {
|
|
345
355
|
'🚨 Grain Analytics Error': {
|
|
@@ -357,10 +367,7 @@ export class GrainAnalytics {
|
|
|
357
367
|
}
|
|
358
368
|
};
|
|
359
369
|
console.error('🚨 Grain Analytics Error:', errorOutput);
|
|
360
|
-
|
|
361
|
-
if (this.config.debug) {
|
|
362
|
-
console.error(`[Grain Analytics] ${code}: ${message} (${context}) - Events: ${digest.eventCount}, Props: ${digest.totalProperties}, Size: ${digest.totalSize}B`);
|
|
363
|
-
}
|
|
370
|
+
console.error(`[Grain Analytics] ${code}: ${message} (${context}) - Events: ${digest.eventCount}, Props: ${digest.totalProperties}, Size: ${digest.totalSize}B`);
|
|
364
371
|
}
|
|
365
372
|
/**
|
|
366
373
|
* Safely execute a function with error handling
|
|
@@ -468,7 +475,6 @@ export class GrainAnalytics {
|
|
|
468
475
|
try {
|
|
469
476
|
const headers = await this.getAuthHeaders();
|
|
470
477
|
const url = `${this.config.apiUrl}/v1/events/${encodeURIComponent(this.config.tenantId)}/multi`;
|
|
471
|
-
this.log(`Sending ${events.length} events to ${url} (attempt ${attempt + 1})`);
|
|
472
478
|
const response = await fetch(url, {
|
|
473
479
|
method: 'POST',
|
|
474
480
|
headers,
|
|
@@ -541,7 +547,6 @@ export class GrainAnalytics {
|
|
|
541
547
|
body,
|
|
542
548
|
keepalive: true,
|
|
543
549
|
});
|
|
544
|
-
this.log(`Successfully sent ${events.length} events via fetch (keepalive)`);
|
|
545
550
|
}
|
|
546
551
|
catch (error) {
|
|
547
552
|
// Log error gracefully for beacon failures (page unload scenarios)
|
|
@@ -613,7 +618,6 @@ export class GrainAnalytics {
|
|
|
613
618
|
inactiveInterval: this.config.heartbeatInactiveInterval,
|
|
614
619
|
debug: this.config.debug,
|
|
615
620
|
});
|
|
616
|
-
this.log('Heartbeat tracking initialized');
|
|
617
621
|
}
|
|
618
622
|
catch (error) {
|
|
619
623
|
this.log('Failed to initialize heartbeat tracking:', error);
|
|
@@ -626,7 +630,6 @@ export class GrainAnalytics {
|
|
|
626
630
|
debug: this.config.debug,
|
|
627
631
|
tenantId: this.config.tenantId,
|
|
628
632
|
});
|
|
629
|
-
this.log('Auto page view tracking initialized');
|
|
630
633
|
}
|
|
631
634
|
catch (error) {
|
|
632
635
|
this.log('Failed to initialize page view tracking:', error);
|
|
@@ -635,12 +638,41 @@ export class GrainAnalytics {
|
|
|
635
638
|
// Initialize auto-tracking when config is available
|
|
636
639
|
this.initializeAutoTracking();
|
|
637
640
|
}
|
|
641
|
+
/**
|
|
642
|
+
* Initialize heatmap tracking
|
|
643
|
+
*/
|
|
644
|
+
initializeHeatmapTracking() {
|
|
645
|
+
if (typeof window === 'undefined')
|
|
646
|
+
return;
|
|
647
|
+
try {
|
|
648
|
+
this.log('Initializing heatmap tracking');
|
|
649
|
+
import('./heatmap-tracking').then(({ HeatmapTrackingManager }) => {
|
|
650
|
+
try {
|
|
651
|
+
this.heatmapTrackingManager = new HeatmapTrackingManager(this, {
|
|
652
|
+
scrollDebounceDelay: 100,
|
|
653
|
+
batchDelay: 2000,
|
|
654
|
+
maxBatchSize: 20,
|
|
655
|
+
debug: this.config.debug,
|
|
656
|
+
});
|
|
657
|
+
this.log('Heatmap tracking initialized');
|
|
658
|
+
}
|
|
659
|
+
catch (error) {
|
|
660
|
+
this.log('Failed to initialize heatmap tracking:', error);
|
|
661
|
+
}
|
|
662
|
+
}).catch((error) => {
|
|
663
|
+
this.log('Failed to load heatmap tracking module:', error);
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
catch (error) {
|
|
667
|
+
this.log('Failed to initialize heatmap tracking:', error);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
638
670
|
/**
|
|
639
671
|
* Initialize auto-tracking (interactions and sections)
|
|
640
672
|
*/
|
|
641
673
|
async initializeAutoTracking() {
|
|
642
674
|
try {
|
|
643
|
-
this.log('Initializing auto-tracking
|
|
675
|
+
this.log('Initializing auto-tracking');
|
|
644
676
|
// Fetch remote config to get auto-tracking configuration
|
|
645
677
|
const userId = this.globalUserId || this.persistentAnonymousUserId || this.generateUUID();
|
|
646
678
|
const currentUrl = typeof window !== 'undefined' ? window.location.href : '';
|
|
@@ -653,25 +685,20 @@ export class GrainAnalytics {
|
|
|
653
685
|
};
|
|
654
686
|
const headers = await this.getAuthHeaders();
|
|
655
687
|
const url = `${this.config.apiUrl}/v1/client/${encodeURIComponent(this.config.tenantId)}/config/configurations`;
|
|
656
|
-
this.log('Fetching auto-tracking config from:', url);
|
|
657
688
|
const response = await fetch(url, {
|
|
658
689
|
method: 'POST',
|
|
659
690
|
headers,
|
|
660
691
|
body: JSON.stringify(request),
|
|
661
692
|
});
|
|
662
693
|
if (!response.ok) {
|
|
663
|
-
this.log('Failed to fetch auto-tracking config:', response.status
|
|
694
|
+
this.log('Failed to fetch auto-tracking config:', response.status);
|
|
664
695
|
return;
|
|
665
696
|
}
|
|
666
697
|
const configResponse = await response.json();
|
|
667
|
-
this.log('Received config response:', configResponse);
|
|
668
698
|
if (configResponse.autoTrackingConfig) {
|
|
669
|
-
this.log('Auto-tracking config
|
|
699
|
+
this.log('Auto-tracking config loaded');
|
|
670
700
|
this.setupAutoTrackingManagers(configResponse.autoTrackingConfig);
|
|
671
701
|
}
|
|
672
|
-
else {
|
|
673
|
-
this.log('No auto-tracking config in response');
|
|
674
|
-
}
|
|
675
702
|
}
|
|
676
703
|
catch (error) {
|
|
677
704
|
this.log('Failed to initialize auto-tracking:', error);
|
|
@@ -682,10 +709,10 @@ export class GrainAnalytics {
|
|
|
682
709
|
* Setup auto-tracking managers
|
|
683
710
|
*/
|
|
684
711
|
setupAutoTrackingManagers(config) {
|
|
685
|
-
this.log('Setting up auto-tracking managers
|
|
712
|
+
this.log('Setting up auto-tracking managers');
|
|
686
713
|
// Lazy load the managers to avoid bundling them if not needed
|
|
687
714
|
if (config.interactions && config.interactions.length > 0) {
|
|
688
|
-
this.log('Loading interaction tracking
|
|
715
|
+
this.log('Loading interaction tracking:', config.interactions.length, 'interactions');
|
|
689
716
|
import('./interaction-tracking').then(({ InteractionTrackingManager }) => {
|
|
690
717
|
try {
|
|
691
718
|
this.interactionTrackingManager = new InteractionTrackingManager(this, config.interactions, {
|
|
@@ -693,20 +720,17 @@ export class GrainAnalytics {
|
|
|
693
720
|
enableMutationObserver: true,
|
|
694
721
|
mutationDebounceDelay: 500,
|
|
695
722
|
});
|
|
696
|
-
this.log('
|
|
723
|
+
this.log('Interaction tracking initialized');
|
|
697
724
|
}
|
|
698
725
|
catch (error) {
|
|
699
|
-
this.log('
|
|
726
|
+
this.log('Failed to initialize interaction tracking:', error);
|
|
700
727
|
}
|
|
701
728
|
}).catch((error) => {
|
|
702
|
-
this.log('
|
|
729
|
+
this.log('Failed to load interaction tracking module:', error);
|
|
703
730
|
});
|
|
704
731
|
}
|
|
705
|
-
else {
|
|
706
|
-
this.log('No interactions configured for auto-tracking');
|
|
707
|
-
}
|
|
708
732
|
if (config.sections && config.sections.length > 0) {
|
|
709
|
-
this.log('Loading section tracking
|
|
733
|
+
this.log('Loading section tracking:', config.sections.length, 'sections');
|
|
710
734
|
import('./section-tracking').then(({ SectionTrackingManager }) => {
|
|
711
735
|
try {
|
|
712
736
|
this.sectionTrackingManager = new SectionTrackingManager(this, config.sections, {
|
|
@@ -717,18 +741,15 @@ export class GrainAnalytics {
|
|
|
717
741
|
batchDelay: 2000,
|
|
718
742
|
debug: this.config.debug,
|
|
719
743
|
});
|
|
720
|
-
this.log('
|
|
744
|
+
this.log('Section tracking initialized');
|
|
721
745
|
}
|
|
722
746
|
catch (error) {
|
|
723
|
-
this.log('
|
|
747
|
+
this.log('Failed to initialize section tracking:', error);
|
|
724
748
|
}
|
|
725
749
|
}).catch((error) => {
|
|
726
|
-
this.log('
|
|
750
|
+
this.log('Failed to load section tracking module:', error);
|
|
727
751
|
});
|
|
728
752
|
}
|
|
729
|
-
else {
|
|
730
|
-
this.log('No sections configured for auto-tracking');
|
|
731
|
-
}
|
|
732
753
|
}
|
|
733
754
|
/**
|
|
734
755
|
* Track session start event
|
|
@@ -786,7 +807,7 @@ export class GrainAnalytics {
|
|
|
786
807
|
properties.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
787
808
|
}
|
|
788
809
|
this.trackSystemEvent('_grain_session_start', properties);
|
|
789
|
-
this.log('Session started
|
|
810
|
+
this.log('Session started');
|
|
790
811
|
}
|
|
791
812
|
/**
|
|
792
813
|
* Track session end event
|
|
@@ -809,7 +830,7 @@ export class GrainAnalytics {
|
|
|
809
830
|
properties.page_count = pageCount; // Keep for backward compatibility
|
|
810
831
|
}
|
|
811
832
|
this.trackSystemEvent('_grain_session_end', properties);
|
|
812
|
-
this.log('Session ended
|
|
833
|
+
this.log('Session ended');
|
|
813
834
|
}
|
|
814
835
|
/**
|
|
815
836
|
* Detect browser name
|
|
@@ -913,7 +934,7 @@ export class GrainAnalytics {
|
|
|
913
934
|
// Bypass consent check for necessary system events
|
|
914
935
|
this.eventQueue.push(event);
|
|
915
936
|
this.eventCountSinceLastHeartbeat++;
|
|
916
|
-
this.log(`Queued system event: ${eventName}
|
|
937
|
+
this.log(`Queued system event: ${eventName}`);
|
|
917
938
|
// Consider flushing
|
|
918
939
|
if (this.eventQueue.length >= this.config.batchSize) {
|
|
919
940
|
this.flush().catch((error) => {
|
|
@@ -949,6 +970,15 @@ export class GrainAnalytics {
|
|
|
949
970
|
resetEventCountSinceLastHeartbeat() {
|
|
950
971
|
this.eventCountSinceLastHeartbeat = 0;
|
|
951
972
|
}
|
|
973
|
+
/**
|
|
974
|
+
* Get the activity detector (for internal use by tracking managers)
|
|
975
|
+
*/
|
|
976
|
+
getActivityDetector() {
|
|
977
|
+
if (!this.activityDetector) {
|
|
978
|
+
throw new Error('Activity detector not initialized');
|
|
979
|
+
}
|
|
980
|
+
return this.activityDetector;
|
|
981
|
+
}
|
|
952
982
|
/**
|
|
953
983
|
* Get the effective user ID (public method)
|
|
954
984
|
*/
|
|
@@ -1008,7 +1038,7 @@ export class GrainAnalytics {
|
|
|
1008
1038
|
this.eventQueue.push(formattedEvent);
|
|
1009
1039
|
this.eventCountSinceLastHeartbeat++;
|
|
1010
1040
|
this.sessionEventCount++;
|
|
1011
|
-
this.log(`Queued event: ${event.eventName}
|
|
1041
|
+
this.log(`Queued event: ${event.eventName}`);
|
|
1012
1042
|
// Check if we should flush immediately
|
|
1013
1043
|
if (opts.flush || this.eventQueue.length >= this.config.batchSize) {
|
|
1014
1044
|
await this.flush();
|
|
@@ -1234,7 +1264,6 @@ export class GrainAnalytics {
|
|
|
1234
1264
|
try {
|
|
1235
1265
|
const headers = await this.getAuthHeaders();
|
|
1236
1266
|
const url = `${this.config.apiUrl}/v1/events/${encodeURIComponent(this.config.tenantId)}/properties`;
|
|
1237
|
-
this.log(`Setting properties for user ${payload.userId} (attempt ${attempt + 1})`);
|
|
1238
1267
|
const response = await fetch(url, {
|
|
1239
1268
|
method: 'POST',
|
|
1240
1269
|
headers,
|
|
@@ -1479,7 +1508,6 @@ export class GrainAnalytics {
|
|
|
1479
1508
|
try {
|
|
1480
1509
|
const headers = await this.getAuthHeaders();
|
|
1481
1510
|
const url = `${this.config.apiUrl}/v1/client/${encodeURIComponent(this.config.tenantId)}/config/configurations`;
|
|
1482
|
-
this.log(`Fetching configurations for user ${userId} (attempt ${attempt + 1})`);
|
|
1483
1511
|
const response = await fetch(url, {
|
|
1484
1512
|
method: 'POST',
|
|
1485
1513
|
headers,
|
|
@@ -1508,7 +1536,7 @@ export class GrainAnalytics {
|
|
|
1508
1536
|
if (configResponse.configurations) {
|
|
1509
1537
|
this.updateConfigCache(configResponse, userId);
|
|
1510
1538
|
}
|
|
1511
|
-
this.log(
|
|
1539
|
+
this.log('Successfully fetched configurations');
|
|
1512
1540
|
return configResponse;
|
|
1513
1541
|
}
|
|
1514
1542
|
catch (error) {
|
|
@@ -1784,6 +1812,10 @@ export class GrainAnalytics {
|
|
|
1784
1812
|
this.sectionTrackingManager.destroy();
|
|
1785
1813
|
this.sectionTrackingManager = null;
|
|
1786
1814
|
}
|
|
1815
|
+
if (this.heatmapTrackingManager) {
|
|
1816
|
+
this.heatmapTrackingManager.destroy();
|
|
1817
|
+
this.heatmapTrackingManager = null;
|
|
1818
|
+
}
|
|
1787
1819
|
// Send any remaining events (in chunks if necessary)
|
|
1788
1820
|
if (this.eventQueue.length > 0) {
|
|
1789
1821
|
const eventsToSend = [...this.eventQueue];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interaction-tracking.d.ts","sourceRoot":"","sources":["../src/interaction-tracking.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjH,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;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,qBAAa,0BAA0B;IACrC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAA6E;IACtG,OAAO,CAAC,UAAU,CAA0C;IAC5D,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,qBAAqB,CAAuB;gBAGlD,OAAO,EAAE,kBAAkB,EAC3B,YAAY,EAAE,iBAAiB,EAAE,EACjC,MAAM,GAAE,yBAA8B;IA0BxC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,yBAAyB;
|
|
1
|
+
{"version":3,"file":"interaction-tracking.d.ts","sourceRoot":"","sources":["../src/interaction-tracking.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjH,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;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,qBAAa,0BAA0B;IACrC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAA6E;IACtG,OAAO,CAAC,UAAU,CAA0C;IAC5D,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,qBAAqB,CAAuB;gBAGlD,OAAO,EAAE,kBAAkB,EAC3B,YAAY,EAAE,iBAAiB,EAAE,EACjC,MAAM,GAAE,yBAA8B;IA0BxC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAiCjC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAiC9B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAkB9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAyC1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA0B7B;;OAEG;IACH,OAAO,CAAC,eAAe;IA+BvB;;OAEG;IACH,OAAO,CAAC,eAAe;IAWvB;;OAEG;IACH,OAAO,CAAC,GAAG;IAMX;;OAEG;IACH,kBAAkB,CAAC,YAAY,EAAE,iBAAiB,EAAE,GAAG,IAAI;IAoB3D;;OAEG;IACH,OAAO,IAAI,IAAI;CA4BhB"}
|
|
@@ -40,7 +40,7 @@ class InteractionTrackingManager {
|
|
|
40
40
|
attachAllListeners() {
|
|
41
41
|
if (this.isDestroyed)
|
|
42
42
|
return;
|
|
43
|
-
this.log('Attaching interaction listeners
|
|
43
|
+
this.log('Attaching interaction listeners');
|
|
44
44
|
for (const interaction of this.interactions) {
|
|
45
45
|
this.attachInteractionListener(interaction);
|
|
46
46
|
}
|
|
@@ -73,7 +73,6 @@ class InteractionTrackingManager {
|
|
|
73
73
|
handlers.push({ event: 'focus', handler: focusHandler });
|
|
74
74
|
}
|
|
75
75
|
this.attachedListeners.set(element, handlers);
|
|
76
|
-
this.log('Attached listeners to element for:', interaction.eventName);
|
|
77
76
|
}
|
|
78
77
|
/**
|
|
79
78
|
* Handle click event on interaction
|
|
@@ -98,21 +97,15 @@ class InteractionTrackingManager {
|
|
|
98
97
|
...(isNavigationLink && { href: element.href }),
|
|
99
98
|
timestamp: Date.now(),
|
|
100
99
|
};
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
this.tracker.track(interaction.eventName, eventProperties);
|
|
100
|
+
// Always use flush for auto-tracked clicks to ensure delivery
|
|
101
|
+
// This is especially important for navigation links and quick interactions
|
|
102
|
+
const result = this.tracker.track(interaction.eventName, eventProperties, { flush: true });
|
|
103
|
+
if (result instanceof Promise) {
|
|
104
|
+
result.catch((error) => {
|
|
105
|
+
// Log error but don't block interaction
|
|
106
|
+
this.log('Failed to track click:', error);
|
|
107
|
+
});
|
|
114
108
|
}
|
|
115
|
-
this.log('Tracked click interaction:', interaction.eventName);
|
|
116
109
|
}
|
|
117
110
|
/**
|
|
118
111
|
* Handle focus event on interaction (for form fields)
|
|
@@ -133,7 +126,6 @@ class InteractionTrackingManager {
|
|
|
133
126
|
element_class: element.className || undefined,
|
|
134
127
|
timestamp: Date.now(),
|
|
135
128
|
});
|
|
136
|
-
this.log('Tracked focus interaction:', interaction.eventName);
|
|
137
129
|
}
|
|
138
130
|
/**
|
|
139
131
|
* Find element by XPath selector
|
|
@@ -233,7 +225,6 @@ class InteractionTrackingManager {
|
|
|
233
225
|
element.removeEventListener(event, handler);
|
|
234
226
|
});
|
|
235
227
|
this.attachedListeners.delete(element);
|
|
236
|
-
this.log('Detached listeners from element');
|
|
237
228
|
}
|
|
238
229
|
/**
|
|
239
230
|
* Log debug messages
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-tracking.d.ts","sourceRoot":"","sources":["../src/page-tracking.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/E,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,kBAAkB,IAAI,MAAM,CAAC;IAC7B,qBAAqB,IAAI,MAAM,CAAC;IAChC,YAAY,IAAI,MAAM,CAAC;CACxB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,iBAAiB,CAAyC;IAClE,OAAO,CAAC,oBAAoB,CAA4C;IACxE,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,aAAa,CAAK;gBAEd,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,kBAAkB;IAY5D;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAqB7B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAK/B;;OAEG;IACH,OAAO,CAAC,cAAc,CAGpB;IAEF;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAGtB;IAEF;;OAEG;IACH,OAAO,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"page-tracking.d.ts","sourceRoot":"","sources":["../src/page-tracking.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/E,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,kBAAkB,IAAI,MAAM,CAAC;IAC7B,qBAAqB,IAAI,MAAM,CAAC;IAChC,YAAY,IAAI,MAAM,CAAC;CACxB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,iBAAiB,CAAyC;IAClE,OAAO,CAAC,oBAAoB,CAA4C;IACxE,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,aAAa,CAAK;gBAEd,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,kBAAkB;IAY5D;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAqB7B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAK/B;;OAEG;IACH,OAAO,CAAC,cAAc,CAGpB;IAEF;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAGtB;IAEF;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA4GxB;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACH,OAAO,CAAC,KAAK;IAUb;;OAEG;IACH,OAAO,CAAC,aAAa;IAwBrB;;OAEG;IACH,OAAO,CAAC,WAAW;IAmBnB;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAqCnE;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,OAAO,IAAI,IAAI;CAqBhB"}
|