@grainql/analytics-web 2.2.0 → 2.3.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 (128) hide show
  1. package/dist/attribution.d.ts +47 -0
  2. package/dist/attribution.d.ts.map +1 -0
  3. package/dist/attribution.js +228 -0
  4. package/dist/cjs/attribution.d.ts +47 -0
  5. package/dist/cjs/attribution.d.ts.map +1 -0
  6. package/dist/cjs/attribution.js +228 -0
  7. package/dist/cjs/attribution.js.map +1 -0
  8. package/dist/cjs/heartbeat.d.ts +1 -0
  9. package/dist/cjs/heartbeat.d.ts.map +1 -1
  10. package/dist/cjs/heartbeat.js +1 -1
  11. package/dist/cjs/heartbeat.js.map +1 -1
  12. package/dist/cjs/index.d.ts +25 -0
  13. package/dist/cjs/index.d.ts.map +1 -1
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/page-tracking.d.ts +25 -0
  16. package/dist/cjs/page-tracking.d.ts.map +1 -1
  17. package/dist/cjs/page-tracking.js +158 -9
  18. package/dist/cjs/page-tracking.js.map +1 -1
  19. package/dist/esm/attribution.d.ts +47 -0
  20. package/dist/esm/attribution.d.ts.map +1 -0
  21. package/dist/esm/attribution.js +218 -0
  22. package/dist/esm/attribution.js.map +1 -0
  23. package/dist/esm/heartbeat.d.ts +1 -0
  24. package/dist/esm/heartbeat.d.ts.map +1 -1
  25. package/dist/esm/heartbeat.js +1 -1
  26. package/dist/esm/heartbeat.js.map +1 -1
  27. package/dist/esm/index.d.ts +25 -0
  28. package/dist/esm/index.d.ts.map +1 -1
  29. package/dist/esm/index.js.map +1 -1
  30. package/dist/esm/page-tracking.d.ts +25 -0
  31. package/dist/esm/page-tracking.d.ts.map +1 -1
  32. package/dist/esm/page-tracking.js +158 -9
  33. package/dist/esm/page-tracking.js.map +1 -1
  34. package/dist/heartbeat.d.ts +1 -0
  35. package/dist/heartbeat.d.ts.map +1 -1
  36. package/dist/heartbeat.js +1 -1
  37. package/dist/index.d.ts +25 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.global.dev.js +464 -11
  40. package/dist/index.global.dev.js.map +3 -3
  41. package/dist/index.global.js +2 -2
  42. package/dist/index.global.js.map +4 -4
  43. package/dist/index.js +157 -1
  44. package/dist/index.mjs +155 -0
  45. package/dist/page-tracking.d.ts +25 -0
  46. package/dist/page-tracking.d.ts.map +1 -1
  47. package/dist/page-tracking.js +158 -9
  48. package/dist/react/index.d.ts +44 -519
  49. package/dist/react/index.d.ts.map +1 -1
  50. package/dist/react/index.js +54 -1517
  51. package/dist/react/index.mjs +42 -1514
  52. package/package.json +1 -1
  53. package/dist/react/activity.d.ts +0 -59
  54. package/dist/react/activity.d.ts.map +0 -1
  55. package/dist/react/activity.js +0 -130
  56. package/dist/react/activity.mjs +0 -126
  57. package/dist/react/consent.d.ts +0 -72
  58. package/dist/react/consent.d.ts.map +0 -1
  59. package/dist/react/consent.js +0 -195
  60. package/dist/react/consent.mjs +0 -191
  61. package/dist/react/cookies.d.ts +0 -28
  62. package/dist/react/cookies.d.ts.map +0 -1
  63. package/dist/react/cookies.js +0 -94
  64. package/dist/react/cookies.mjs +0 -88
  65. package/dist/react/heartbeat.d.ts +0 -47
  66. package/dist/react/heartbeat.d.ts.map +0 -1
  67. package/dist/react/heartbeat.js +0 -119
  68. package/dist/react/heartbeat.mjs +0 -115
  69. package/dist/react/page-tracking.d.ts +0 -60
  70. package/dist/react/page-tracking.d.ts.map +0 -1
  71. package/dist/react/page-tracking.js +0 -179
  72. package/dist/react/page-tracking.mjs +0 -175
  73. package/dist/react/react/index.d.ts +0 -47
  74. package/dist/react/react/index.d.ts.map +0 -1
  75. package/dist/react/react/index.js +0 -58
  76. package/dist/react/react/index.mjs +0 -44
  77. /package/dist/react/{react/GrainProvider.d.ts → GrainProvider.d.ts} +0 -0
  78. /package/dist/react/{react/GrainProvider.d.ts.map → GrainProvider.d.ts.map} +0 -0
  79. /package/dist/react/{react/GrainProvider.js → GrainProvider.js} +0 -0
  80. /package/dist/react/{react/GrainProvider.mjs → GrainProvider.mjs} +0 -0
  81. /package/dist/react/{react/components → components}/ConsentBanner.d.ts +0 -0
  82. /package/dist/react/{react/components → components}/ConsentBanner.d.ts.map +0 -0
  83. /package/dist/react/{react/components → components}/ConsentBanner.js +0 -0
  84. /package/dist/react/{react/components → components}/ConsentBanner.mjs +0 -0
  85. /package/dist/react/{react/components → components}/CookieNotice.d.ts +0 -0
  86. /package/dist/react/{react/components → components}/CookieNotice.d.ts.map +0 -0
  87. /package/dist/react/{react/components → components}/CookieNotice.js +0 -0
  88. /package/dist/react/{react/components → components}/CookieNotice.mjs +0 -0
  89. /package/dist/react/{react/components → components}/PrivacyPreferenceCenter.d.ts +0 -0
  90. /package/dist/react/{react/components → components}/PrivacyPreferenceCenter.d.ts.map +0 -0
  91. /package/dist/react/{react/components → components}/PrivacyPreferenceCenter.js +0 -0
  92. /package/dist/react/{react/components → components}/PrivacyPreferenceCenter.mjs +0 -0
  93. /package/dist/react/{react/context.d.ts → context.d.ts} +0 -0
  94. /package/dist/react/{react/context.d.ts.map → context.d.ts.map} +0 -0
  95. /package/dist/react/{react/context.js → context.js} +0 -0
  96. /package/dist/react/{react/context.mjs → context.mjs} +0 -0
  97. /package/dist/react/{react/hooks → hooks}/useAllConfigs.d.ts +0 -0
  98. /package/dist/react/{react/hooks → hooks}/useAllConfigs.d.ts.map +0 -0
  99. /package/dist/react/{react/hooks → hooks}/useAllConfigs.js +0 -0
  100. /package/dist/react/{react/hooks → hooks}/useAllConfigs.mjs +0 -0
  101. /package/dist/react/{react/hooks → hooks}/useConfig.d.ts +0 -0
  102. /package/dist/react/{react/hooks → hooks}/useConfig.d.ts.map +0 -0
  103. /package/dist/react/{react/hooks → hooks}/useConfig.js +0 -0
  104. /package/dist/react/{react/hooks → hooks}/useConfig.mjs +0 -0
  105. /package/dist/react/{react/hooks → hooks}/useConsent.d.ts +0 -0
  106. /package/dist/react/{react/hooks → hooks}/useConsent.d.ts.map +0 -0
  107. /package/dist/react/{react/hooks → hooks}/useConsent.js +0 -0
  108. /package/dist/react/{react/hooks → hooks}/useConsent.mjs +0 -0
  109. /package/dist/react/{react/hooks → hooks}/useDataDeletion.d.ts +0 -0
  110. /package/dist/react/{react/hooks → hooks}/useDataDeletion.d.ts.map +0 -0
  111. /package/dist/react/{react/hooks → hooks}/useDataDeletion.js +0 -0
  112. /package/dist/react/{react/hooks → hooks}/useDataDeletion.mjs +0 -0
  113. /package/dist/react/{react/hooks → hooks}/useGrainAnalytics.d.ts +0 -0
  114. /package/dist/react/{react/hooks → hooks}/useGrainAnalytics.d.ts.map +0 -0
  115. /package/dist/react/{react/hooks → hooks}/useGrainAnalytics.js +0 -0
  116. /package/dist/react/{react/hooks → hooks}/useGrainAnalytics.mjs +0 -0
  117. /package/dist/react/{react/hooks → hooks}/usePrivacyPreferences.d.ts +0 -0
  118. /package/dist/react/{react/hooks → hooks}/usePrivacyPreferences.d.ts.map +0 -0
  119. /package/dist/react/{react/hooks → hooks}/usePrivacyPreferences.js +0 -0
  120. /package/dist/react/{react/hooks → hooks}/usePrivacyPreferences.mjs +0 -0
  121. /package/dist/react/{react/hooks → hooks}/useTrack.d.ts +0 -0
  122. /package/dist/react/{react/hooks → hooks}/useTrack.d.ts.map +0 -0
  123. /package/dist/react/{react/hooks → hooks}/useTrack.js +0 -0
  124. /package/dist/react/{react/hooks → hooks}/useTrack.mjs +0 -0
  125. /package/dist/react/{react/types.d.ts → types.d.ts} +0 -0
  126. /package/dist/react/{react/types.d.ts.map → types.d.ts.map} +0 -0
  127. /package/dist/react/{react/types.js → types.js} +0 -0
  128. /package/dist/react/{react/types.mjs → types.mjs} +0 -0
