@jmp-technologies/analytics 0.1.17 → 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-MUHLIN7P.js → chunk-SOHYQ5GT.js} +282 -75
- package/dist/chunk-SOHYQ5GT.js.map +1 -0
- package/dist/{chunk-3ELQETAA.js → chunk-W7CQ5VG2.js} +2 -2
- package/dist/index.cjs +288 -75
- 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 +293 -82
- 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 +261 -65
- 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-MUHLIN7P.js.map +0 -1
- /package/dist/{chunk-3ELQETAA.js.map → chunk-W7CQ5VG2.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -20,8 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
BOOKING_LINK_HOSTS: () => BOOKING_LINK_HOSTS,
|
|
23
24
|
DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS: () => DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
|
|
25
|
+
JMP_ANALYTICS_SDK_VERSION: () => JMP_ANALYTICS_SDK_VERSION,
|
|
26
|
+
JMP_TRACKING_CONSENT_STORAGE_KEY: () => JMP_TRACKING_CONSENT_STORAGE_KEY,
|
|
24
27
|
buildLandingCaptureInlineScript: () => buildLandingCaptureInlineScript,
|
|
28
|
+
classifyContactHref: () => classifyContactHref,
|
|
25
29
|
createJmpAnalytics: () => createJmpAnalytics,
|
|
26
30
|
createJmpContentClient: () => createJmpContentClient,
|
|
27
31
|
createJmpContentClientFromServerEnv: () => createJmpContentClientFromServerEnv,
|
|
@@ -36,9 +40,11 @@ __export(index_exports, {
|
|
|
36
40
|
getOrCreateJmpAnalyticsFromBrowserEnv: () => getOrCreateJmpAnalyticsFromBrowserEnv,
|
|
37
41
|
isJmpBrowserAnalyticsEnvConfigured: () => isJmpBrowserAnalyticsEnvConfigured,
|
|
38
42
|
isJmpServerContentEnvConfigured: () => isJmpServerContentEnvConfigured,
|
|
43
|
+
isJmpTrackingConsentGranted: () => isJmpTrackingConsentGranted,
|
|
39
44
|
registerJmpContentWrappers: () => registerJmpContentWrappers,
|
|
40
45
|
registerJmpTrustCapabilities: () => registerJmpTrustCapabilities,
|
|
41
|
-
|
|
46
|
+
setJmpTrackingConsent: () => setJmpTrackingConsent,
|
|
47
|
+
subscribeJmpTrackingConsent: () => subscribeJmpTrackingConsent,
|
|
42
48
|
trackJmpServerPageView: () => trackJmpServerPageView
|
|
43
49
|
});
|
|
44
50
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -48,7 +54,6 @@ var JMP_SESSION_ID_KEY = "jmp_analytics_sid";
|
|
|
48
54
|
var JMP_LANDING_REFERER_KEY = "jmp_analytics_landing_referer";
|
|
49
55
|
var JMP_LANDING_REFERER_COOKIE = "jmp_lr";
|
|
50
56
|
var JMP_UTM_SESSION_KEY = "jmp_analytics_utm";
|
|
51
|
-
var JMP_EARLY_BEACON_PATH_KEY = "jmp_analytics_early_beacon_path";
|
|
52
57
|
var LANDING_REFERER_COOKIE_MAX_AGE_SEC = 30 * 60;
|
|
53
58
|
var JMP_UTM_PARAM_KEYS = [
|
|
54
59
|
"utm_source",
|
|
@@ -181,84 +186,175 @@ function getOrCreateSessionIdFromStorage() {
|
|
|
181
186
|
return void 0;
|
|
182
187
|
}
|
|
183
188
|
}
|
|
184
|
-
function
|
|
185
|
-
|
|
186
|
-
|
|
189
|
+
function buildLandingCaptureInlineScript() {
|
|
190
|
+
const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC);
|
|
191
|
+
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){}})();`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// src/contact-link-classifier.ts
|
|
195
|
+
var BOOKING_LINK_HOSTS = [
|
|
196
|
+
"calendly.com",
|
|
197
|
+
"cal.com",
|
|
198
|
+
"acuityscheduling.com",
|
|
199
|
+
"calendar.google.com",
|
|
200
|
+
"calendar.app.google",
|
|
201
|
+
"bookings.microsoft.com",
|
|
202
|
+
"outlook.office.com",
|
|
203
|
+
"outlook.office365.com",
|
|
204
|
+
"book.ms",
|
|
205
|
+
"setmore.com",
|
|
206
|
+
"simplybook.me",
|
|
207
|
+
"oncehub.com",
|
|
208
|
+
"scheduleonce.com",
|
|
209
|
+
"youcanbook.me",
|
|
210
|
+
"savvycal.com",
|
|
211
|
+
"tidycal.com",
|
|
212
|
+
"zohobookings.com",
|
|
213
|
+
"square.site",
|
|
214
|
+
"squareup.com",
|
|
215
|
+
"meetings.hubspot.com",
|
|
216
|
+
"jobber.com",
|
|
217
|
+
"housecallpro.com",
|
|
218
|
+
"servicetitan.com",
|
|
219
|
+
"thryv.com",
|
|
220
|
+
"honeybook.com",
|
|
221
|
+
"dubsado.com",
|
|
222
|
+
"fresha.com",
|
|
223
|
+
"booksy.com",
|
|
224
|
+
"vagaro.com",
|
|
225
|
+
"mindbodyonline.com",
|
|
226
|
+
"mindbody.io",
|
|
227
|
+
"janeapp.com",
|
|
228
|
+
"cliniko.com",
|
|
229
|
+
"practicebetter.io"
|
|
230
|
+
];
|
|
231
|
+
var WHATSAPP_HOSTS = ["wa.me", "api.whatsapp.com", "whatsapp.com"];
|
|
232
|
+
function hostnameMatches(host, pattern) {
|
|
233
|
+
const h = host.toLowerCase();
|
|
234
|
+
const p = pattern.toLowerCase();
|
|
235
|
+
return h === p || h.endsWith(`.${p}`);
|
|
236
|
+
}
|
|
237
|
+
function isMapsHost(host, pathname) {
|
|
238
|
+
if (hostnameMatches(host, "maps.apple.com")) {
|
|
239
|
+
return true;
|
|
187
240
|
}
|
|
188
|
-
|
|
189
|
-
return
|
|
190
|
-
}
|
|
191
|
-
|
|
241
|
+
if (hostnameMatches(host, "maps.app.goo.gl")) {
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
if (hostnameMatches(host, "google.com") || hostnameMatches(host, "google.co")) {
|
|
245
|
+
return pathname === "/maps" || pathname.startsWith("/maps/") || pathname.startsWith("/local");
|
|
192
246
|
}
|
|
247
|
+
return false;
|
|
193
248
|
}
|
|
194
|
-
function
|
|
195
|
-
|
|
196
|
-
|
|
249
|
+
function isWhatsAppHost(host, pathname) {
|
|
250
|
+
for (const pattern of WHATSAPP_HOSTS) {
|
|
251
|
+
if (!hostnameMatches(host, pattern)) {
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (pattern === "whatsapp.com") {
|
|
255
|
+
return pathname.startsWith("/send");
|
|
256
|
+
}
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
function isBookingHost(host) {
|
|
262
|
+
for (const pattern of BOOKING_LINK_HOSTS) {
|
|
263
|
+
if (hostnameMatches(host, pattern)) {
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
function classifyContactHref(href) {
|
|
270
|
+
const raw = href.trim();
|
|
271
|
+
if (!raw || raw.startsWith("#") || raw.startsWith("javascript:")) {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
const lower = raw.toLowerCase();
|
|
275
|
+
if (lower.startsWith("tel:")) {
|
|
276
|
+
return { kind: "call" };
|
|
277
|
+
}
|
|
278
|
+
if (lower.startsWith("mailto:")) {
|
|
279
|
+
return { kind: "email" };
|
|
197
280
|
}
|
|
281
|
+
if (lower.startsWith("sms:") || lower.startsWith("smsto:")) {
|
|
282
|
+
return { kind: "contact_click", channel: "sms", linkHost: null };
|
|
283
|
+
}
|
|
284
|
+
if (lower.startsWith("geo:")) {
|
|
285
|
+
return { kind: "contact_click", channel: "maps", linkHost: null };
|
|
286
|
+
}
|
|
287
|
+
if (raw.startsWith("/") || raw.startsWith("?")) {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
let url;
|
|
198
291
|
try {
|
|
199
|
-
|
|
292
|
+
url = new URL(raw);
|
|
200
293
|
} catch {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
const host = url.hostname.toLowerCase();
|
|
300
|
+
const pathname = url.pathname.toLowerCase();
|
|
301
|
+
if (isWhatsAppHost(host, pathname)) {
|
|
302
|
+
return { kind: "contact_click", channel: "whatsapp", linkHost: host };
|
|
303
|
+
}
|
|
304
|
+
if (isMapsHost(host, pathname)) {
|
|
305
|
+
return { kind: "contact_click", channel: "maps", linkHost: host };
|
|
306
|
+
}
|
|
307
|
+
if (isBookingHost(host)) {
|
|
308
|
+
return { kind: "contact_click", channel: "booking", linkHost: host };
|
|
201
309
|
}
|
|
310
|
+
return null;
|
|
202
311
|
}
|
|
203
|
-
|
|
204
|
-
|
|
312
|
+
|
|
313
|
+
// src/index.ts
|
|
314
|
+
var JMP_ANALYTICS_SDK_VERSION = "0.1.18";
|
|
315
|
+
var JMP_TRACKING_CONSENT_STORAGE_KEY = "jmp_analytics_consent_v1";
|
|
316
|
+
var moduleTrackingConsentGranted = true;
|
|
317
|
+
var trackingConsentListeners = /* @__PURE__ */ new Set();
|
|
318
|
+
function readStoredTrackingConsent() {
|
|
319
|
+
if (typeof window === "undefined") {
|
|
205
320
|
return false;
|
|
206
321
|
}
|
|
207
|
-
|
|
208
|
-
|
|
322
|
+
try {
|
|
323
|
+
return localStorage.getItem(JMP_TRACKING_CONSENT_STORAGE_KEY) === "granted";
|
|
324
|
+
} catch {
|
|
209
325
|
return false;
|
|
210
326
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
metadata.referer = landingReferer;
|
|
220
|
-
}
|
|
221
|
-
const payload = {
|
|
222
|
-
type: "page_view",
|
|
223
|
-
path,
|
|
224
|
-
trackingKey: args.trackingKey,
|
|
225
|
-
...sessionId ? { sessionId } : {},
|
|
226
|
-
metadata
|
|
227
|
-
};
|
|
228
|
-
const headers = {
|
|
229
|
-
"Content-Type": "application/json",
|
|
230
|
-
"X-JMP-Tracking-Key": args.trackingKey
|
|
327
|
+
}
|
|
328
|
+
function isJmpTrackingConsentGranted() {
|
|
329
|
+
return moduleTrackingConsentGranted;
|
|
330
|
+
}
|
|
331
|
+
function subscribeJmpTrackingConsent(listener) {
|
|
332
|
+
trackingConsentListeners.add(listener);
|
|
333
|
+
return () => {
|
|
334
|
+
trackingConsentListeners.delete(listener);
|
|
231
335
|
};
|
|
232
|
-
|
|
233
|
-
|
|
336
|
+
}
|
|
337
|
+
function setJmpTrackingConsent(granted) {
|
|
338
|
+
if (moduleTrackingConsentGranted === granted) {
|
|
339
|
+
return;
|
|
234
340
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
method: "POST",
|
|
238
|
-
headers,
|
|
239
|
-
body: JSON.stringify(payload),
|
|
240
|
-
keepalive: true,
|
|
241
|
-
mode: "cors",
|
|
242
|
-
credentials: "omit"
|
|
243
|
-
}).catch(() => {
|
|
341
|
+
moduleTrackingConsentGranted = granted;
|
|
342
|
+
if (typeof window !== "undefined") {
|
|
244
343
|
try {
|
|
245
|
-
|
|
344
|
+
localStorage.setItem(
|
|
345
|
+
JMP_TRACKING_CONSENT_STORAGE_KEY,
|
|
346
|
+
granted ? "granted" : "denied"
|
|
347
|
+
);
|
|
246
348
|
} catch {
|
|
247
349
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const baseUrl = escapeInlineScript(args.baseUrl.replace(/\/$/, ""));
|
|
256
|
-
const trackingKey = escapeInlineScript(args.trackingKey);
|
|
257
|
-
const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC);
|
|
258
|
-
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){}})();`;
|
|
350
|
+
if (granted) {
|
|
351
|
+
captureLandingAttribution(window.location.hostname);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
for (const listener of trackingConsentListeners) {
|
|
355
|
+
listener();
|
|
356
|
+
}
|
|
259
357
|
}
|
|
260
|
-
|
|
261
|
-
// src/index.ts
|
|
262
358
|
function captureAndGetLandingReferer() {
|
|
263
359
|
if (typeof window === "undefined") {
|
|
264
360
|
return null;
|
|
@@ -333,9 +429,16 @@ function createJmpAnalytics(config) {
|
|
|
333
429
|
);
|
|
334
430
|
}
|
|
335
431
|
const fetchFn = resolvedFetch;
|
|
432
|
+
moduleTrackingConsentGranted = config.requireConsent ? readStoredTrackingConsent() : true;
|
|
433
|
+
function canSend() {
|
|
434
|
+
return moduleTrackingConsentGranted;
|
|
435
|
+
}
|
|
336
436
|
let lastDedupePath = "";
|
|
337
437
|
let lastDedupeAt = 0;
|
|
338
438
|
async function send(body) {
|
|
439
|
+
if (!canSend()) {
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
339
442
|
const url = `${baseUrl}/api/events`;
|
|
340
443
|
const headers = {
|
|
341
444
|
"Content-Type": "application/json",
|
|
@@ -391,6 +494,9 @@ function createJmpAnalytics(config) {
|
|
|
391
494
|
}
|
|
392
495
|
}
|
|
393
496
|
async function sendLead(body) {
|
|
497
|
+
if (!canSend()) {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
394
500
|
const url = `${baseUrl}/api/leads`;
|
|
395
501
|
const headers = {
|
|
396
502
|
"Content-Type": "application/json",
|
|
@@ -453,6 +559,9 @@ function createJmpAnalytics(config) {
|
|
|
453
559
|
return false;
|
|
454
560
|
}
|
|
455
561
|
function trackPageView(options) {
|
|
562
|
+
if (!canSend()) {
|
|
563
|
+
return Promise.resolve();
|
|
564
|
+
}
|
|
456
565
|
const pathFromOptions = options?.path?.trim();
|
|
457
566
|
let pathname = "/";
|
|
458
567
|
let search = "";
|
|
@@ -468,9 +577,6 @@ function createJmpAnalytics(config) {
|
|
|
468
577
|
search = window.location.search.replace(/^\?/, "");
|
|
469
578
|
}
|
|
470
579
|
const path = search ? `${pathname}?${search}` : pathname;
|
|
471
|
-
if (wasEarlyBeaconSentForPath(path)) {
|
|
472
|
-
return Promise.resolve();
|
|
473
|
-
}
|
|
474
580
|
if (shouldDedupePageView(pathname)) {
|
|
475
581
|
return Promise.resolve();
|
|
476
582
|
}
|
|
@@ -521,6 +627,20 @@ function createJmpAnalytics(config) {
|
|
|
521
627
|
metadata: metadata ?? {}
|
|
522
628
|
});
|
|
523
629
|
}
|
|
630
|
+
function trackContactClick(path, options) {
|
|
631
|
+
const metadata = {
|
|
632
|
+
...options.metadata && typeof options.metadata === "object" ? options.metadata : {},
|
|
633
|
+
channel: options.channel
|
|
634
|
+
};
|
|
635
|
+
if (options.linkHost) {
|
|
636
|
+
metadata.linkHost = options.linkHost;
|
|
637
|
+
}
|
|
638
|
+
return send({
|
|
639
|
+
type: "contact_click",
|
|
640
|
+
path: path || "/",
|
|
641
|
+
metadata
|
|
642
|
+
});
|
|
643
|
+
}
|
|
524
644
|
function trackLead(options) {
|
|
525
645
|
const path = options?.path ?? (typeof window !== "undefined" ? window.location.pathname : "/");
|
|
526
646
|
const body = { path: path || "/" };
|
|
@@ -553,7 +673,20 @@ function createJmpAnalytics(config) {
|
|
|
553
673
|
if (type === "call_click") {
|
|
554
674
|
return trackCallClick(payload.path, payload.metadata);
|
|
555
675
|
}
|
|
556
|
-
|
|
676
|
+
if (type === "email_click") {
|
|
677
|
+
return trackEmailClick(payload.path, payload.metadata);
|
|
678
|
+
}
|
|
679
|
+
const meta = payload.metadata ?? {};
|
|
680
|
+
const channel = typeof meta.channel === "string" ? meta.channel : "";
|
|
681
|
+
const linkHost = typeof meta.linkHost === "string" ? meta.linkHost : null;
|
|
682
|
+
if (channel !== "sms" && channel !== "whatsapp" && channel !== "maps" && channel !== "booking") {
|
|
683
|
+
return Promise.resolve();
|
|
684
|
+
}
|
|
685
|
+
return trackContactClick(payload.path, {
|
|
686
|
+
channel,
|
|
687
|
+
linkHost,
|
|
688
|
+
metadata: meta
|
|
689
|
+
});
|
|
557
690
|
}
|
|
558
691
|
function subscribeToSpaNavigation() {
|
|
559
692
|
if (typeof window === "undefined") {
|
|
@@ -587,12 +720,75 @@ function createJmpAnalytics(config) {
|
|
|
587
720
|
history.replaceState = replace;
|
|
588
721
|
};
|
|
589
722
|
}
|
|
590
|
-
|
|
723
|
+
let lastContactClickKey = "";
|
|
724
|
+
let lastContactClickAt = 0;
|
|
725
|
+
function subscribeContactLinkAutoTrack() {
|
|
726
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
727
|
+
return () => {
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
const handler = (event) => {
|
|
731
|
+
if (!canSend()) {
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
const target = event.target;
|
|
735
|
+
if (!(target instanceof Element)) {
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
const anchor = target.closest("a[href]");
|
|
739
|
+
if (!(anchor instanceof HTMLAnchorElement)) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
if (anchor.closest("[data-jmp-no-track]")) {
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
const href = anchor.getAttribute("href") ?? "";
|
|
746
|
+
const classified = classifyContactHref(href);
|
|
747
|
+
if (!classified) {
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
const path = window.location.pathname;
|
|
751
|
+
if (classified.kind === "call") {
|
|
752
|
+
if (dedupeContactClick(`call_click:${path}`)) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
void trackCallClick(path);
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
if (classified.kind === "email") {
|
|
759
|
+
if (dedupeContactClick(`email_click:${path}`)) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
void trackEmailClick(path);
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
if (dedupeContactClick(`contact_click:${classified.channel}:${path}`)) {
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
void trackContactClick(path, {
|
|
769
|
+
channel: classified.channel,
|
|
770
|
+
linkHost: classified.linkHost
|
|
771
|
+
});
|
|
772
|
+
};
|
|
773
|
+
document.addEventListener("click", handler, { capture: true });
|
|
774
|
+
return () => {
|
|
775
|
+
document.removeEventListener("click", handler, { capture: true });
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
function dedupeContactClick(key) {
|
|
779
|
+
const now = Date.now();
|
|
780
|
+
if (key === lastContactClickKey && now - lastContactClickAt < 1e3) {
|
|
781
|
+
return true;
|
|
782
|
+
}
|
|
783
|
+
lastContactClickKey = key;
|
|
784
|
+
lastContactClickAt = now;
|
|
785
|
+
return false;
|
|
786
|
+
}
|
|
787
|
+
if (typeof window !== "undefined" && canSend()) {
|
|
591
788
|
captureLandingAttribution(window.location.hostname);
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
});
|
|
789
|
+
}
|
|
790
|
+
if (typeof window !== "undefined" && config.autoTrackContactLinks && canSend()) {
|
|
791
|
+
subscribeContactLinkAutoTrack();
|
|
596
792
|
}
|
|
597
793
|
return {
|
|
598
794
|
track,
|
|
@@ -600,8 +796,12 @@ function createJmpAnalytics(config) {
|
|
|
600
796
|
trackFormSubmit,
|
|
601
797
|
trackCallClick,
|
|
602
798
|
trackEmailClick,
|
|
799
|
+
trackContactClick,
|
|
603
800
|
trackLead,
|
|
604
|
-
subscribeToSpaNavigation
|
|
801
|
+
subscribeToSpaNavigation,
|
|
802
|
+
subscribeContactLinkAutoTrack,
|
|
803
|
+
setTrackingConsent: setJmpTrackingConsent,
|
|
804
|
+
isTrackingConsentGranted: isJmpTrackingConsentGranted
|
|
605
805
|
};
|
|
606
806
|
}
|
|
607
807
|
async function trackJmpServerPageView(config, options = {}) {
|
|
@@ -724,7 +924,10 @@ async function registerJmpContentWrappers(config) {
|
|
|
724
924
|
"Content-Type": "application/json",
|
|
725
925
|
"X-JMP-Tracking-Key": config.trackingKey
|
|
726
926
|
},
|
|
727
|
-
body: JSON.stringify({
|
|
927
|
+
body: JSON.stringify({
|
|
928
|
+
wrappers,
|
|
929
|
+
sdkVersion: JMP_ANALYTICS_SDK_VERSION
|
|
930
|
+
})
|
|
728
931
|
});
|
|
729
932
|
const text = await res.text();
|
|
730
933
|
if (!res.ok) {
|
|
@@ -822,11 +1025,15 @@ function getJmpBrowserAnalyticsConfigFromEnv(overrides) {
|
|
|
822
1025
|
const baseUrl = readProcessEnv("NEXT_PUBLIC_JMP_ANALYTICS_URL");
|
|
823
1026
|
const trackingKey = readProcessEnv("NEXT_PUBLIC_JMP_TRACKING_KEY");
|
|
824
1027
|
if (!baseUrl || !trackingKey) return null;
|
|
1028
|
+
const requireConsentFromEnv = readProcessEnv("NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT") === "true";
|
|
1029
|
+
const autoTrackContactLinksFromEnv = readProcessEnv("NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS") === "true";
|
|
825
1030
|
return {
|
|
826
1031
|
baseUrl,
|
|
827
1032
|
trackingKey,
|
|
828
1033
|
pageViewDedupeMs: DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
|
|
829
|
-
...overrides
|
|
1034
|
+
...overrides,
|
|
1035
|
+
requireConsent: overrides?.requireConsent ?? requireConsentFromEnv,
|
|
1036
|
+
autoTrackContactLinks: overrides?.autoTrackContactLinks ?? autoTrackContactLinksFromEnv
|
|
830
1037
|
};
|
|
831
1038
|
}
|
|
832
1039
|
function getJmpServerContentConfigFromEnv(overrides) {
|
|
@@ -859,8 +1066,12 @@ function createJmpContentClientFromServerEnv(overrides) {
|
|
|
859
1066
|
}
|
|
860
1067
|
// Annotate the CommonJS export names for ESM import in node:
|
|
861
1068
|
0 && (module.exports = {
|
|
1069
|
+
BOOKING_LINK_HOSTS,
|
|
862
1070
|
DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
|
|
1071
|
+
JMP_ANALYTICS_SDK_VERSION,
|
|
1072
|
+
JMP_TRACKING_CONSENT_STORAGE_KEY,
|
|
863
1073
|
buildLandingCaptureInlineScript,
|
|
1074
|
+
classifyContactHref,
|
|
864
1075
|
createJmpAnalytics,
|
|
865
1076
|
createJmpContentClient,
|
|
866
1077
|
createJmpContentClientFromServerEnv,
|
|
@@ -875,9 +1086,11 @@ function createJmpContentClientFromServerEnv(overrides) {
|
|
|
875
1086
|
getOrCreateJmpAnalyticsFromBrowserEnv,
|
|
876
1087
|
isJmpBrowserAnalyticsEnvConfigured,
|
|
877
1088
|
isJmpServerContentEnvConfigured,
|
|
1089
|
+
isJmpTrackingConsentGranted,
|
|
878
1090
|
registerJmpContentWrappers,
|
|
879
1091
|
registerJmpTrustCapabilities,
|
|
880
|
-
|
|
1092
|
+
setJmpTrackingConsent,
|
|
1093
|
+
subscribeJmpTrackingConsent,
|
|
881
1094
|
trackJmpServerPageView
|
|
882
1095
|
});
|
|
883
1096
|
//# sourceMappingURL=index.cjs.map
|