@jmp-technologies/analytics 0.1.17 → 0.1.19
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/{chunk-3ELQETAA.js → chunk-EPNF76VK.js} +2 -2
- package/dist/{chunk-MUHLIN7P.js → chunk-GB37RVJJ.js} +339 -103
- package/dist/chunk-GB37RVJJ.js.map +1 -0
- package/dist/index.cjs +348 -104
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +112 -35
- package/dist/index.d.ts +112 -35
- package/dist/index.js +21 -5
- package/dist/next/content.cjs +322 -0
- package/dist/next/content.cjs.map +1 -0
- package/dist/next/content.d.cts +37 -0
- package/dist/next/content.d.ts +37 -0
- package/dist/next/content.js +172 -0
- package/dist/next/content.js.map +1 -0
- package/dist/next/instrumentation.cjs +131 -0
- package/dist/next/instrumentation.cjs.map +1 -0
- package/dist/next/instrumentation.d.cts +7 -0
- package/dist/next/instrumentation.d.ts +7 -0
- package/dist/next/instrumentation.js +18 -0
- package/dist/next/instrumentation.js.map +1 -0
- package/dist/next/middleware.cjs +147 -0
- package/dist/next/middleware.cjs.map +1 -0
- package/dist/next/middleware.d.cts +13 -0
- package/dist/next/middleware.d.ts +13 -0
- package/dist/next/middleware.js +22 -0
- package/dist/next/middleware.js.map +1 -0
- package/dist/next.cjs +322 -86
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +24 -8
- package/dist/next.d.ts +24 -8
- package/dist/next.js +41 -13
- package/dist/next.js.map +1 -1
- package/dist/react.cjs +279 -69
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +2 -2
- package/docs/legal-and-privacy.md +1 -0
- package/package.json +17 -2
- package/dist/chunk-MUHLIN7P.js.map +0 -1
- /package/dist/{chunk-3ELQETAA.js.map → chunk-EPNF76VK.js.map} +0 -0
package/dist/next.cjs
CHANGED
|
@@ -34,9 +34,13 @@ __export(next_exports, {
|
|
|
34
34
|
JmpLandingCaptureScript: () => JmpLandingCaptureScript,
|
|
35
35
|
JmpNextAnalytics: () => JmpNextAnalytics,
|
|
36
36
|
JmpNextPageViewTracker: () => JmpNextPageViewTracker,
|
|
37
|
+
JmpSiteRoot: () => JmpSiteRoot,
|
|
37
38
|
JmpTrackedMailtoLink: () => JmpTrackedMailtoLink,
|
|
38
39
|
JmpTrackedTelLink: () => JmpTrackedTelLink,
|
|
39
40
|
buildLandingCaptureInlineScript: () => buildLandingCaptureInlineScript,
|
|
41
|
+
isJmpTrackingConsentGranted: () => isJmpTrackingConsentGranted,
|
|
42
|
+
setJmpTrackingConsent: () => setJmpTrackingConsent,
|
|
43
|
+
subscribeJmpTrackingConsent: () => subscribeJmpTrackingConsent,
|
|
40
44
|
useJmpAnalytics: () => useJmpAnalytics
|
|
41
45
|
});
|
|
42
46
|
module.exports = __toCommonJS(next_exports);
|
|
@@ -49,7 +53,6 @@ var JMP_SESSION_ID_KEY = "jmp_analytics_sid";
|
|
|
49
53
|
var JMP_LANDING_REFERER_KEY = "jmp_analytics_landing_referer";
|
|
50
54
|
var JMP_LANDING_REFERER_COOKIE = "jmp_lr";
|
|
51
55
|
var JMP_UTM_SESSION_KEY = "jmp_analytics_utm";
|
|
52
|
-
var JMP_EARLY_BEACON_PATH_KEY = "jmp_analytics_early_beacon_path";
|
|
53
56
|
var LANDING_REFERER_COOKIE_MAX_AGE_SEC = 30 * 60;
|
|
54
57
|
var JMP_UTM_PARAM_KEYS = [
|
|
55
58
|
"utm_source",
|
|
@@ -182,84 +185,174 @@ function getOrCreateSessionIdFromStorage() {
|
|
|
182
185
|
return void 0;
|
|
183
186
|
}
|
|
184
187
|
}
|
|
185
|
-
function
|
|
186
|
-
|
|
187
|
-
|
|
188
|
+
function buildLandingCaptureInlineScript() {
|
|
189
|
+
const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC);
|
|
190
|
+
return `(function(){try{var h=location.hostname;var ref=document.referrer||'';function rh(u){try{return new URL(u).hostname.replace(/^www\\./i,'').toLowerCase()}catch(e){try{return new URL('https://'+u).hostname.replace(/^www\\./i,'').toLowerCase()}catch(e2){return null}}}function ext(r){var x=rh(r);if(!x)return false;var s=h.replace(/^www\\./i,'').toLowerCase();return x!==s&&x.slice(-('.'+s).length)!==('.'+s)}function apexDom(hn){var s=hn.replace(/^www\\./i,'').toLowerCase();if(!s||s==='localhost'||/\\.local$/i.test(s)||s.indexOf('.')<0)return null;return s}function readCk(hn){var apex=apexDom(hn);if(!apex)return '';var pre='${JMP_LANDING_REFERER_COOKIE}=';var parts=document.cookie.split(';');for(var i=0;i<parts.length;i++){var t=parts[i].trim();if(t.indexOf(pre)===0){try{return decodeURIComponent(t.slice(pre.length)).trim()}catch(e){return ''}}}return ''}function writeCk(r,hn){var apex=apexDom(hn);if(!apex)return;var sec=location.protocol==='https:'?'; Secure':'';document.cookie='${JMP_LANDING_REFERER_COOKIE}='+encodeURIComponent(r.slice(0,2048))+'; Domain=.'+apex+'; Path=/; Max-Age=${cookieMaxAge}; SameSite=Lax'+sec}var stored=sessionStorage.getItem('${JMP_LANDING_REFERER_KEY}')||'';var ck=readCk(h);var preserved=stored||ck;var lr='';if(ref&&ext(ref)){sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',ref);writeCk(ref,h);lr=ref}else{lr=preserved||'';if(lr&&!stored)sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',lr)}var sid=sessionStorage.getItem('${JMP_SESSION_ID_KEY}');if(!sid&&crypto&&crypto.randomUUID){sid=crypto.randomUUID();sessionStorage.setItem('${JMP_SESSION_ID_KEY}',sid)}try{var sp=new URLSearchParams(location.search);var utm={};var updated=false;['utm_source','utm_medium','utm_campaign','utm_content','utm_term'].forEach(function(n){var v=sp.get(n);if(v){utm[n]=v;updated=true}});if(updated)sessionStorage.setItem('${JMP_UTM_SESSION_KEY}',JSON.stringify(utm))}catch(e){}}catch(e){}})();`;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// src/contact-link-classifier.ts
|
|
194
|
+
var BOOKING_LINK_HOSTS = [
|
|
195
|
+
"calendly.com",
|
|
196
|
+
"cal.com",
|
|
197
|
+
"acuityscheduling.com",
|
|
198
|
+
"calendar.google.com",
|
|
199
|
+
"calendar.app.google",
|
|
200
|
+
"bookings.microsoft.com",
|
|
201
|
+
"outlook.office.com",
|
|
202
|
+
"outlook.office365.com",
|
|
203
|
+
"book.ms",
|
|
204
|
+
"setmore.com",
|
|
205
|
+
"simplybook.me",
|
|
206
|
+
"oncehub.com",
|
|
207
|
+
"scheduleonce.com",
|
|
208
|
+
"youcanbook.me",
|
|
209
|
+
"savvycal.com",
|
|
210
|
+
"tidycal.com",
|
|
211
|
+
"zohobookings.com",
|
|
212
|
+
"square.site",
|
|
213
|
+
"squareup.com",
|
|
214
|
+
"meetings.hubspot.com",
|
|
215
|
+
"jobber.com",
|
|
216
|
+
"housecallpro.com",
|
|
217
|
+
"servicetitan.com",
|
|
218
|
+
"thryv.com",
|
|
219
|
+
"honeybook.com",
|
|
220
|
+
"dubsado.com",
|
|
221
|
+
"fresha.com",
|
|
222
|
+
"booksy.com",
|
|
223
|
+
"vagaro.com",
|
|
224
|
+
"mindbodyonline.com",
|
|
225
|
+
"mindbody.io",
|
|
226
|
+
"janeapp.com",
|
|
227
|
+
"cliniko.com",
|
|
228
|
+
"practicebetter.io"
|
|
229
|
+
];
|
|
230
|
+
var WHATSAPP_HOSTS = ["wa.me", "api.whatsapp.com", "whatsapp.com"];
|
|
231
|
+
function hostnameMatches(host, pattern) {
|
|
232
|
+
const h = host.toLowerCase();
|
|
233
|
+
const p = pattern.toLowerCase();
|
|
234
|
+
return h === p || h.endsWith(`.${p}`);
|
|
235
|
+
}
|
|
236
|
+
function isMapsHost(host, pathname) {
|
|
237
|
+
if (hostnameMatches(host, "maps.apple.com")) {
|
|
238
|
+
return true;
|
|
188
239
|
}
|
|
189
|
-
|
|
190
|
-
return
|
|
191
|
-
} catch {
|
|
192
|
-
return false;
|
|
240
|
+
if (hostnameMatches(host, "maps.app.goo.gl")) {
|
|
241
|
+
return true;
|
|
193
242
|
}
|
|
243
|
+
if (hostnameMatches(host, "google.com") || hostnameMatches(host, "google.co")) {
|
|
244
|
+
return pathname === "/maps" || pathname.startsWith("/maps/") || pathname.startsWith("/local");
|
|
245
|
+
}
|
|
246
|
+
return false;
|
|
194
247
|
}
|
|
195
|
-
function
|
|
196
|
-
|
|
197
|
-
|
|
248
|
+
function isWhatsAppHost(host, pathname) {
|
|
249
|
+
for (const pattern of WHATSAPP_HOSTS) {
|
|
250
|
+
if (!hostnameMatches(host, pattern)) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (pattern === "whatsapp.com") {
|
|
254
|
+
return pathname.startsWith("/send");
|
|
255
|
+
}
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
function isBookingHost(host) {
|
|
261
|
+
for (const pattern of BOOKING_LINK_HOSTS) {
|
|
262
|
+
if (hostnameMatches(host, pattern)) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
function classifyContactHref(href) {
|
|
269
|
+
const raw = href.trim();
|
|
270
|
+
if (!raw || raw.startsWith("#") || raw.startsWith("javascript:")) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
const lower = raw.toLowerCase();
|
|
274
|
+
if (lower.startsWith("tel:")) {
|
|
275
|
+
return { kind: "call" };
|
|
276
|
+
}
|
|
277
|
+
if (lower.startsWith("mailto:")) {
|
|
278
|
+
return { kind: "email" };
|
|
279
|
+
}
|
|
280
|
+
if (lower.startsWith("sms:") || lower.startsWith("smsto:")) {
|
|
281
|
+
return { kind: "contact_click", channel: "sms", linkHost: null };
|
|
282
|
+
}
|
|
283
|
+
if (lower.startsWith("geo:")) {
|
|
284
|
+
return { kind: "contact_click", channel: "maps", linkHost: null };
|
|
285
|
+
}
|
|
286
|
+
if (raw.startsWith("/") || raw.startsWith("?")) {
|
|
287
|
+
return null;
|
|
198
288
|
}
|
|
289
|
+
let url;
|
|
199
290
|
try {
|
|
200
|
-
|
|
291
|
+
url = new URL(raw);
|
|
201
292
|
} catch {
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
const host = url.hostname.toLowerCase();
|
|
299
|
+
const pathname = url.pathname.toLowerCase();
|
|
300
|
+
if (isWhatsAppHost(host, pathname)) {
|
|
301
|
+
return { kind: "contact_click", channel: "whatsapp", linkHost: host };
|
|
202
302
|
}
|
|
303
|
+
if (isMapsHost(host, pathname)) {
|
|
304
|
+
return { kind: "contact_click", channel: "maps", linkHost: host };
|
|
305
|
+
}
|
|
306
|
+
if (isBookingHost(host)) {
|
|
307
|
+
return { kind: "contact_click", channel: "booking", linkHost: host };
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
203
310
|
}
|
|
204
|
-
|
|
205
|
-
|
|
311
|
+
|
|
312
|
+
// src/index.ts
|
|
313
|
+
var JMP_TRACKING_CONSENT_STORAGE_KEY = "jmp_analytics_consent_v1";
|
|
314
|
+
var moduleTrackingConsentGranted = true;
|
|
315
|
+
var trackingConsentListeners = /* @__PURE__ */ new Set();
|
|
316
|
+
function readStoredTrackingConsent() {
|
|
317
|
+
if (typeof window === "undefined") {
|
|
206
318
|
return false;
|
|
207
319
|
}
|
|
208
|
-
|
|
209
|
-
|
|
320
|
+
try {
|
|
321
|
+
return localStorage.getItem(JMP_TRACKING_CONSENT_STORAGE_KEY) === "granted";
|
|
322
|
+
} catch {
|
|
210
323
|
return false;
|
|
211
324
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
metadata.referer = landingReferer;
|
|
221
|
-
}
|
|
222
|
-
const payload = {
|
|
223
|
-
type: "page_view",
|
|
224
|
-
path,
|
|
225
|
-
trackingKey: args.trackingKey,
|
|
226
|
-
...sessionId ? { sessionId } : {},
|
|
227
|
-
metadata
|
|
228
|
-
};
|
|
229
|
-
const headers = {
|
|
230
|
-
"Content-Type": "application/json",
|
|
231
|
-
"X-JMP-Tracking-Key": args.trackingKey
|
|
325
|
+
}
|
|
326
|
+
function isJmpTrackingConsentGranted() {
|
|
327
|
+
return moduleTrackingConsentGranted;
|
|
328
|
+
}
|
|
329
|
+
function subscribeJmpTrackingConsent(listener) {
|
|
330
|
+
trackingConsentListeners.add(listener);
|
|
331
|
+
return () => {
|
|
332
|
+
trackingConsentListeners.delete(listener);
|
|
232
333
|
};
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
body: JSON.stringify(payload),
|
|
241
|
-
keepalive: true,
|
|
242
|
-
mode: "cors",
|
|
243
|
-
credentials: "omit"
|
|
244
|
-
}).catch(() => {
|
|
334
|
+
}
|
|
335
|
+
function setJmpTrackingConsent(granted) {
|
|
336
|
+
if (moduleTrackingConsentGranted === granted) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
moduleTrackingConsentGranted = granted;
|
|
340
|
+
if (typeof window !== "undefined") {
|
|
245
341
|
try {
|
|
246
|
-
|
|
342
|
+
localStorage.setItem(
|
|
343
|
+
JMP_TRACKING_CONSENT_STORAGE_KEY,
|
|
344
|
+
granted ? "granted" : "denied"
|
|
345
|
+
);
|
|
247
346
|
} catch {
|
|
248
347
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const baseUrl = escapeInlineScript(args.baseUrl.replace(/\/$/, ""));
|
|
257
|
-
const trackingKey = escapeInlineScript(args.trackingKey);
|
|
258
|
-
const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC);
|
|
259
|
-
return `(function(){try{var k='${trackingKey}',b='${baseUrl}';if(!k||!b)return;var p=location.pathname+location.search||'/';var sentKey='${JMP_EARLY_BEACON_PATH_KEY}';if(sessionStorage.getItem(sentKey)===p)return;var h=location.hostname;var ref=document.referrer||'';function rh(u){try{return new URL(u).hostname.replace(/^www\\./i,'').toLowerCase()}catch(e){try{return new URL('https://'+u).hostname.replace(/^www\\./i,'').toLowerCase()}catch(e2){return null}}}function ext(r){var x=rh(r);if(!x)return false;var s=h.replace(/^www\\./i,'').toLowerCase();return x!==s&&x.slice(-('.'+s).length)!==('.'+s)}function apexDom(hn){var s=hn.replace(/^www\\./i,'').toLowerCase();if(!s||s==='localhost'||/\\.local$/i.test(s)||s.indexOf('.')<0)return null;return s}function readCk(hn){var apex=apexDom(hn);if(!apex)return '';var pre='${JMP_LANDING_REFERER_COOKIE}=';var parts=document.cookie.split(';');for(var i=0;i<parts.length;i++){var t=parts[i].trim();if(t.indexOf(pre)===0){try{return decodeURIComponent(t.slice(pre.length)).trim()}catch(e){return ''}}}return ''}function writeCk(r,hn){var apex=apexDom(hn);if(!apex)return;var sec=location.protocol==='https:'?'; Secure':'';document.cookie='${JMP_LANDING_REFERER_COOKIE}='+encodeURIComponent(r.slice(0,2048))+'; Domain=.'+apex+'; Path=/; Max-Age=${cookieMaxAge}; SameSite=Lax'+sec}var stored=sessionStorage.getItem('${JMP_LANDING_REFERER_KEY}')||'';var ck=readCk(h);var preserved=stored||ck;var lr='';if(ref&&ext(ref)){sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',ref);writeCk(ref,h);lr=ref}else{lr=preserved||'';if(lr&&!stored)sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',lr)}var sid=sessionStorage.getItem('${JMP_SESSION_ID_KEY}');if(!sid&&crypto&&crypto.randomUUID){sid=crypto.randomUUID();sessionStorage.setItem('${JMP_SESSION_ID_KEY}',sid)}var md={pageHostname:h,earlyBeacon:true};try{var sp=new URLSearchParams(location.search);['utm_source','utm_medium','utm_campaign','utm_content','utm_term'].forEach(function(n){var v=sp.get(n);if(v)md[n]=v})}catch(e){}if(lr)md.referer=lr;var body=JSON.stringify({type:'page_view',path:p,trackingKey:k,sessionId:sid||undefined,metadata:md});var hd={'Content-Type':'application/json','X-JMP-Tracking-Key':k};if(lr)hd['X-JMP-Visitor-Referer']=lr;sessionStorage.setItem(sentKey,p);fetch(b+'/api/events',{method:'POST',headers:hd,body:body,keepalive:true,mode:'cors',credentials:'omit'}).catch(function(){sessionStorage.removeItem(sentKey)})}catch(e){}})();`;
|
|
348
|
+
if (granted) {
|
|
349
|
+
captureLandingAttribution(window.location.hostname);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
for (const listener of trackingConsentListeners) {
|
|
353
|
+
listener();
|
|
354
|
+
}
|
|
260
355
|
}
|
|
261
|
-
|
|
262
|
-
// src/index.ts
|
|
263
356
|
function captureAndGetLandingReferer() {
|
|
264
357
|
if (typeof window === "undefined") {
|
|
265
358
|
return null;
|
|
@@ -309,9 +402,16 @@ function createJmpAnalytics(config) {
|
|
|
309
402
|
);
|
|
310
403
|
}
|
|
311
404
|
const fetchFn = resolvedFetch;
|
|
405
|
+
moduleTrackingConsentGranted = config.requireConsent ? readStoredTrackingConsent() : true;
|
|
406
|
+
function canSend() {
|
|
407
|
+
return moduleTrackingConsentGranted;
|
|
408
|
+
}
|
|
312
409
|
let lastDedupePath = "";
|
|
313
410
|
let lastDedupeAt = 0;
|
|
314
411
|
async function send(body) {
|
|
412
|
+
if (!canSend()) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
315
415
|
const url = `${baseUrl}/api/events`;
|
|
316
416
|
const headers = {
|
|
317
417
|
"Content-Type": "application/json",
|
|
@@ -367,6 +467,9 @@ function createJmpAnalytics(config) {
|
|
|
367
467
|
}
|
|
368
468
|
}
|
|
369
469
|
async function sendLead(body) {
|
|
470
|
+
if (!canSend()) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
370
473
|
const url = `${baseUrl}/api/leads`;
|
|
371
474
|
const headers = {
|
|
372
475
|
"Content-Type": "application/json",
|
|
@@ -429,6 +532,9 @@ function createJmpAnalytics(config) {
|
|
|
429
532
|
return false;
|
|
430
533
|
}
|
|
431
534
|
function trackPageView(options) {
|
|
535
|
+
if (!canSend()) {
|
|
536
|
+
return Promise.resolve();
|
|
537
|
+
}
|
|
432
538
|
const pathFromOptions = options?.path?.trim();
|
|
433
539
|
let pathname = "/";
|
|
434
540
|
let search = "";
|
|
@@ -444,9 +550,6 @@ function createJmpAnalytics(config) {
|
|
|
444
550
|
search = window.location.search.replace(/^\?/, "");
|
|
445
551
|
}
|
|
446
552
|
const path = search ? `${pathname}?${search}` : pathname;
|
|
447
|
-
if (wasEarlyBeaconSentForPath(path)) {
|
|
448
|
-
return Promise.resolve();
|
|
449
|
-
}
|
|
450
553
|
if (shouldDedupePageView(pathname)) {
|
|
451
554
|
return Promise.resolve();
|
|
452
555
|
}
|
|
@@ -497,6 +600,20 @@ function createJmpAnalytics(config) {
|
|
|
497
600
|
metadata: metadata ?? {}
|
|
498
601
|
});
|
|
499
602
|
}
|
|
603
|
+
function trackContactClick(path, options) {
|
|
604
|
+
const metadata = {
|
|
605
|
+
...options.metadata && typeof options.metadata === "object" ? options.metadata : {},
|
|
606
|
+
channel: options.channel
|
|
607
|
+
};
|
|
608
|
+
if (options.linkHost) {
|
|
609
|
+
metadata.linkHost = options.linkHost;
|
|
610
|
+
}
|
|
611
|
+
return send({
|
|
612
|
+
type: "contact_click",
|
|
613
|
+
path: path || "/",
|
|
614
|
+
metadata
|
|
615
|
+
});
|
|
616
|
+
}
|
|
500
617
|
function trackLead(options) {
|
|
501
618
|
const path = options?.path ?? (typeof window !== "undefined" ? window.location.pathname : "/");
|
|
502
619
|
const body = { path: path || "/" };
|
|
@@ -529,7 +646,20 @@ function createJmpAnalytics(config) {
|
|
|
529
646
|
if (type === "call_click") {
|
|
530
647
|
return trackCallClick(payload.path, payload.metadata);
|
|
531
648
|
}
|
|
532
|
-
|
|
649
|
+
if (type === "email_click") {
|
|
650
|
+
return trackEmailClick(payload.path, payload.metadata);
|
|
651
|
+
}
|
|
652
|
+
const meta = payload.metadata ?? {};
|
|
653
|
+
const channel = typeof meta.channel === "string" ? meta.channel : "";
|
|
654
|
+
const linkHost = typeof meta.linkHost === "string" ? meta.linkHost : null;
|
|
655
|
+
if (channel !== "sms" && channel !== "whatsapp" && channel !== "maps" && channel !== "booking") {
|
|
656
|
+
return Promise.resolve();
|
|
657
|
+
}
|
|
658
|
+
return trackContactClick(payload.path, {
|
|
659
|
+
channel,
|
|
660
|
+
linkHost,
|
|
661
|
+
metadata: meta
|
|
662
|
+
});
|
|
533
663
|
}
|
|
534
664
|
function subscribeToSpaNavigation() {
|
|
535
665
|
if (typeof window === "undefined") {
|
|
@@ -563,12 +693,75 @@ function createJmpAnalytics(config) {
|
|
|
563
693
|
history.replaceState = replace;
|
|
564
694
|
};
|
|
565
695
|
}
|
|
566
|
-
|
|
696
|
+
let lastContactClickKey = "";
|
|
697
|
+
let lastContactClickAt = 0;
|
|
698
|
+
function subscribeContactLinkAutoTrack() {
|
|
699
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
700
|
+
return () => {
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
const handler = (event) => {
|
|
704
|
+
if (!canSend()) {
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
const target = event.target;
|
|
708
|
+
if (!(target instanceof Element)) {
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
const anchor = target.closest("a[href]");
|
|
712
|
+
if (!(anchor instanceof HTMLAnchorElement)) {
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (anchor.closest("[data-jmp-no-track]")) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
const href = anchor.getAttribute("href") ?? "";
|
|
719
|
+
const classified = classifyContactHref(href);
|
|
720
|
+
if (!classified) {
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
const path = window.location.pathname;
|
|
724
|
+
if (classified.kind === "call") {
|
|
725
|
+
if (dedupeContactClick(`call_click:${path}`)) {
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
void trackCallClick(path);
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
if (classified.kind === "email") {
|
|
732
|
+
if (dedupeContactClick(`email_click:${path}`)) {
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
void trackEmailClick(path);
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
if (dedupeContactClick(`contact_click:${classified.channel}:${path}`)) {
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
void trackContactClick(path, {
|
|
742
|
+
channel: classified.channel,
|
|
743
|
+
linkHost: classified.linkHost
|
|
744
|
+
});
|
|
745
|
+
};
|
|
746
|
+
document.addEventListener("click", handler, { capture: true });
|
|
747
|
+
return () => {
|
|
748
|
+
document.removeEventListener("click", handler, { capture: true });
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
function dedupeContactClick(key) {
|
|
752
|
+
const now = Date.now();
|
|
753
|
+
if (key === lastContactClickKey && now - lastContactClickAt < 1e3) {
|
|
754
|
+
return true;
|
|
755
|
+
}
|
|
756
|
+
lastContactClickKey = key;
|
|
757
|
+
lastContactClickAt = now;
|
|
758
|
+
return false;
|
|
759
|
+
}
|
|
760
|
+
if (typeof window !== "undefined" && canSend()) {
|
|
567
761
|
captureLandingAttribution(window.location.hostname);
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
});
|
|
762
|
+
}
|
|
763
|
+
if (typeof window !== "undefined" && config.autoTrackContactLinks && canSend()) {
|
|
764
|
+
subscribeContactLinkAutoTrack();
|
|
572
765
|
}
|
|
573
766
|
return {
|
|
574
767
|
track,
|
|
@@ -576,25 +769,47 @@ function createJmpAnalytics(config) {
|
|
|
576
769
|
trackFormSubmit,
|
|
577
770
|
trackCallClick,
|
|
578
771
|
trackEmailClick,
|
|
772
|
+
trackContactClick,
|
|
579
773
|
trackLead,
|
|
580
|
-
subscribeToSpaNavigation
|
|
774
|
+
subscribeToSpaNavigation,
|
|
775
|
+
subscribeContactLinkAutoTrack,
|
|
776
|
+
setTrackingConsent: setJmpTrackingConsent,
|
|
777
|
+
isTrackingConsentGranted: isJmpTrackingConsentGranted
|
|
581
778
|
};
|
|
582
779
|
}
|
|
583
780
|
var DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 800;
|
|
584
|
-
function
|
|
781
|
+
function readNextPublicEnv(key) {
|
|
585
782
|
if (typeof process === "undefined" || !process.env) return void 0;
|
|
586
|
-
|
|
783
|
+
let v;
|
|
784
|
+
switch (key) {
|
|
785
|
+
case "NEXT_PUBLIC_JMP_ANALYTICS_URL":
|
|
786
|
+
v = process.env.NEXT_PUBLIC_JMP_ANALYTICS_URL;
|
|
787
|
+
break;
|
|
788
|
+
case "NEXT_PUBLIC_JMP_TRACKING_KEY":
|
|
789
|
+
v = process.env.NEXT_PUBLIC_JMP_TRACKING_KEY;
|
|
790
|
+
break;
|
|
791
|
+
case "NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT":
|
|
792
|
+
v = process.env.NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT;
|
|
793
|
+
break;
|
|
794
|
+
case "NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS":
|
|
795
|
+
v = process.env.NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS;
|
|
796
|
+
break;
|
|
797
|
+
}
|
|
587
798
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
588
799
|
}
|
|
589
800
|
function getJmpBrowserAnalyticsConfigFromEnv(overrides) {
|
|
590
|
-
const baseUrl =
|
|
591
|
-
const trackingKey =
|
|
801
|
+
const baseUrl = readNextPublicEnv("NEXT_PUBLIC_JMP_ANALYTICS_URL");
|
|
802
|
+
const trackingKey = readNextPublicEnv("NEXT_PUBLIC_JMP_TRACKING_KEY");
|
|
592
803
|
if (!baseUrl || !trackingKey) return null;
|
|
804
|
+
const requireConsentFromEnv = readNextPublicEnv("NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT") === "true";
|
|
805
|
+
const autoTrackContactLinksFromEnv = readNextPublicEnv("NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS") === "true";
|
|
593
806
|
return {
|
|
594
807
|
baseUrl,
|
|
595
808
|
trackingKey,
|
|
596
809
|
pageViewDedupeMs: DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
|
|
597
|
-
...overrides
|
|
810
|
+
...overrides,
|
|
811
|
+
requireConsent: overrides?.requireConsent ?? requireConsentFromEnv,
|
|
812
|
+
autoTrackContactLinks: overrides?.autoTrackContactLinks ?? autoTrackContactLinksFromEnv
|
|
598
813
|
};
|
|
599
814
|
}
|
|
600
815
|
var jmpAnalyticsBrowserSingleton = null;
|
|
@@ -655,12 +870,9 @@ function JmpTrackedMailtoLink({
|
|
|
655
870
|
// src/next.tsx
|
|
656
871
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
657
872
|
function JmpLandingCaptureScript({
|
|
658
|
-
baseUrl = process.env.NEXT_PUBLIC_JMP_ANALYTICS_URL,
|
|
659
873
|
trackingKey = process.env.NEXT_PUBLIC_JMP_TRACKING_KEY
|
|
660
874
|
} = {}) {
|
|
661
|
-
|
|
662
|
-
const resolvedKey = trackingKey?.trim();
|
|
663
|
-
if (!resolvedBase || !resolvedKey) {
|
|
875
|
+
if (!trackingKey?.trim()) {
|
|
664
876
|
return null;
|
|
665
877
|
}
|
|
666
878
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -669,10 +881,7 @@ function JmpLandingCaptureScript({
|
|
|
669
881
|
id: "jmp-landing-capture",
|
|
670
882
|
strategy: "beforeInteractive",
|
|
671
883
|
dangerouslySetInnerHTML: {
|
|
672
|
-
__html: buildLandingCaptureInlineScript(
|
|
673
|
-
baseUrl: resolvedBase,
|
|
674
|
-
trackingKey: resolvedKey
|
|
675
|
-
})
|
|
884
|
+
__html: buildLandingCaptureInlineScript()
|
|
676
885
|
}
|
|
677
886
|
}
|
|
678
887
|
);
|
|
@@ -691,20 +900,47 @@ function JmpNextPageViewTrackerInner() {
|
|
|
691
900
|
function JmpNextPageViewTracker() {
|
|
692
901
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react2.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(JmpNextPageViewTrackerInner, {}) });
|
|
693
902
|
}
|
|
694
|
-
function
|
|
903
|
+
function useJmpTrackingActive(deferUntilConsent) {
|
|
904
|
+
const consentGranted = (0, import_react2.useSyncExternalStore)(
|
|
905
|
+
subscribeJmpTrackingConsent,
|
|
906
|
+
() => isJmpTrackingConsentGranted(),
|
|
907
|
+
() => false
|
|
908
|
+
);
|
|
909
|
+
return !deferUntilConsent || consentGranted;
|
|
910
|
+
}
|
|
911
|
+
function JmpNextAnalytics({
|
|
912
|
+
deferUntilConsent = process.env.NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT === "true"
|
|
913
|
+
} = {}) {
|
|
914
|
+
const active = useJmpTrackingActive(deferUntilConsent);
|
|
915
|
+
if (!active) {
|
|
916
|
+
return null;
|
|
917
|
+
}
|
|
695
918
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
696
919
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(JmpLandingCaptureScript, {}),
|
|
697
920
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(JmpNextPageViewTracker, {})
|
|
698
921
|
] });
|
|
699
922
|
}
|
|
923
|
+
function JmpSiteRoot({
|
|
924
|
+
children,
|
|
925
|
+
deferUntilConsent
|
|
926
|
+
}) {
|
|
927
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
928
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(JmpNextAnalytics, { deferUntilConsent }),
|
|
929
|
+
children
|
|
930
|
+
] });
|
|
931
|
+
}
|
|
700
932
|
// Annotate the CommonJS export names for ESM import in node:
|
|
701
933
|
0 && (module.exports = {
|
|
702
934
|
JmpLandingCaptureScript,
|
|
703
935
|
JmpNextAnalytics,
|
|
704
936
|
JmpNextPageViewTracker,
|
|
937
|
+
JmpSiteRoot,
|
|
705
938
|
JmpTrackedMailtoLink,
|
|
706
939
|
JmpTrackedTelLink,
|
|
707
940
|
buildLandingCaptureInlineScript,
|
|
941
|
+
isJmpTrackingConsentGranted,
|
|
942
|
+
setJmpTrackingConsent,
|
|
943
|
+
subscribeJmpTrackingConsent,
|
|
708
944
|
useJmpAnalytics
|
|
709
945
|
});
|
|
710
946
|
//# sourceMappingURL=next.cjs.map
|