@@ -5,12 +5,16 @@
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.PageTrackingManager = void 0;
8
+ const attribution_1 = require("./attribution");
8
9
  class PageTrackingManager {
9
10
  constructor(tracker, config) {
10
11
  this.isDestroyed = false;
11
12
  this.currentPath = null;
12
13
  this.originalPushState = null;
13
14
  this.originalReplaceState = null;
15
+ this.previousPage = null;
16
+ this.landingPage = null;
17
+ this.pageViewCount = 0;
14
18
  /**
15
19
  * Handle popstate event (back/forward navigation)
16
20
  */
@@ -29,8 +33,8 @@ class PageTrackingManager {
29
33
  };
30
34
  this.tracker = tracker;
31
35
  this.config = config;
32
- // Track initial page load
33
- this.trackCurrentPage();
36
+ // Track initial page load (this is the landing page)
37
+ this.trackCurrentPage(true);
34
38
  // Setup listeners
35
39
  this.setupHistoryListeners();
36
40
  this.setupHashChangeListener();
@@ -67,16 +71,39 @@ class PageTrackingManager {
67
71
  /**
68
72
  * Track the current page
69
73
  */
70
- trackCurrentPage() {
74
+ trackCurrentPage(isLanding = false) {
71
75
  if (this.isDestroyed || typeof window === 'undefined')
72
76
  return;
73
77
  const page = this.extractPath(window.location.href);
74
- // Don't track if it's the same page
75
- if (page === this.currentPath) {
78
+ // Don't track if it's the same page (unless it's the landing page)
79
+ if (!isLanding && page === this.currentPath) {
76
80
  return;
77
81
  }
82
+ // Store previous page before updating
83
+ if (this.currentPath) {
84
+ this.previousPage = this.currentPath;
85
+ }
78
86
  this.currentPath = page;
87
+ this.pageViewCount++;
88
+ // Set landing page on first view
89
+ if (isLanding) {
90
+ this.landingPage = page;
91
+ }
79
92
  const hasConsent = this.tracker.hasConsent('analytics');
93
+ const currentUrl = window.location.href;
94
+ const referrer = document.referrer || '';
95
+ // Parse UTM parameters from current URL
96
+ const utmParams = (0, attribution_1.parseUTMParameters)(currentUrl);
97
+ // Store session UTM if they exist (first time only or if new UTMs appear)
98
+ if (Object.keys(utmParams).length > 0) {
99
+ const existing = (0, attribution_1.getSessionUTMParameters)();
100
+ if (!existing || isLanding) {
101
+ (0, attribution_1.setSessionUTMParameters)(utmParams);
102
+ }
103
+ }
104
+ // Get or create first-touch attribution
105
+ const sessionUTMs = (0, attribution_1.getSessionUTMParameters)() || {};
106
+ const firstTouch = (0, attribution_1.getOrCreateFirstTouchAttribution)(this.config.tenantId, referrer, currentUrl, sessionUTMs);
80
107
  // Base properties (always included)
81
108
  const properties = {
82
109
  page,
@@ -84,9 +111,47 @@ class PageTrackingManager {
84
111
  };
85
112
  // Enhanced properties when consent is granted
86
113
  if (hasConsent) {
87
- properties.referrer = document.referrer || '';
88
114
  properties.title = document.title || '';
89
- properties.full_url = window.location.href;
115
+ properties.full_url = currentUrl;
116
+ properties.session_id = this.tracker.getSessionId();
117
+ // Add referrer info
118
+ if (referrer) {
119
+ properties.referrer = referrer;
120
+ properties.referrer_domain = this.extractDomain(referrer);
121
+ properties.referrer_category = (0, attribution_1.categorizeReferrer)(referrer, currentUrl);
122
+ }
123
+ // Add landing page if this is not the first view
124
+ if (this.landingPage && !isLanding) {
125
+ properties.landing_page = this.landingPage;
126
+ }
127
+ // Add previous page if available
128
+ if (this.previousPage) {
129
+ properties.previous_page = this.previousPage;
130
+ }
131
+ // Add UTM parameters if present (from session)
132
+ if (sessionUTMs.utm_source)
133
+ properties.utm_source = sessionUTMs.utm_source;
134
+ if (sessionUTMs.utm_medium)
135
+ properties.utm_medium = sessionUTMs.utm_medium;
136
+ if (sessionUTMs.utm_campaign)
137
+ properties.utm_campaign = sessionUTMs.utm_campaign;
138
+ if (sessionUTMs.utm_term)
139
+ properties.utm_term = sessionUTMs.utm_term;
140
+ if (sessionUTMs.utm_content)
141
+ properties.utm_content = sessionUTMs.utm_content;
142
+ // Add first-touch attribution
143
+ properties.first_touch_source = firstTouch.source;
144
+ properties.first_touch_medium = firstTouch.medium;
145
+ properties.first_touch_campaign = firstTouch.campaign;
146
+ properties.first_touch_referrer_category = firstTouch.referrer_category;
147
+ // Browser and device info
148
+ properties.device = this.getDeviceType();
149
+ properties.browser = this.getBrowser();
150
+ properties.os = this.getOS();
151
+ properties.language = navigator.language || '';
152
+ properties.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
153
+ properties.screen_resolution = `${screen.width}x${screen.height}`;
154
+ properties.viewport = `${window.innerWidth}x${window.innerHeight}`;
90
155
  }
91
156
  // Track the page view event
92
157
  this.tracker.trackSystemEvent('page_view', properties);
@@ -94,6 +159,75 @@ class PageTrackingManager {
94
159
  console.log('[Page Tracking] Tracked page view:', properties);
95
160
  }
96
161
  }
162
+ /**
163
+ * Extract domain from URL
164
+ */
165
+ extractDomain(url) {
166
+ try {
167
+ const urlObj = new URL(url);
168
+ return urlObj.hostname;
169
+ }
170
+ catch {
171
+ return '';
172
+ }
173
+ }
174
+ /**
175
+ * Detect browser name
176
+ */
177
+ getBrowser() {
178
+ const ua = navigator.userAgent;
179
+ if (ua.includes('Firefox/'))
180
+ return 'Firefox';
181
+ if (ua.includes('Edg/'))
182
+ return 'Edge';
183
+ if (ua.includes('Chrome/'))
184
+ return 'Chrome';
185
+ if (ua.includes('Safari/') && !ua.includes('Chrome/'))
186
+ return 'Safari';
187
+ if (ua.includes('Opera/') || ua.includes('OPR/'))
188
+ return 'Opera';
189
+ return 'Unknown';
190
+ }
191
+ /**
192
+ * Detect operating system
193
+ */
194
+ getOS() {
195
+ const ua = navigator.userAgent;
196
+ if (ua.includes('Win'))
197
+ return 'Windows';
198
+ if (ua.includes('Mac'))
199
+ return 'macOS';
200
+ if (ua.includes('Linux'))
201
+ return 'Linux';
202
+ if (ua.includes('Android'))
203
+ return 'Android';
204
+ if (ua.includes('iOS') || ua.includes('iPhone') || ua.includes('iPad'))
205
+ return 'iOS';
206
+ return 'Unknown';
207
+ }
208
+ /**
209
+ * Detect device type (Mobile, Tablet, Desktop)
210
+ */
211
+ getDeviceType() {
212
+ const ua = navigator.userAgent;
213
+ const width = window.innerWidth;
214
+ // Check for tablet-specific indicators
215
+ if (ua.includes('iPad') || (ua.includes('Android') && !ua.includes('Mobile'))) {
216
+ return 'Tablet';
217
+ }
218
+ // Check for mobile indicators
219
+ if (ua.includes('Mobile') || ua.includes('iPhone') || ua.includes('Android')) {
220
+ return 'Mobile';
221
+ }
222
+ // Fallback to screen width detection
223
+ if (width < 768) {
224
+ return 'Mobile';
225
+ }
226
+ else if (width >= 768 && width < 1024) {
227
+ return 'Tablet';
228
+ }
229
+ return 'Desktop';
230
+ }
97
231
  /**
98
232
  * Extract path from URL, optionally stripping query parameters
99
233
  */
@@ -134,22 +268,37 @@ class PageTrackingManager {
134
268
  ...properties,
135
269
  };
136
270
  // Enhanced properties when consent is granted
137
- if (hasConsent && typeof document !== 'undefined') {
271
+ if (hasConsent && typeof document !== 'undefined' && typeof window !== 'undefined') {
138
272
  if (!baseProperties.referrer) {
139
273
  baseProperties.referrer = document.referrer || '';
140
274
  }
141
275
  if (!baseProperties.title) {
142
276
  baseProperties.title = document.title || '';
143
277
  }
144
- if (!baseProperties.full_url && typeof window !== 'undefined') {
278
+ if (!baseProperties.full_url) {
145
279
  baseProperties.full_url = window.location.href;
146
280
  }
281
+ if (!baseProperties.session_id) {
282
+ baseProperties.session_id = this.tracker.getSessionId();
283
+ }
284
+ if (!baseProperties.browser) {
285
+ baseProperties.browser = this.getBrowser();
286
+ }
287
+ if (!baseProperties.os) {
288
+ baseProperties.os = this.getOS();
289
+ }
147
290
  }
148
291
  this.tracker.trackSystemEvent('page_view', baseProperties);
149
292
  if (this.config.debug) {
150
293
  console.log('[Page Tracking] Manually tracked page:', baseProperties);
151
294
  }
152
295
  }
296
+ /**
297
+ * Get page view count for current session
298
+ */
299
+ getPageViewCount() {
300
+ return this.pageViewCount;
301
+ }
153
302
  /**
154
303
  * Destroy the page tracker
155
304
  */