@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/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
- sendEarlyPageViewBeacon: () => sendEarlyPageViewBeacon,
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",
@@ -134,11 +139,9 @@ function captureLandingAttribution(siteHostname) {
134
139
  const preservedReferer = storedReferer || cookieReferer;
135
140
  const currentReferer = document.referrer?.trim() || null;
136
141
  if (currentReferer && isExternalReferrerUrl(currentReferer, siteHostname)) {
137
- if (!storedReferer) {
138
- sessionStorage.setItem(JMP_LANDING_REFERER_KEY, currentReferer);
139
- }
142
+ sessionStorage.setItem(JMP_LANDING_REFERER_KEY, currentReferer);
140
143
  writeLandingRefererCookie(currentReferer, siteHostname);
141
- landingReferer = preservedReferer || currentReferer;
144
+ landingReferer = currentReferer;
142
145
  } else if (preservedReferer) {
143
146
  landingReferer = preservedReferer;
144
147
  if (!storedReferer) {
@@ -183,84 +186,175 @@ function getOrCreateSessionIdFromStorage() {
183
186
  return void 0;
184
187
  }
185
188
  }
186
- function wasEarlyBeaconSentForPath(path) {
187
- if (typeof window === "undefined") {
188
- return false;
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;
189
240
  }
190
- try {
191
- return sessionStorage.getItem(JMP_EARLY_BEACON_PATH_KEY) === path;
192
- } catch {
193
- return false;
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");
194
246
  }
247
+ return false;
195
248
  }
196
- function markEarlyBeaconSentForPath(path) {
197
- if (typeof window === "undefined") {
198
- return;
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" };
280
+ }
281
+ if (lower.startsWith("sms:") || lower.startsWith("smsto:")) {
282
+ return { kind: "contact_click", channel: "sms", linkHost: null };
199
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;
200
291
  try {
201
- sessionStorage.setItem(JMP_EARLY_BEACON_PATH_KEY, path);
292
+ url = new URL(raw);
202
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 };
203
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 };
309
+ }
310
+ return null;
204
311
  }
205
- function sendEarlyPageViewBeacon(args) {
206
- if (typeof window === "undefined" || typeof fetch === "undefined") {
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") {
207
320
  return false;
208
321
  }
209
- const path = `${window.location.pathname}${window.location.search}` || "/";
210
- if (wasEarlyBeaconSentForPath(path)) {
322
+ try {
323
+ return localStorage.getItem(JMP_TRACKING_CONSENT_STORAGE_KEY) === "granted";
324
+ } catch {
211
325
  return false;
212
326
  }
213
- const { landingReferer, utm } = captureLandingAttribution(window.location.hostname);
214
- const sessionId = getOrCreateSessionIdFromStorage();
215
- const metadata = {
216
- pageHostname: window.location.hostname,
217
- earlyBeacon: true,
218
- ...utm
219
- };
220
- if (landingReferer) {
221
- metadata.referer = landingReferer;
222
- }
223
- const payload = {
224
- type: "page_view",
225
- path,
226
- trackingKey: args.trackingKey,
227
- ...sessionId ? { sessionId } : {},
228
- metadata
229
- };
230
- const headers = {
231
- "Content-Type": "application/json",
232
- "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);
233
335
  };
234
- if (landingReferer) {
235
- headers["X-JMP-Visitor-Referer"] = landingReferer;
336
+ }
337
+ function setJmpTrackingConsent(granted) {
338
+ if (moduleTrackingConsentGranted === granted) {
339
+ return;
236
340
  }
237
- markEarlyBeaconSentForPath(path);
238
- void fetch(`${args.baseUrl.replace(/\/$/, "")}/api/events`, {
239
- method: "POST",
240
- headers,
241
- body: JSON.stringify(payload),
242
- keepalive: true,
243
- mode: "cors",
244
- credentials: "omit"
245
- }).catch(() => {
341
+ moduleTrackingConsentGranted = granted;
342
+ if (typeof window !== "undefined") {
246
343
  try {
247
- sessionStorage.removeItem(JMP_EARLY_BEACON_PATH_KEY);
344
+ localStorage.setItem(
345
+ JMP_TRACKING_CONSENT_STORAGE_KEY,
346
+ granted ? "granted" : "denied"
347
+ );
248
348
  } catch {
249
349
  }
250
- });
251
- return true;
252
- }
253
- function escapeInlineScript(value) {
254
- return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
255
- }
256
- function buildLandingCaptureInlineScript(args) {
257
- const baseUrl = escapeInlineScript(args.baseUrl.replace(/\/$/, ""));
258
- const trackingKey = escapeInlineScript(args.trackingKey);
259
- const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC);
260
- 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){}})();`;
350
+ if (granted) {
351
+ captureLandingAttribution(window.location.hostname);
352
+ }
353
+ }
354
+ for (const listener of trackingConsentListeners) {
355
+ listener();
356
+ }
261
357
  }
262
-
263
- // src/index.ts
264
358
  function captureAndGetLandingReferer() {
265
359
  if (typeof window === "undefined") {
266
360
  return null;
@@ -335,9 +429,16 @@ function createJmpAnalytics(config) {
335
429
  );
336
430
  }
337
431
  const fetchFn = resolvedFetch;
432
+ moduleTrackingConsentGranted = config.requireConsent ? readStoredTrackingConsent() : true;
433
+ function canSend() {
434
+ return moduleTrackingConsentGranted;
435
+ }
338
436
  let lastDedupePath = "";
339
437
  let lastDedupeAt = 0;
340
438
  async function send(body) {
439
+ if (!canSend()) {
440
+ return;
441
+ }
341
442
  const url = `${baseUrl}/api/events`;
342
443
  const headers = {
343
444
  "Content-Type": "application/json",
@@ -393,6 +494,9 @@ function createJmpAnalytics(config) {
393
494
  }
394
495
  }
395
496
  async function sendLead(body) {
497
+ if (!canSend()) {
498
+ return;
499
+ }
396
500
  const url = `${baseUrl}/api/leads`;
397
501
  const headers = {
398
502
  "Content-Type": "application/json",
@@ -455,6 +559,9 @@ function createJmpAnalytics(config) {
455
559
  return false;
456
560
  }
457
561
  function trackPageView(options) {
562
+ if (!canSend()) {
563
+ return Promise.resolve();
564
+ }
458
565
  const pathFromOptions = options?.path?.trim();
459
566
  let pathname = "/";
460
567
  let search = "";
@@ -470,9 +577,6 @@ function createJmpAnalytics(config) {
470
577
  search = window.location.search.replace(/^\?/, "");
471
578
  }
472
579
  const path = search ? `${pathname}?${search}` : pathname;
473
- if (wasEarlyBeaconSentForPath(path)) {
474
- return Promise.resolve();
475
- }
476
580
  if (shouldDedupePageView(pathname)) {
477
581
  return Promise.resolve();
478
582
  }
@@ -523,6 +627,20 @@ function createJmpAnalytics(config) {
523
627
  metadata: metadata ?? {}
524
628
  });
525
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
+ }
526
644
  function trackLead(options) {
527
645
  const path = options?.path ?? (typeof window !== "undefined" ? window.location.pathname : "/");
528
646
  const body = { path: path || "/" };
@@ -555,7 +673,20 @@ function createJmpAnalytics(config) {
555
673
  if (type === "call_click") {
556
674
  return trackCallClick(payload.path, payload.metadata);
557
675
  }
558
- return trackEmailClick(payload.path, payload.metadata);
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
+ });
559
690
  }
560
691
  function subscribeToSpaNavigation() {
561
692
  if (typeof window === "undefined") {
@@ -589,12 +720,75 @@ function createJmpAnalytics(config) {
589
720
  history.replaceState = replace;
590
721
  };
591
722
  }
592
- if (typeof window !== "undefined") {
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()) {
593
788
  captureLandingAttribution(window.location.hostname);
594
- sendEarlyPageViewBeacon({
595
- baseUrl,
596
- trackingKey: config.trackingKey
597
- });
789
+ }
790
+ if (typeof window !== "undefined" && config.autoTrackContactLinks && canSend()) {
791
+ subscribeContactLinkAutoTrack();
598
792
  }
599
793
  return {
600
794
  track,
@@ -602,8 +796,12 @@ function createJmpAnalytics(config) {
602
796
  trackFormSubmit,
603
797
  trackCallClick,
604
798
  trackEmailClick,
799
+ trackContactClick,
605
800
  trackLead,
606
- subscribeToSpaNavigation
801
+ subscribeToSpaNavigation,
802
+ subscribeContactLinkAutoTrack,
803
+ setTrackingConsent: setJmpTrackingConsent,
804
+ isTrackingConsentGranted: isJmpTrackingConsentGranted
607
805
  };
608
806
  }
609
807
  async function trackJmpServerPageView(config, options = {}) {
@@ -726,7 +924,10 @@ async function registerJmpContentWrappers(config) {
726
924
  "Content-Type": "application/json",
727
925
  "X-JMP-Tracking-Key": config.trackingKey
728
926
  },
729
- body: JSON.stringify({ wrappers })
927
+ body: JSON.stringify({
928
+ wrappers,
929
+ sdkVersion: JMP_ANALYTICS_SDK_VERSION
930
+ })
730
931
  });
731
932
  const text = await res.text();
732
933
  if (!res.ok) {
@@ -824,11 +1025,15 @@ function getJmpBrowserAnalyticsConfigFromEnv(overrides) {
824
1025
  const baseUrl = readProcessEnv("NEXT_PUBLIC_JMP_ANALYTICS_URL");
825
1026
  const trackingKey = readProcessEnv("NEXT_PUBLIC_JMP_TRACKING_KEY");
826
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";
827
1030
  return {
828
1031
  baseUrl,
829
1032
  trackingKey,
830
1033
  pageViewDedupeMs: DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
831
- ...overrides
1034
+ ...overrides,
1035
+ requireConsent: overrides?.requireConsent ?? requireConsentFromEnv,
1036
+ autoTrackContactLinks: overrides?.autoTrackContactLinks ?? autoTrackContactLinksFromEnv
832
1037
  };
833
1038
  }
834
1039
  function getJmpServerContentConfigFromEnv(overrides) {
@@ -861,8 +1066,12 @@ function createJmpContentClientFromServerEnv(overrides) {
861
1066
  }
862
1067
  // Annotate the CommonJS export names for ESM import in node:
863
1068
  0 && (module.exports = {
1069
+ BOOKING_LINK_HOSTS,
864
1070
  DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
1071
+ JMP_ANALYTICS_SDK_VERSION,
1072
+ JMP_TRACKING_CONSENT_STORAGE_KEY,
865
1073
  buildLandingCaptureInlineScript,
1074
+ classifyContactHref,
866
1075
  createJmpAnalytics,
867
1076
  createJmpContentClient,
868
1077
  createJmpContentClientFromServerEnv,
@@ -877,9 +1086,11 @@ function createJmpContentClientFromServerEnv(overrides) {
877
1086
  getOrCreateJmpAnalyticsFromBrowserEnv,
878
1087
  isJmpBrowserAnalyticsEnvConfigured,
879
1088
  isJmpServerContentEnvConfigured,
1089
+ isJmpTrackingConsentGranted,
880
1090
  registerJmpContentWrappers,
881
1091
  registerJmpTrustCapabilities,
882
- sendEarlyPageViewBeacon,
1092
+ setJmpTrackingConsent,
1093
+ subscribeJmpTrackingConsent,
883
1094
  trackJmpServerPageView
884
1095
  });
885
1096
  //# sourceMappingURL=index.cjs.map