@jmp-technologies/analytics 0.1.16 → 0.1.18
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-AEQGPTDY.js → chunk-SOHYQ5GT.js} +284 -79
- package/dist/chunk-SOHYQ5GT.js.map +1 -0
- package/dist/{chunk-P4IKTSPX.js → chunk-W7CQ5VG2.js} +2 -2
- package/dist/index.cjs +290 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +70 -14
- package/dist/index.d.ts +70 -14
- package/dist/index.js +15 -3
- package/dist/next.cjs +295 -86
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +13 -6
- package/dist/next.d.ts +13 -6
- package/dist/next.js +27 -13
- package/dist/next.js.map +1 -1
- package/dist/react.cjs +263 -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 +1 -1
- package/dist/chunk-AEQGPTDY.js.map +0 -1
- /package/dist/{chunk-P4IKTSPX.js.map → chunk-W7CQ5VG2.js.map} +0 -0
package/dist/next.cjs
CHANGED
|
@@ -37,6 +37,9 @@ __export(next_exports, {
|
|
|
37
37
|
JmpTrackedMailtoLink: () => JmpTrackedMailtoLink,
|
|
38
38
|
JmpTrackedTelLink: () => JmpTrackedTelLink,
|
|
39
39
|
buildLandingCaptureInlineScript: () => buildLandingCaptureInlineScript,
|
|
40
|
+
isJmpTrackingConsentGranted: () => isJmpTrackingConsentGranted,
|
|
41
|
+
setJmpTrackingConsent: () => setJmpTrackingConsent,
|
|
42
|
+
subscribeJmpTrackingConsent: () => subscribeJmpTrackingConsent,
|
|
40
43
|
useJmpAnalytics: () => useJmpAnalytics
|
|
41
44
|
});
|
|
42
45
|
module.exports = __toCommonJS(next_exports);
|
|
@@ -49,7 +52,6 @@ var JMP_SESSION_ID_KEY = "jmp_analytics_sid";
|
|
|
49
52
|
var JMP_LANDING_REFERER_KEY = "jmp_analytics_landing_referer";
|
|
50
53
|
var JMP_LANDING_REFERER_COOKIE = "jmp_lr";
|
|
51
54
|
var JMP_UTM_SESSION_KEY = "jmp_analytics_utm";
|
|
52
|
-
var JMP_EARLY_BEACON_PATH_KEY = "jmp_analytics_early_beacon_path";
|
|
53
55
|
var LANDING_REFERER_COOKIE_MAX_AGE_SEC = 30 * 60;
|
|
54
56
|
var JMP_UTM_PARAM_KEYS = [
|
|
55
57
|
"utm_source",
|
|
@@ -135,11 +137,9 @@ function captureLandingAttribution(siteHostname) {
|
|
|
135
137
|
const preservedReferer = storedReferer || cookieReferer;
|
|
136
138
|
const currentReferer = document.referrer?.trim() || null;
|
|
137
139
|
if (currentReferer && isExternalReferrerUrl(currentReferer, siteHostname)) {
|
|
138
|
-
|
|
139
|
-
sessionStorage.setItem(JMP_LANDING_REFERER_KEY, currentReferer);
|
|
140
|
-
}
|
|
140
|
+
sessionStorage.setItem(JMP_LANDING_REFERER_KEY, currentReferer);
|
|
141
141
|
writeLandingRefererCookie(currentReferer, siteHostname);
|
|
142
|
-
landingReferer =
|
|
142
|
+
landingReferer = currentReferer;
|
|
143
143
|
} else if (preservedReferer) {
|
|
144
144
|
landingReferer = preservedReferer;
|
|
145
145
|
if (!storedReferer) {
|
|
@@ -184,84 +184,174 @@ function getOrCreateSessionIdFromStorage() {
|
|
|
184
184
|
return void 0;
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
|
-
function
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
function buildLandingCaptureInlineScript() {
|
|
188
|
+
const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC);
|
|
189
|
+
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){}})();`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// src/contact-link-classifier.ts
|
|
193
|
+
var BOOKING_LINK_HOSTS = [
|
|
194
|
+
"calendly.com",
|
|
195
|
+
"cal.com",
|
|
196
|
+
"acuityscheduling.com",
|
|
197
|
+
"calendar.google.com",
|
|
198
|
+
"calendar.app.google",
|
|
199
|
+
"bookings.microsoft.com",
|
|
200
|
+
"outlook.office.com",
|
|
201
|
+
"outlook.office365.com",
|
|
202
|
+
"book.ms",
|
|
203
|
+
"setmore.com",
|
|
204
|
+
"simplybook.me",
|
|
205
|
+
"oncehub.com",
|
|
206
|
+
"scheduleonce.com",
|
|
207
|
+
"youcanbook.me",
|
|
208
|
+
"savvycal.com",
|
|
209
|
+
"tidycal.com",
|
|
210
|
+
"zohobookings.com",
|
|
211
|
+
"square.site",
|
|
212
|
+
"squareup.com",
|
|
213
|
+
"meetings.hubspot.com",
|
|
214
|
+
"jobber.com",
|
|
215
|
+
"housecallpro.com",
|
|
216
|
+
"servicetitan.com",
|
|
217
|
+
"thryv.com",
|
|
218
|
+
"honeybook.com",
|
|
219
|
+
"dubsado.com",
|
|
220
|
+
"fresha.com",
|
|
221
|
+
"booksy.com",
|
|
222
|
+
"vagaro.com",
|
|
223
|
+
"mindbodyonline.com",
|
|
224
|
+
"mindbody.io",
|
|
225
|
+
"janeapp.com",
|
|
226
|
+
"cliniko.com",
|
|
227
|
+
"practicebetter.io"
|
|
228
|
+
];
|
|
229
|
+
var WHATSAPP_HOSTS = ["wa.me", "api.whatsapp.com", "whatsapp.com"];
|
|
230
|
+
function hostnameMatches(host, pattern) {
|
|
231
|
+
const h = host.toLowerCase();
|
|
232
|
+
const p = pattern.toLowerCase();
|
|
233
|
+
return h === p || h.endsWith(`.${p}`);
|
|
234
|
+
}
|
|
235
|
+
function isMapsHost(host, pathname) {
|
|
236
|
+
if (hostnameMatches(host, "maps.apple.com")) {
|
|
237
|
+
return true;
|
|
190
238
|
}
|
|
191
|
-
|
|
192
|
-
return
|
|
193
|
-
}
|
|
194
|
-
|
|
239
|
+
if (hostnameMatches(host, "maps.app.goo.gl")) {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
if (hostnameMatches(host, "google.com") || hostnameMatches(host, "google.co")) {
|
|
243
|
+
return pathname === "/maps" || pathname.startsWith("/maps/") || pathname.startsWith("/local");
|
|
195
244
|
}
|
|
245
|
+
return false;
|
|
196
246
|
}
|
|
197
|
-
function
|
|
198
|
-
|
|
199
|
-
|
|
247
|
+
function isWhatsAppHost(host, pathname) {
|
|
248
|
+
for (const pattern of WHATSAPP_HOSTS) {
|
|
249
|
+
if (!hostnameMatches(host, pattern)) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (pattern === "whatsapp.com") {
|
|
253
|
+
return pathname.startsWith("/send");
|
|
254
|
+
}
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
function isBookingHost(host) {
|
|
260
|
+
for (const pattern of BOOKING_LINK_HOSTS) {
|
|
261
|
+
if (hostnameMatches(host, pattern)) {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
function classifyContactHref(href) {
|
|
268
|
+
const raw = href.trim();
|
|
269
|
+
if (!raw || raw.startsWith("#") || raw.startsWith("javascript:")) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
const lower = raw.toLowerCase();
|
|
273
|
+
if (lower.startsWith("tel:")) {
|
|
274
|
+
return { kind: "call" };
|
|
275
|
+
}
|
|
276
|
+
if (lower.startsWith("mailto:")) {
|
|
277
|
+
return { kind: "email" };
|
|
278
|
+
}
|
|
279
|
+
if (lower.startsWith("sms:") || lower.startsWith("smsto:")) {
|
|
280
|
+
return { kind: "contact_click", channel: "sms", linkHost: null };
|
|
200
281
|
}
|
|
282
|
+
if (lower.startsWith("geo:")) {
|
|
283
|
+
return { kind: "contact_click", channel: "maps", linkHost: null };
|
|
284
|
+
}
|
|
285
|
+
if (raw.startsWith("/") || raw.startsWith("?")) {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
let url;
|
|
201
289
|
try {
|
|
202
|
-
|
|
290
|
+
url = new URL(raw);
|
|
203
291
|
} catch {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
const host = url.hostname.toLowerCase();
|
|
298
|
+
const pathname = url.pathname.toLowerCase();
|
|
299
|
+
if (isWhatsAppHost(host, pathname)) {
|
|
300
|
+
return { kind: "contact_click", channel: "whatsapp", linkHost: host };
|
|
204
301
|
}
|
|
302
|
+
if (isMapsHost(host, pathname)) {
|
|
303
|
+
return { kind: "contact_click", channel: "maps", linkHost: host };
|
|
304
|
+
}
|
|
305
|
+
if (isBookingHost(host)) {
|
|
306
|
+
return { kind: "contact_click", channel: "booking", linkHost: host };
|
|
307
|
+
}
|
|
308
|
+
return null;
|
|
205
309
|
}
|
|
206
|
-
|
|
207
|
-
|
|
310
|
+
|
|
311
|
+
// src/index.ts
|
|
312
|
+
var JMP_TRACKING_CONSENT_STORAGE_KEY = "jmp_analytics_consent_v1";
|
|
313
|
+
var moduleTrackingConsentGranted = true;
|
|
314
|
+
var trackingConsentListeners = /* @__PURE__ */ new Set();
|
|
315
|
+
function readStoredTrackingConsent() {
|
|
316
|
+
if (typeof window === "undefined") {
|
|
208
317
|
return false;
|
|
209
318
|
}
|
|
210
|
-
|
|
211
|
-
|
|
319
|
+
try {
|
|
320
|
+
return localStorage.getItem(JMP_TRACKING_CONSENT_STORAGE_KEY) === "granted";
|
|
321
|
+
} catch {
|
|
212
322
|
return false;
|
|
213
323
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
metadata.referer = landingReferer;
|
|
223
|
-
}
|
|
224
|
-
const payload = {
|
|
225
|
-
type: "page_view",
|
|
226
|
-
path,
|
|
227
|
-
trackingKey: args.trackingKey,
|
|
228
|
-
...sessionId ? { sessionId } : {},
|
|
229
|
-
metadata
|
|
230
|
-
};
|
|
231
|
-
const headers = {
|
|
232
|
-
"Content-Type": "application/json",
|
|
233
|
-
"X-JMP-Tracking-Key": args.trackingKey
|
|
324
|
+
}
|
|
325
|
+
function isJmpTrackingConsentGranted() {
|
|
326
|
+
return moduleTrackingConsentGranted;
|
|
327
|
+
}
|
|
328
|
+
function subscribeJmpTrackingConsent(listener) {
|
|
329
|
+
trackingConsentListeners.add(listener);
|
|
330
|
+
return () => {
|
|
331
|
+
trackingConsentListeners.delete(listener);
|
|
234
332
|
};
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
body: JSON.stringify(payload),
|
|
243
|
-
keepalive: true,
|
|
244
|
-
mode: "cors",
|
|
245
|
-
credentials: "omit"
|
|
246
|
-
}).catch(() => {
|
|
333
|
+
}
|
|
334
|
+
function setJmpTrackingConsent(granted) {
|
|
335
|
+
if (moduleTrackingConsentGranted === granted) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
moduleTrackingConsentGranted = granted;
|
|
339
|
+
if (typeof window !== "undefined") {
|
|
247
340
|
try {
|
|
248
|
-
|
|
341
|
+
localStorage.setItem(
|
|
342
|
+
JMP_TRACKING_CONSENT_STORAGE_KEY,
|
|
343
|
+
granted ? "granted" : "denied"
|
|
344
|
+
);
|
|
249
345
|
} catch {
|
|
250
346
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const baseUrl = escapeInlineScript(args.baseUrl.replace(/\/$/, ""));
|
|
259
|
-
const trackingKey = escapeInlineScript(args.trackingKey);
|
|
260
|
-
const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC);
|
|
261
|
-
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)){if(!stored)sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',ref);writeCk(ref,h);lr=preserved||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){}})();`;
|
|
347
|
+
if (granted) {
|
|
348
|
+
captureLandingAttribution(window.location.hostname);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
for (const listener of trackingConsentListeners) {
|
|
352
|
+
listener();
|
|
353
|
+
}
|
|
262
354
|
}
|
|
263
|
-
|
|
264
|
-
// src/index.ts
|
|
265
355
|
function captureAndGetLandingReferer() {
|
|
266
356
|
if (typeof window === "undefined") {
|
|
267
357
|
return null;
|
|
@@ -311,9 +401,16 @@ function createJmpAnalytics(config) {
|
|
|
311
401
|
);
|
|
312
402
|
}
|
|
313
403
|
const fetchFn = resolvedFetch;
|
|
404
|
+
moduleTrackingConsentGranted = config.requireConsent ? readStoredTrackingConsent() : true;
|
|
405
|
+
function canSend() {
|
|
406
|
+
return moduleTrackingConsentGranted;
|
|
407
|
+
}
|
|
314
408
|
let lastDedupePath = "";
|
|
315
409
|
let lastDedupeAt = 0;
|
|
316
410
|
async function send(body) {
|
|
411
|
+
if (!canSend()) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
317
414
|
const url = `${baseUrl}/api/events`;
|
|
318
415
|
const headers = {
|
|
319
416
|
"Content-Type": "application/json",
|
|
@@ -369,6 +466,9 @@ function createJmpAnalytics(config) {
|
|
|
369
466
|
}
|
|
370
467
|
}
|
|
371
468
|
async function sendLead(body) {
|
|
469
|
+
if (!canSend()) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
372
472
|
const url = `${baseUrl}/api/leads`;
|
|
373
473
|
const headers = {
|
|
374
474
|
"Content-Type": "application/json",
|
|
@@ -431,6 +531,9 @@ function createJmpAnalytics(config) {
|
|
|
431
531
|
return false;
|
|
432
532
|
}
|
|
433
533
|
function trackPageView(options) {
|
|
534
|
+
if (!canSend()) {
|
|
535
|
+
return Promise.resolve();
|
|
536
|
+
}
|
|
434
537
|
const pathFromOptions = options?.path?.trim();
|
|
435
538
|
let pathname = "/";
|
|
436
539
|
let search = "";
|
|
@@ -446,9 +549,6 @@ function createJmpAnalytics(config) {
|
|
|
446
549
|
search = window.location.search.replace(/^\?/, "");
|
|
447
550
|
}
|
|
448
551
|
const path = search ? `${pathname}?${search}` : pathname;
|
|
449
|
-
if (wasEarlyBeaconSentForPath(path)) {
|
|
450
|
-
return Promise.resolve();
|
|
451
|
-
}
|
|
452
552
|
if (shouldDedupePageView(pathname)) {
|
|
453
553
|
return Promise.resolve();
|
|
454
554
|
}
|
|
@@ -499,6 +599,20 @@ function createJmpAnalytics(config) {
|
|
|
499
599
|
metadata: metadata ?? {}
|
|
500
600
|
});
|
|
501
601
|
}
|
|
602
|
+
function trackContactClick(path, options) {
|
|
603
|
+
const metadata = {
|
|
604
|
+
...options.metadata && typeof options.metadata === "object" ? options.metadata : {},
|
|
605
|
+
channel: options.channel
|
|
606
|
+
};
|
|
607
|
+
if (options.linkHost) {
|
|
608
|
+
metadata.linkHost = options.linkHost;
|
|
609
|
+
}
|
|
610
|
+
return send({
|
|
611
|
+
type: "contact_click",
|
|
612
|
+
path: path || "/",
|
|
613
|
+
metadata
|
|
614
|
+
});
|
|
615
|
+
}
|
|
502
616
|
function trackLead(options) {
|
|
503
617
|
const path = options?.path ?? (typeof window !== "undefined" ? window.location.pathname : "/");
|
|
504
618
|
const body = { path: path || "/" };
|
|
@@ -531,7 +645,20 @@ function createJmpAnalytics(config) {
|
|
|
531
645
|
if (type === "call_click") {
|
|
532
646
|
return trackCallClick(payload.path, payload.metadata);
|
|
533
647
|
}
|
|
534
|
-
|
|
648
|
+
if (type === "email_click") {
|
|
649
|
+
return trackEmailClick(payload.path, payload.metadata);
|
|
650
|
+
}
|
|
651
|
+
const meta = payload.metadata ?? {};
|
|
652
|
+
const channel = typeof meta.channel === "string" ? meta.channel : "";
|
|
653
|
+
const linkHost = typeof meta.linkHost === "string" ? meta.linkHost : null;
|
|
654
|
+
if (channel !== "sms" && channel !== "whatsapp" && channel !== "maps" && channel !== "booking") {
|
|
655
|
+
return Promise.resolve();
|
|
656
|
+
}
|
|
657
|
+
return trackContactClick(payload.path, {
|
|
658
|
+
channel,
|
|
659
|
+
linkHost,
|
|
660
|
+
metadata: meta
|
|
661
|
+
});
|
|
535
662
|
}
|
|
536
663
|
function subscribeToSpaNavigation() {
|
|
537
664
|
if (typeof window === "undefined") {
|
|
@@ -565,12 +692,75 @@ function createJmpAnalytics(config) {
|
|
|
565
692
|
history.replaceState = replace;
|
|
566
693
|
};
|
|
567
694
|
}
|
|
568
|
-
|
|
695
|
+
let lastContactClickKey = "";
|
|
696
|
+
let lastContactClickAt = 0;
|
|
697
|
+
function subscribeContactLinkAutoTrack() {
|
|
698
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
699
|
+
return () => {
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
const handler = (event) => {
|
|
703
|
+
if (!canSend()) {
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
const target = event.target;
|
|
707
|
+
if (!(target instanceof Element)) {
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
const anchor = target.closest("a[href]");
|
|
711
|
+
if (!(anchor instanceof HTMLAnchorElement)) {
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
if (anchor.closest("[data-jmp-no-track]")) {
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
const href = anchor.getAttribute("href") ?? "";
|
|
718
|
+
const classified = classifyContactHref(href);
|
|
719
|
+
if (!classified) {
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
const path = window.location.pathname;
|
|
723
|
+
if (classified.kind === "call") {
|
|
724
|
+
if (dedupeContactClick(`call_click:${path}`)) {
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
void trackCallClick(path);
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
if (classified.kind === "email") {
|
|
731
|
+
if (dedupeContactClick(`email_click:${path}`)) {
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
void trackEmailClick(path);
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
if (dedupeContactClick(`contact_click:${classified.channel}:${path}`)) {
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
void trackContactClick(path, {
|
|
741
|
+
channel: classified.channel,
|
|
742
|
+
linkHost: classified.linkHost
|
|
743
|
+
});
|
|
744
|
+
};
|
|
745
|
+
document.addEventListener("click", handler, { capture: true });
|
|
746
|
+
return () => {
|
|
747
|
+
document.removeEventListener("click", handler, { capture: true });
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
function dedupeContactClick(key) {
|
|
751
|
+
const now = Date.now();
|
|
752
|
+
if (key === lastContactClickKey && now - lastContactClickAt < 1e3) {
|
|
753
|
+
return true;
|
|
754
|
+
}
|
|
755
|
+
lastContactClickKey = key;
|
|
756
|
+
lastContactClickAt = now;
|
|
757
|
+
return false;
|
|
758
|
+
}
|
|
759
|
+
if (typeof window !== "undefined" && canSend()) {
|
|
569
760
|
captureLandingAttribution(window.location.hostname);
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
});
|
|
761
|
+
}
|
|
762
|
+
if (typeof window !== "undefined" && config.autoTrackContactLinks && canSend()) {
|
|
763
|
+
subscribeContactLinkAutoTrack();
|
|
574
764
|
}
|
|
575
765
|
return {
|
|
576
766
|
track,
|
|
@@ -578,8 +768,12 @@ function createJmpAnalytics(config) {
|
|
|
578
768
|
trackFormSubmit,
|
|
579
769
|
trackCallClick,
|
|
580
770
|
trackEmailClick,
|
|
771
|
+
trackContactClick,
|
|
581
772
|
trackLead,
|
|
582
|
-
subscribeToSpaNavigation
|
|
773
|
+
subscribeToSpaNavigation,
|
|
774
|
+
subscribeContactLinkAutoTrack,
|
|
775
|
+
setTrackingConsent: setJmpTrackingConsent,
|
|
776
|
+
isTrackingConsentGranted: isJmpTrackingConsentGranted
|
|
583
777
|
};
|
|
584
778
|
}
|
|
585
779
|
var DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 800;
|
|
@@ -592,11 +786,15 @@ function getJmpBrowserAnalyticsConfigFromEnv(overrides) {
|
|
|
592
786
|
const baseUrl = readProcessEnv("NEXT_PUBLIC_JMP_ANALYTICS_URL");
|
|
593
787
|
const trackingKey = readProcessEnv("NEXT_PUBLIC_JMP_TRACKING_KEY");
|
|
594
788
|
if (!baseUrl || !trackingKey) return null;
|
|
789
|
+
const requireConsentFromEnv = readProcessEnv("NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT") === "true";
|
|
790
|
+
const autoTrackContactLinksFromEnv = readProcessEnv("NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS") === "true";
|
|
595
791
|
return {
|
|
596
792
|
baseUrl,
|
|
597
793
|
trackingKey,
|
|
598
794
|
pageViewDedupeMs: DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
|
|
599
|
-
...overrides
|
|
795
|
+
...overrides,
|
|
796
|
+
requireConsent: overrides?.requireConsent ?? requireConsentFromEnv,
|
|
797
|
+
autoTrackContactLinks: overrides?.autoTrackContactLinks ?? autoTrackContactLinksFromEnv
|
|
600
798
|
};
|
|
601
799
|
}
|
|
602
800
|
var jmpAnalyticsBrowserSingleton = null;
|
|
@@ -657,12 +855,9 @@ function JmpTrackedMailtoLink({
|
|
|
657
855
|
// src/next.tsx
|
|
658
856
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
659
857
|
function JmpLandingCaptureScript({
|
|
660
|
-
baseUrl = process.env.NEXT_PUBLIC_JMP_ANALYTICS_URL,
|
|
661
858
|
trackingKey = process.env.NEXT_PUBLIC_JMP_TRACKING_KEY
|
|
662
859
|
} = {}) {
|
|
663
|
-
|
|
664
|
-
const resolvedKey = trackingKey?.trim();
|
|
665
|
-
if (!resolvedBase || !resolvedKey) {
|
|
860
|
+
if (!trackingKey?.trim()) {
|
|
666
861
|
return null;
|
|
667
862
|
}
|
|
668
863
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -671,10 +866,7 @@ function JmpLandingCaptureScript({
|
|
|
671
866
|
id: "jmp-landing-capture",
|
|
672
867
|
strategy: "beforeInteractive",
|
|
673
868
|
dangerouslySetInnerHTML: {
|
|
674
|
-
__html: buildLandingCaptureInlineScript(
|
|
675
|
-
baseUrl: resolvedBase,
|
|
676
|
-
trackingKey: resolvedKey
|
|
677
|
-
})
|
|
869
|
+
__html: buildLandingCaptureInlineScript()
|
|
678
870
|
}
|
|
679
871
|
}
|
|
680
872
|
);
|
|
@@ -693,7 +885,21 @@ function JmpNextPageViewTrackerInner() {
|
|
|
693
885
|
function JmpNextPageViewTracker() {
|
|
694
886
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react2.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(JmpNextPageViewTrackerInner, {}) });
|
|
695
887
|
}
|
|
696
|
-
function
|
|
888
|
+
function useJmpTrackingActive(deferUntilConsent) {
|
|
889
|
+
const consentGranted = (0, import_react2.useSyncExternalStore)(
|
|
890
|
+
subscribeJmpTrackingConsent,
|
|
891
|
+
() => isJmpTrackingConsentGranted(),
|
|
892
|
+
() => false
|
|
893
|
+
);
|
|
894
|
+
return !deferUntilConsent || consentGranted;
|
|
895
|
+
}
|
|
896
|
+
function JmpNextAnalytics({
|
|
897
|
+
deferUntilConsent = process.env.NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT === "true"
|
|
898
|
+
} = {}) {
|
|
899
|
+
const active = useJmpTrackingActive(deferUntilConsent);
|
|
900
|
+
if (!active) {
|
|
901
|
+
return null;
|
|
902
|
+
}
|
|
697
903
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
698
904
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(JmpLandingCaptureScript, {}),
|
|
699
905
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(JmpNextPageViewTracker, {})
|
|
@@ -707,6 +913,9 @@ function JmpNextAnalytics() {
|
|
|
707
913
|
JmpTrackedMailtoLink,
|
|
708
914
|
JmpTrackedTelLink,
|
|
709
915
|
buildLandingCaptureInlineScript,
|
|
916
|
+
isJmpTrackingConsentGranted,
|
|
917
|
+
setJmpTrackingConsent,
|
|
918
|
+
subscribeJmpTrackingConsent,
|
|
710
919
|
useJmpAnalytics
|
|
711
920
|
});
|
|
712
921
|
//# sourceMappingURL=next.cjs.map
|