@jmp-technologies/analytics 0.1.23 → 0.1.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +22 -1
  2. package/dist/astro/client.cjs.map +1 -1
  3. package/dist/astro/client.d.cts +2 -2
  4. package/dist/astro/client.d.ts +2 -2
  5. package/dist/astro/client.js +2 -2
  6. package/dist/astro/content.cjs.map +1 -1
  7. package/dist/astro/content.d.cts +2 -2
  8. package/dist/astro/content.d.ts +2 -2
  9. package/dist/astro/content.js +3 -3
  10. package/dist/astro/integration.cjs +1 -1
  11. package/dist/astro/integration.cjs.map +1 -1
  12. package/dist/astro/integration.js +3 -3
  13. package/dist/astro/middleware.cjs.map +1 -1
  14. package/dist/astro/middleware.d.cts +2 -2
  15. package/dist/astro/middleware.d.ts +2 -2
  16. package/dist/astro/middleware.js +2 -2
  17. package/dist/astro/register.cjs +1 -1
  18. package/dist/astro/register.cjs.map +1 -1
  19. package/dist/astro/register.js +3 -3
  20. package/dist/chunk-2KAGOVRZ.js +45 -0
  21. package/dist/chunk-2KAGOVRZ.js.map +1 -0
  22. package/dist/{chunk-G3SNRG7J.js → chunk-5GORAM7J.js} +2 -2
  23. package/dist/{chunk-776LXUWH.js → chunk-7MLPSL6T.js} +2 -2
  24. package/dist/{chunk-HIJ6OV4S.js → chunk-AJ33NQVZ.js} +3 -3
  25. package/dist/chunk-L67PVZYL.js +154 -0
  26. package/dist/chunk-L67PVZYL.js.map +1 -0
  27. package/dist/{chunk-B3FYJIXY.js → chunk-MOX7RJUU.js} +1 -1
  28. package/dist/{chunk-B3FYJIXY.js.map → chunk-MOX7RJUU.js.map} +1 -1
  29. package/dist/{chunk-QUNCGUEE.js → chunk-OLWCYWVB.js} +3 -3
  30. package/dist/{chunk-W6VYMD2P.js → chunk-VRDPVKAN.js} +6 -4
  31. package/dist/{chunk-W6VYMD2P.js.map → chunk-VRDPVKAN.js.map} +1 -1
  32. package/dist/{create-jmp-analytics-BdGOgPxl.d.ts → create-jmp-analytics-COxo3-yg.d.ts} +1 -1
  33. package/dist/{create-jmp-analytics-DxhHOmtR.d.cts → create-jmp-analytics-ClLOMb9p.d.cts} +1 -1
  34. package/dist/index.cjs +25 -24
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +6 -6
  37. package/dist/index.d.ts +6 -6
  38. package/dist/index.js +2 -2
  39. package/dist/next/content.cjs.map +1 -1
  40. package/dist/next/content.d.cts +2 -2
  41. package/dist/next/content.d.ts +2 -2
  42. package/dist/next/content.js +3 -3
  43. package/dist/next/google-tag.cjs +80 -0
  44. package/dist/next/google-tag.cjs.map +1 -0
  45. package/dist/next/google-tag.d.cts +17 -0
  46. package/dist/next/google-tag.d.ts +17 -0
  47. package/dist/next/google-tag.js +8 -0
  48. package/dist/next/google-tag.js.map +1 -0
  49. package/dist/next/instrumentation.cjs +1 -1
  50. package/dist/next/instrumentation.cjs.map +1 -1
  51. package/dist/next/instrumentation.js +2 -2
  52. package/dist/next/middleware.cjs.map +1 -1
  53. package/dist/next/middleware.d.cts +2 -2
  54. package/dist/next/middleware.d.ts +2 -2
  55. package/dist/next/middleware.js +2 -2
  56. package/dist/next/site-root-server.cjs +1134 -0
  57. package/dist/next/site-root-server.cjs.map +1 -0
  58. package/dist/next/site-root-server.d.cts +24 -0
  59. package/dist/next/site-root-server.d.ts +24 -0
  60. package/dist/next/site-root-server.js +62 -0
  61. package/dist/next/site-root-server.js.map +1 -0
  62. package/dist/next.cjs +110 -29
  63. package/dist/next.cjs.map +1 -1
  64. package/dist/next.d.cts +16 -7
  65. package/dist/next.d.ts +16 -7
  66. package/dist/next.js +15 -108
  67. package/dist/next.js.map +1 -1
  68. package/dist/react.cjs +8 -1
  69. package/dist/react.cjs.map +1 -1
  70. package/dist/react.d.cts +2 -2
  71. package/dist/react.d.ts +2 -2
  72. package/dist/react.js +3 -3
  73. package/dist/{site-config-BRuZWGSW.d.cts → site-config-8TTHIW6w.d.cts} +6 -1
  74. package/dist/{site-config-hkGMSeT7.d.ts → site-config-BSMVyUjk.d.ts} +6 -1
  75. package/dist/{track-page-view-Cr8I4Unm.d.cts → track-page-view-BweavmXz.d.cts} +1 -1
  76. package/dist/{track-page-view-CcPlzQNB.d.ts → track-page-view-DtxbdM5q.d.ts} +1 -1
  77. package/dist/{types-BtiK_Acj.d.ts → types-Bk0ST1aH.d.cts} +2 -0
  78. package/dist/{types-BtiK_Acj.d.cts → types-Bk0ST1aH.d.ts} +2 -0
  79. package/package.json +7 -2
  80. /package/dist/{chunk-G3SNRG7J.js.map → chunk-5GORAM7J.js.map} +0 -0
  81. /package/dist/{chunk-776LXUWH.js.map → chunk-7MLPSL6T.js.map} +0 -0
  82. /package/dist/{chunk-HIJ6OV4S.js.map → chunk-AJ33NQVZ.js.map} +0 -0
  83. /package/dist/{chunk-QUNCGUEE.js.map → chunk-OLWCYWVB.js.map} +0 -0
@@ -0,0 +1,1134 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/next/site-root-server.tsx
31
+ var site_root_server_exports = {};
32
+ __export(site_root_server_exports, {
33
+ JmpSiteRootServer: () => JmpSiteRootServer
34
+ });
35
+ module.exports = __toCommonJS(site_root_server_exports);
36
+
37
+ // src/constants.ts
38
+ var JMP_TRACKING_CONSENT_STORAGE_KEY = "jmp_analytics_consent_v1";
39
+ var DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 2500;
40
+
41
+ // src/http.ts
42
+ function responseLooksLikeHtml(body) {
43
+ const s = body.trimStart();
44
+ return s.startsWith("<!") || s.toLowerCase().startsWith("<html") || s.startsWith("<") && /<html[\s>]/i.test(s.slice(0, 500));
45
+ }
46
+ function normalizeBaseUrl(baseUrl) {
47
+ return baseUrl.replace(/\/$/, "");
48
+ }
49
+ function resolveFetch(fetchImpl, context) {
50
+ const resolved = fetchImpl ?? (typeof globalThis !== "undefined" && globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
51
+ if (!resolved) {
52
+ throw new Error(`${context}: fetch is not available; pass fetchImpl in config`);
53
+ }
54
+ return resolved;
55
+ }
56
+ function formatApiErrorMessage(status, text, prefix) {
57
+ if (responseLooksLikeHtml(text)) {
58
+ return `${prefix} HTTP ${status} \u2014 response was HTML (not the JSON API). Check baseUrl points at the JMP Analytics dashboard.`;
59
+ }
60
+ let parsed = {};
61
+ try {
62
+ parsed = JSON.parse(text);
63
+ } catch {
64
+ parsed = { error: text };
65
+ }
66
+ const detail = parsed.error ?? text;
67
+ return [
68
+ `${prefix} HTTP ${status}`,
69
+ parsed.code ? `[${parsed.code}]` : null,
70
+ detail,
71
+ parsed.hint ? `Hint: ${parsed.hint}` : null,
72
+ parsed.expectedDomain ? `Domain in JMP admin: ${parsed.expectedDomain}` : null
73
+ ].filter(Boolean).join(" \u2014 ");
74
+ }
75
+
76
+ // src/content/fetch.ts
77
+ async function getContent(config, path) {
78
+ const text = await getContentText(config, path);
79
+ try {
80
+ return JSON.parse(text);
81
+ } catch {
82
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
83
+ const url = `${baseUrl}${path}`;
84
+ throw new Error(`JMP content HTTP 200 \u2014 ${url} returned invalid JSON.`);
85
+ }
86
+ }
87
+ async function getContentText(config, path) {
88
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
89
+ const resolvedFetch = config.fetchImpl ?? (typeof globalThis !== "undefined" && globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
90
+ if (!resolvedFetch) {
91
+ throw new Error("JMP content: fetch is not available; pass fetchImpl in config");
92
+ }
93
+ const url = `${baseUrl}${path}`;
94
+ if (config.debug) {
95
+ console.debug("[@jmp-technologies/analytics]", "GET", url);
96
+ }
97
+ const res = await resolvedFetch(url, {
98
+ method: "GET",
99
+ headers: {
100
+ "X-JMP-Tracking-Key": config.trackingKey
101
+ }
102
+ });
103
+ const text = await res.text();
104
+ if (!res.ok) {
105
+ if (responseLooksLikeHtml(text)) {
106
+ throw new Error(
107
+ `JMP content HTTP ${res.status} \u2014 ${url} returned HTML (not the JSON API). Set baseUrl to your JMP Analytics dashboard origin.`
108
+ );
109
+ }
110
+ let parsed = {};
111
+ try {
112
+ parsed = JSON.parse(text);
113
+ } catch {
114
+ parsed = { error: text };
115
+ }
116
+ throw new Error(
117
+ [`JMP content HTTP ${res.status}`, parsed.error, parsed.hint].filter(Boolean).join(" \u2014 ")
118
+ );
119
+ }
120
+ return text;
121
+ }
122
+
123
+ // src/content/api.ts
124
+ async function getJmpSiteProfile(config) {
125
+ const data = await getContent(
126
+ config,
127
+ "/api/content/site"
128
+ );
129
+ return data.site;
130
+ }
131
+
132
+ // src/env-public.ts
133
+ function firstDefined(...values) {
134
+ for (const v of values) {
135
+ if (v) return v;
136
+ }
137
+ return void 0;
138
+ }
139
+ function readJmpPublicEnvFromProcessEnv() {
140
+ if (typeof process === "undefined" || !process.env) {
141
+ return {};
142
+ }
143
+ const { env } = process;
144
+ const analyticsUrl = firstDefined(
145
+ env.NEXT_PUBLIC_JMP_ANALYTICS_URL,
146
+ env.PUBLIC_JMP_ANALYTICS_URL
147
+ );
148
+ const trackingKey = firstDefined(
149
+ env.NEXT_PUBLIC_JMP_TRACKING_KEY,
150
+ env.PUBLIC_JMP_TRACKING_KEY
151
+ );
152
+ const requireConsentRaw = firstDefined(
153
+ env.NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT,
154
+ env.PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT
155
+ );
156
+ const autoContactRaw = firstDefined(
157
+ env.NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS,
158
+ env.PUBLIC_JMP_AUTO_CONTACT_LINKS
159
+ );
160
+ return {
161
+ analyticsUrl,
162
+ trackingKey,
163
+ requireConsent: requireConsentRaw === "true",
164
+ autoContactLinks: autoContactRaw === "true"
165
+ };
166
+ }
167
+ function readJmpPublicEnvFromProcess(overrides) {
168
+ const fromEnv = readJmpPublicEnvFromProcessEnv();
169
+ return {
170
+ analyticsUrl: firstDefined(overrides?.analyticsUrl, fromEnv.analyticsUrl),
171
+ trackingKey: firstDefined(overrides?.trackingKey, fromEnv.trackingKey),
172
+ requireConsent: overrides?.requireConsent ?? fromEnv.requireConsent,
173
+ autoContactLinks: overrides?.autoContactLinks ?? fromEnv.autoContactLinks
174
+ };
175
+ }
176
+
177
+ // src/site-config.ts
178
+ var registeredSite = null;
179
+ function getJmpSiteDefinition() {
180
+ return registeredSite;
181
+ }
182
+ function getJmpContentConfig() {
183
+ const { analyticsUrl, trackingKey } = readJmpPublicEnvFromProcess();
184
+ if (!analyticsUrl || !trackingKey) {
185
+ return null;
186
+ }
187
+ const site = getJmpSiteDefinition();
188
+ return {
189
+ baseUrl: analyticsUrl,
190
+ trackingKey,
191
+ contentWrappers: site?.contentWrappers ?? void 0
192
+ };
193
+ }
194
+
195
+ // src/next.tsx
196
+ var import_script2 = __toESM(require("next/script"), 1);
197
+ var import_react3 = require("react");
198
+ var import_navigation2 = require("next/navigation");
199
+
200
+ // src/landing-capture.ts
201
+ var JMP_SESSION_ID_KEY = "jmp_analytics_sid";
202
+ var JMP_LANDING_REFERER_KEY = "jmp_analytics_landing_referer";
203
+ var JMP_LANDING_REFERER_COOKIE = "jmp_lr";
204
+ var JMP_UTM_SESSION_KEY = "jmp_analytics_utm";
205
+ var LANDING_REFERER_COOKIE_MAX_AGE_SEC = 30 * 60;
206
+ var JMP_UTM_PARAM_KEYS = [
207
+ "utm_source",
208
+ "utm_medium",
209
+ "utm_campaign",
210
+ "utm_content",
211
+ "utm_term"
212
+ ];
213
+ function refererHostFromUrl(referer) {
214
+ const trimmed = referer.trim();
215
+ try {
216
+ return new URL(trimmed).hostname.replace(/^www\./i, "").toLowerCase();
217
+ } catch {
218
+ try {
219
+ return new URL(`https://${trimmed}`).hostname.replace(/^www\./i, "").toLowerCase();
220
+ } catch {
221
+ return null;
222
+ }
223
+ }
224
+ }
225
+ function isExternalReferrerUrl(referer, siteHostname) {
226
+ const refHost = refererHostFromUrl(referer);
227
+ if (!refHost) {
228
+ return false;
229
+ }
230
+ const site = siteHostname.replace(/^www\./i, "").toLowerCase();
231
+ return refHost !== site && !refHost.endsWith(`.${site}`);
232
+ }
233
+ function registrableSiteDomain(siteHostname) {
234
+ const site = siteHostname.replace(/^www\./i, "").toLowerCase();
235
+ if (!site || site === "localhost" || site.endsWith(".local")) {
236
+ return null;
237
+ }
238
+ if (!site.includes(".")) {
239
+ return null;
240
+ }
241
+ return site;
242
+ }
243
+ function readLandingRefererCookie(siteHostname) {
244
+ if (typeof document === "undefined") {
245
+ return null;
246
+ }
247
+ const apex = registrableSiteDomain(siteHostname);
248
+ if (!apex) {
249
+ return null;
250
+ }
251
+ const prefix = `${JMP_LANDING_REFERER_COOKIE}=`;
252
+ for (const part of document.cookie.split(";")) {
253
+ const trimmed = part.trim();
254
+ if (!trimmed.startsWith(prefix)) {
255
+ continue;
256
+ }
257
+ try {
258
+ const value = decodeURIComponent(trimmed.slice(prefix.length)).trim();
259
+ return value.length > 0 ? value : null;
260
+ } catch {
261
+ return null;
262
+ }
263
+ }
264
+ return null;
265
+ }
266
+ function writeLandingRefererCookie(referer, siteHostname) {
267
+ if (typeof document === "undefined") {
268
+ return;
269
+ }
270
+ const apex = registrableSiteDomain(siteHostname);
271
+ if (!apex) {
272
+ return;
273
+ }
274
+ const value = encodeURIComponent(referer.trim().slice(0, 2048));
275
+ const secure = typeof window !== "undefined" && window.location.protocol === "https:" ? "; Secure" : "";
276
+ document.cookie = `${JMP_LANDING_REFERER_COOKIE}=${value}; Domain=.${apex}; Path=/; Max-Age=${LANDING_REFERER_COOKIE_MAX_AGE_SEC}; SameSite=Lax${secure}`;
277
+ }
278
+ function captureLandingAttribution(siteHostname) {
279
+ if (typeof document === "undefined" || typeof window === "undefined") {
280
+ return { landingReferer: null, utm: {} };
281
+ }
282
+ let landingReferer = null;
283
+ let utm = {};
284
+ try {
285
+ const storedReferer = sessionStorage.getItem(JMP_LANDING_REFERER_KEY)?.trim() || null;
286
+ const cookieReferer = readLandingRefererCookie(siteHostname);
287
+ const preservedReferer = storedReferer || cookieReferer;
288
+ const currentReferer = document.referrer?.trim() || null;
289
+ if (currentReferer && isExternalReferrerUrl(currentReferer, siteHostname)) {
290
+ sessionStorage.setItem(JMP_LANDING_REFERER_KEY, currentReferer);
291
+ writeLandingRefererCookie(currentReferer, siteHostname);
292
+ landingReferer = currentReferer;
293
+ } else if (preservedReferer) {
294
+ landingReferer = preservedReferer;
295
+ if (!storedReferer) {
296
+ sessionStorage.setItem(JMP_LANDING_REFERER_KEY, preservedReferer);
297
+ }
298
+ }
299
+ const params = new URLSearchParams(window.location.search);
300
+ const rawUtm = sessionStorage.getItem(JMP_UTM_SESSION_KEY);
301
+ if (rawUtm) {
302
+ const parsed = JSON.parse(rawUtm);
303
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
304
+ utm = parsed;
305
+ }
306
+ }
307
+ let updated = false;
308
+ for (const key of JMP_UTM_PARAM_KEYS) {
309
+ const value = params.get(key)?.trim();
310
+ if (value) {
311
+ utm[key] = value;
312
+ updated = true;
313
+ }
314
+ }
315
+ if (updated) {
316
+ sessionStorage.setItem(JMP_UTM_SESSION_KEY, JSON.stringify(utm));
317
+ }
318
+ } catch {
319
+ }
320
+ return { landingReferer, utm };
321
+ }
322
+ function getOrCreateSessionIdFromStorage() {
323
+ if (typeof window === "undefined" || !globalThis.crypto?.randomUUID) {
324
+ return void 0;
325
+ }
326
+ try {
327
+ let id = sessionStorage.getItem(JMP_SESSION_ID_KEY);
328
+ if (!id) {
329
+ id = crypto.randomUUID();
330
+ sessionStorage.setItem(JMP_SESSION_ID_KEY, id);
331
+ }
332
+ return id;
333
+ } catch {
334
+ return void 0;
335
+ }
336
+ }
337
+ function buildLandingCaptureInlineScript() {
338
+ const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC);
339
+ 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){}})();`;
340
+ }
341
+
342
+ // src/tracker/page-view-dedupe.ts
343
+ var JMP_PAGE_VIEW_DEDUPE_STORAGE_KEY = "jmp_analytics_last_pv";
344
+ var moduleLastPath = "";
345
+ var moduleLastAt = 0;
346
+ function shouldDedupeBrowserPageView(pathname, dedupeMs, storage = null) {
347
+ if (dedupeMs <= 0) {
348
+ return false;
349
+ }
350
+ const now = Date.now();
351
+ if (pathname === moduleLastPath && now - moduleLastAt < dedupeMs) {
352
+ return true;
353
+ }
354
+ try {
355
+ const raw = storage?.getItem(JMP_PAGE_VIEW_DEDUPE_STORAGE_KEY);
356
+ if (raw) {
357
+ const prev = JSON.parse(raw);
358
+ if (prev.path === pathname && now - prev.at < dedupeMs) {
359
+ return true;
360
+ }
361
+ }
362
+ storage?.setItem(
363
+ JMP_PAGE_VIEW_DEDUPE_STORAGE_KEY,
364
+ JSON.stringify({ path: pathname, at: now })
365
+ );
366
+ } catch {
367
+ }
368
+ moduleLastPath = pathname;
369
+ moduleLastAt = now;
370
+ return false;
371
+ }
372
+
373
+ // src/contact-link-classifier.ts
374
+ var BOOKING_LINK_HOSTS = [
375
+ "calendly.com",
376
+ "cal.com",
377
+ "acuityscheduling.com",
378
+ "calendar.google.com",
379
+ "calendar.app.google",
380
+ "bookings.microsoft.com",
381
+ "outlook.office.com",
382
+ "outlook.office365.com",
383
+ "book.ms",
384
+ "setmore.com",
385
+ "simplybook.me",
386
+ "oncehub.com",
387
+ "scheduleonce.com",
388
+ "youcanbook.me",
389
+ "savvycal.com",
390
+ "tidycal.com",
391
+ "zohobookings.com",
392
+ "square.site",
393
+ "squareup.com",
394
+ "meetings.hubspot.com",
395
+ "jobber.com",
396
+ "housecallpro.com",
397
+ "servicetitan.com",
398
+ "thryv.com",
399
+ "honeybook.com",
400
+ "dubsado.com",
401
+ "fresha.com",
402
+ "booksy.com",
403
+ "vagaro.com",
404
+ "mindbodyonline.com",
405
+ "mindbody.io",
406
+ "janeapp.com",
407
+ "cliniko.com",
408
+ "practicebetter.io"
409
+ ];
410
+ var WHATSAPP_HOSTS = ["wa.me", "api.whatsapp.com", "whatsapp.com"];
411
+ function hostnameMatches(host, pattern) {
412
+ const h = host.toLowerCase();
413
+ const p = pattern.toLowerCase();
414
+ return h === p || h.endsWith(`.${p}`);
415
+ }
416
+ function isMapsHost(host, pathname) {
417
+ if (hostnameMatches(host, "maps.apple.com")) {
418
+ return true;
419
+ }
420
+ if (hostnameMatches(host, "maps.app.goo.gl")) {
421
+ return true;
422
+ }
423
+ if (hostnameMatches(host, "google.com") || hostnameMatches(host, "google.co")) {
424
+ return pathname === "/maps" || pathname.startsWith("/maps/") || pathname.startsWith("/local");
425
+ }
426
+ return false;
427
+ }
428
+ function isWhatsAppHost(host, pathname) {
429
+ for (const pattern of WHATSAPP_HOSTS) {
430
+ if (!hostnameMatches(host, pattern)) {
431
+ continue;
432
+ }
433
+ if (pattern === "whatsapp.com") {
434
+ return pathname.startsWith("/send");
435
+ }
436
+ return true;
437
+ }
438
+ return false;
439
+ }
440
+ function isBookingHost(host) {
441
+ for (const pattern of BOOKING_LINK_HOSTS) {
442
+ if (hostnameMatches(host, pattern)) {
443
+ return true;
444
+ }
445
+ }
446
+ return false;
447
+ }
448
+ function classifyContactHref(href) {
449
+ const raw = href.trim();
450
+ if (!raw || raw.startsWith("#") || raw.startsWith("javascript:")) {
451
+ return null;
452
+ }
453
+ const lower = raw.toLowerCase();
454
+ if (lower.startsWith("tel:")) {
455
+ return { kind: "call" };
456
+ }
457
+ if (lower.startsWith("mailto:")) {
458
+ return { kind: "email" };
459
+ }
460
+ if (lower.startsWith("sms:") || lower.startsWith("smsto:")) {
461
+ return { kind: "contact_click", channel: "sms", linkHost: null };
462
+ }
463
+ if (lower.startsWith("geo:")) {
464
+ return { kind: "contact_click", channel: "maps", linkHost: null };
465
+ }
466
+ if (raw.startsWith("/") || raw.startsWith("?")) {
467
+ return null;
468
+ }
469
+ let url;
470
+ try {
471
+ url = new URL(raw);
472
+ } catch {
473
+ return null;
474
+ }
475
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
476
+ return null;
477
+ }
478
+ const host = url.hostname.toLowerCase();
479
+ const pathname = url.pathname.toLowerCase();
480
+ if (isWhatsAppHost(host, pathname)) {
481
+ return { kind: "contact_click", channel: "whatsapp", linkHost: host };
482
+ }
483
+ if (isMapsHost(host, pathname)) {
484
+ return { kind: "contact_click", channel: "maps", linkHost: host };
485
+ }
486
+ if (isBookingHost(host)) {
487
+ return { kind: "contact_click", channel: "booking", linkHost: host };
488
+ }
489
+ return null;
490
+ }
491
+
492
+ // src/consent.ts
493
+ var moduleTrackingConsentGranted = true;
494
+ var trackingConsentListeners = /* @__PURE__ */ new Set();
495
+ function readStoredTrackingConsent() {
496
+ if (typeof window === "undefined") {
497
+ return false;
498
+ }
499
+ try {
500
+ return localStorage.getItem(JMP_TRACKING_CONSENT_STORAGE_KEY) === "granted";
501
+ } catch {
502
+ return false;
503
+ }
504
+ }
505
+ function initJmpTrackingConsent(requireConsent) {
506
+ moduleTrackingConsentGranted = requireConsent ? readStoredTrackingConsent() : true;
507
+ }
508
+ function isJmpTrackingConsentGranted() {
509
+ return moduleTrackingConsentGranted;
510
+ }
511
+ function subscribeJmpTrackingConsent(listener) {
512
+ trackingConsentListeners.add(listener);
513
+ return () => {
514
+ trackingConsentListeners.delete(listener);
515
+ };
516
+ }
517
+ function setJmpTrackingConsent(granted) {
518
+ if (moduleTrackingConsentGranted === granted) {
519
+ return;
520
+ }
521
+ moduleTrackingConsentGranted = granted;
522
+ if (typeof window !== "undefined") {
523
+ try {
524
+ localStorage.setItem(
525
+ JMP_TRACKING_CONSENT_STORAGE_KEY,
526
+ granted ? "granted" : "denied"
527
+ );
528
+ } catch {
529
+ }
530
+ if (granted) {
531
+ captureLandingAttribution(window.location.hostname);
532
+ }
533
+ }
534
+ for (const listener of trackingConsentListeners) {
535
+ listener();
536
+ }
537
+ }
538
+
539
+ // src/tracker/helpers.ts
540
+ function captureAndGetLandingReferer() {
541
+ if (typeof window === "undefined") {
542
+ return null;
543
+ }
544
+ return captureLandingAttribution(window.location.hostname).landingReferer;
545
+ }
546
+ function mergeSessionUtms(metadata) {
547
+ if (typeof window === "undefined") {
548
+ return;
549
+ }
550
+ const { utm } = captureLandingAttribution(window.location.hostname);
551
+ for (const key of JMP_UTM_PARAM_KEYS) {
552
+ if (metadata[key] === void 0 && utm[key]) {
553
+ metadata[key] = utm[key];
554
+ }
555
+ }
556
+ }
557
+ function splitPathAndSearch(pathInput) {
558
+ const qIndex = pathInput.indexOf("?");
559
+ if (qIndex === -1) {
560
+ return { pathname: pathInput || "/", search: "" };
561
+ }
562
+ return {
563
+ pathname: pathInput.slice(0, qIndex) || "/",
564
+ search: pathInput.slice(qIndex + 1)
565
+ };
566
+ }
567
+ function inferDevice() {
568
+ if (typeof window === "undefined") {
569
+ return "unknown";
570
+ }
571
+ return window.innerWidth < 768 ? "mobile" : "desktop";
572
+ }
573
+
574
+ // src/tracker/create-jmp-analytics.ts
575
+ function createJmpAnalytics(config) {
576
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
577
+ const fetchFn = resolveFetch(config.fetchImpl, "createJmpAnalytics");
578
+ initJmpTrackingConsent(config.requireConsent);
579
+ function canSend() {
580
+ return isJmpTrackingConsentGranted();
581
+ }
582
+ async function send(body) {
583
+ if (!canSend()) {
584
+ return;
585
+ }
586
+ const url = `${baseUrl}/api/events`;
587
+ const headers = {
588
+ "Content-Type": "application/json",
589
+ "X-JMP-Tracking-Key": config.trackingKey
590
+ };
591
+ if (body.type === "page_view" && typeof window !== "undefined") {
592
+ const landingReferer = captureAndGetLandingReferer();
593
+ if (landingReferer) {
594
+ headers["X-JMP-Visitor-Referer"] = landingReferer;
595
+ }
596
+ }
597
+ const sid = getOrCreateSessionIdFromStorage();
598
+ const payload = { ...body, ...sid ? { sessionId: sid } : {} };
599
+ if (config.debug) {
600
+ console.debug("[@jmp-technologies/analytics]", "POST", url, payload);
601
+ }
602
+ const res = await fetchFn(url, {
603
+ method: "POST",
604
+ headers,
605
+ body: JSON.stringify(payload),
606
+ keepalive: true
607
+ });
608
+ if (!res.ok) {
609
+ const text = await res.text();
610
+ const message = formatApiErrorMessage(res.status, text, "JMP Analytics");
611
+ if (config.debug) {
612
+ console.debug("[@jmp-technologies/analytics]", "error response", { status: res.status, raw: text });
613
+ }
614
+ throw new Error(message);
615
+ }
616
+ }
617
+ async function sendLead(body) {
618
+ if (!canSend()) {
619
+ return;
620
+ }
621
+ const url = `${baseUrl}/api/leads`;
622
+ const headers = {
623
+ "Content-Type": "application/json",
624
+ "X-JMP-Tracking-Key": config.trackingKey
625
+ };
626
+ const sid = getOrCreateSessionIdFromStorage();
627
+ const payload = { ...body, ...sid ? { sessionId: sid } : {} };
628
+ if (config.debug) {
629
+ console.debug("[@jmp-technologies/analytics]", "POST", url, payload);
630
+ }
631
+ const res = await fetchFn(url, {
632
+ method: "POST",
633
+ headers,
634
+ body: JSON.stringify(payload),
635
+ keepalive: true
636
+ });
637
+ if (!res.ok) {
638
+ const text = await res.text();
639
+ const message = formatApiErrorMessage(res.status, text, "JMP Analytics");
640
+ if (config.debug) {
641
+ console.debug("[@jmp-technologies/analytics]", "error response", { status: res.status, raw: text });
642
+ }
643
+ throw new Error(message);
644
+ }
645
+ }
646
+ function trackPageView(options) {
647
+ if (!canSend()) {
648
+ return Promise.resolve();
649
+ }
650
+ const pathFromOptions = options?.path?.trim();
651
+ let pathname = "/";
652
+ let search = "";
653
+ if (pathFromOptions) {
654
+ const split = splitPathAndSearch(pathFromOptions);
655
+ pathname = split.pathname;
656
+ search = split.search;
657
+ } else if (typeof window !== "undefined") {
658
+ pathname = window.location.pathname;
659
+ search = window.location.search.replace(/^\?/, "");
660
+ }
661
+ if (!search && typeof window !== "undefined") {
662
+ search = window.location.search.replace(/^\?/, "");
663
+ }
664
+ const path = search ? `${pathname}?${search}` : pathname;
665
+ const dedupeMs = config.pageViewDedupeMs ?? DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS;
666
+ const storage = typeof window !== "undefined" ? window.sessionStorage : null;
667
+ if (shouldDedupeBrowserPageView(pathname, dedupeMs, storage)) {
668
+ return Promise.resolve();
669
+ }
670
+ const metadata = options?.metadata && typeof options.metadata === "object" ? { ...options.metadata } : {};
671
+ if (typeof window !== "undefined") {
672
+ metadata.pageHostname = window.location.hostname;
673
+ const params = new URLSearchParams(
674
+ search ? `?${search}` : window.location.search
675
+ );
676
+ for (const key of JMP_UTM_PARAM_KEYS) {
677
+ const v = params.get(key);
678
+ if (v && metadata[key] === void 0) {
679
+ metadata[key] = v;
680
+ }
681
+ }
682
+ mergeSessionUtms(metadata);
683
+ const landingReferer = captureAndGetLandingReferer();
684
+ if (landingReferer && metadata.referer === void 0) {
685
+ metadata.referer = landingReferer;
686
+ }
687
+ }
688
+ return send({
689
+ type: "page_view",
690
+ path: path || "/",
691
+ device: options?.device ?? inferDevice(),
692
+ country: options?.country,
693
+ metadata
694
+ });
695
+ }
696
+ function trackFormSubmit(path, metadata) {
697
+ return send({
698
+ type: "form_submit",
699
+ path: path || "/",
700
+ metadata: metadata ?? {}
701
+ });
702
+ }
703
+ function trackCallClick(path, metadata) {
704
+ return send({
705
+ type: "call_click",
706
+ path: path || "/",
707
+ metadata: metadata ?? {}
708
+ });
709
+ }
710
+ function trackEmailClick(path, metadata) {
711
+ return send({
712
+ type: "email_click",
713
+ path: path || "/",
714
+ metadata: metadata ?? {}
715
+ });
716
+ }
717
+ function trackContactClick(path, options) {
718
+ const metadata = {
719
+ ...options.metadata && typeof options.metadata === "object" ? options.metadata : {},
720
+ channel: options.channel
721
+ };
722
+ if (options.linkHost) {
723
+ metadata.linkHost = options.linkHost;
724
+ }
725
+ return send({
726
+ type: "contact_click",
727
+ path: path || "/",
728
+ metadata
729
+ });
730
+ }
731
+ function trackLead(options) {
732
+ const path = options?.path ?? (typeof window !== "undefined" ? window.location.pathname : "/");
733
+ const body = { path: path || "/" };
734
+ if (options?.name) body.name = options.name;
735
+ if (options?.email) body.email = options.email;
736
+ if (options?.phone) body.phone = options.phone;
737
+ if (options?.company) body.company = options.company;
738
+ if (options?.website) body.website = options.website;
739
+ if (options?.subject) body.subject = options.subject;
740
+ if (options?.message) body.message = options.message;
741
+ if (options?.metadata && typeof options.metadata === "object") {
742
+ body.metadata = options.metadata;
743
+ }
744
+ if (options?.sessionId) body.sessionId = options.sessionId;
745
+ return sendLead(body);
746
+ }
747
+ function track(type, payload) {
748
+ if (type === "page_view") {
749
+ return trackPageView({
750
+ path: payload.path,
751
+ source: payload.source,
752
+ device: payload.device,
753
+ country: payload.country,
754
+ metadata: payload.metadata
755
+ });
756
+ }
757
+ if (type === "form_submit") {
758
+ return trackFormSubmit(payload.path, payload.metadata);
759
+ }
760
+ if (type === "call_click") {
761
+ return trackCallClick(payload.path, payload.metadata);
762
+ }
763
+ if (type === "email_click") {
764
+ return trackEmailClick(payload.path, payload.metadata);
765
+ }
766
+ const meta = payload.metadata ?? {};
767
+ const channel = typeof meta.channel === "string" ? meta.channel : "";
768
+ const linkHost = typeof meta.linkHost === "string" ? meta.linkHost : null;
769
+ if (channel !== "sms" && channel !== "whatsapp" && channel !== "maps" && channel !== "booking") {
770
+ return Promise.resolve();
771
+ }
772
+ return trackContactClick(payload.path, {
773
+ channel,
774
+ linkHost,
775
+ metadata: meta
776
+ });
777
+ }
778
+ function subscribeToSpaNavigation() {
779
+ if (typeof window === "undefined") {
780
+ return () => {
781
+ };
782
+ }
783
+ let lastPath = window.location.pathname;
784
+ const run = () => {
785
+ const path = window.location.pathname;
786
+ if (path !== lastPath) {
787
+ lastPath = path;
788
+ void trackPageView({ path });
789
+ }
790
+ };
791
+ window.addEventListener("popstate", run);
792
+ const push = history.pushState.bind(history);
793
+ const replace = history.replaceState.bind(history);
794
+ history.pushState = (...args) => {
795
+ const r = push(...args);
796
+ queueMicrotask(run);
797
+ return r;
798
+ };
799
+ history.replaceState = (...args) => {
800
+ const r = replace(...args);
801
+ queueMicrotask(run);
802
+ return r;
803
+ };
804
+ return () => {
805
+ window.removeEventListener("popstate", run);
806
+ history.pushState = push;
807
+ history.replaceState = replace;
808
+ };
809
+ }
810
+ let lastContactClickKey = "";
811
+ let lastContactClickAt = 0;
812
+ function subscribeContactLinkAutoTrack() {
813
+ if (typeof window === "undefined" || typeof document === "undefined") {
814
+ return () => {
815
+ };
816
+ }
817
+ const handler = (event) => {
818
+ if (!canSend()) {
819
+ return;
820
+ }
821
+ const target = event.target;
822
+ if (!(target instanceof Element)) {
823
+ return;
824
+ }
825
+ const anchor = target.closest("a[href]");
826
+ if (!(anchor instanceof HTMLAnchorElement)) {
827
+ return;
828
+ }
829
+ if (anchor.closest("[data-jmp-no-track]") || anchor.closest("[data-jmp-tracked]")) {
830
+ return;
831
+ }
832
+ const href = anchor.getAttribute("href") ?? "";
833
+ const classified = classifyContactHref(href);
834
+ if (!classified) {
835
+ return;
836
+ }
837
+ const path = window.location.pathname;
838
+ if (classified.kind === "call") {
839
+ if (dedupeContactClick(`call_click:${path}`)) {
840
+ return;
841
+ }
842
+ void trackCallClick(path);
843
+ return;
844
+ }
845
+ if (classified.kind === "email") {
846
+ if (dedupeContactClick(`email_click:${path}`)) {
847
+ return;
848
+ }
849
+ void trackEmailClick(path);
850
+ return;
851
+ }
852
+ if (dedupeContactClick(`contact_click:${classified.channel}:${path}`)) {
853
+ return;
854
+ }
855
+ void trackContactClick(path, {
856
+ channel: classified.channel,
857
+ linkHost: classified.linkHost
858
+ });
859
+ };
860
+ document.addEventListener("click", handler, { capture: true });
861
+ return () => {
862
+ document.removeEventListener("click", handler, { capture: true });
863
+ };
864
+ }
865
+ function dedupeContactClick(key) {
866
+ const now = Date.now();
867
+ if (key === lastContactClickKey && now - lastContactClickAt < 1e3) {
868
+ return true;
869
+ }
870
+ lastContactClickKey = key;
871
+ lastContactClickAt = now;
872
+ return false;
873
+ }
874
+ if (typeof window !== "undefined" && canSend()) {
875
+ captureLandingAttribution(window.location.hostname);
876
+ }
877
+ if (typeof window !== "undefined" && config.autoTrackContactLinks && canSend()) {
878
+ subscribeContactLinkAutoTrack();
879
+ }
880
+ return {
881
+ track,
882
+ trackPageView,
883
+ trackFormSubmit,
884
+ trackCallClick,
885
+ trackEmailClick,
886
+ trackContactClick,
887
+ trackLead,
888
+ subscribeToSpaNavigation,
889
+ subscribeContactLinkAutoTrack,
890
+ setTrackingConsent: setJmpTrackingConsent,
891
+ isTrackingConsentGranted: isJmpTrackingConsentGranted
892
+ };
893
+ }
894
+
895
+ // src/env/browser.ts
896
+ function getJmpBrowserAnalyticsConfigFromEnv(overrides) {
897
+ const pub = readJmpPublicEnvFromProcess();
898
+ const site = getJmpSiteDefinition();
899
+ const baseUrl = overrides?.baseUrl ?? pub.analyticsUrl ?? site?.analyticsPortalUrl;
900
+ const trackingKey = overrides?.trackingKey ?? pub.trackingKey;
901
+ if (!baseUrl || !trackingKey) return null;
902
+ return {
903
+ baseUrl,
904
+ trackingKey,
905
+ pageViewDedupeMs: DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
906
+ ...overrides,
907
+ requireConsent: overrides?.requireConsent ?? pub.requireConsent,
908
+ autoTrackContactLinks: overrides?.autoTrackContactLinks ?? pub.autoContactLinks
909
+ };
910
+ }
911
+ var jmpAnalyticsBrowserSingleton = null;
912
+ function getOrCreateJmpAnalyticsFromBrowserEnv(overrides) {
913
+ if (typeof window === "undefined") return null;
914
+ if (jmpAnalyticsBrowserSingleton) return jmpAnalyticsBrowserSingleton;
915
+ const config = getJmpBrowserAnalyticsConfigFromEnv(overrides);
916
+ if (!config) return null;
917
+ jmpAnalyticsBrowserSingleton = createJmpAnalytics(config);
918
+ return jmpAnalyticsBrowserSingleton;
919
+ }
920
+
921
+ // src/env/browser-next.ts
922
+ function readNextAutoContactLinksEnv() {
923
+ if (typeof process === "undefined" || !process.env) {
924
+ return void 0;
925
+ }
926
+ const { env } = process;
927
+ const raw = env.NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS ?? env.PUBLIC_JMP_AUTO_CONTACT_LINKS;
928
+ return typeof raw === "string" && raw.length > 0 ? raw : void 0;
929
+ }
930
+ function getJmpNextAnalyticsConfigOverrides() {
931
+ const autoEnv = readNextAutoContactLinksEnv();
932
+ const autoContactLinks = autoEnv === "false" ? false : autoEnv === "true" ? true : true;
933
+ return { autoTrackContactLinks: autoContactLinks };
934
+ }
935
+ function getOrCreateJmpAnalyticsForNextApp(overrides) {
936
+ return getOrCreateJmpAnalyticsFromBrowserEnv({
937
+ ...getJmpNextAnalyticsConfigOverrides(),
938
+ ...overrides
939
+ });
940
+ }
941
+
942
+ // src/react.tsx
943
+ var import_react = require("react");
944
+ var import_jsx_runtime = require("react/jsx-runtime");
945
+
946
+ // src/next/google-tag.tsx
947
+ var import_script = __toESM(require("next/script"), 1);
948
+ var import_navigation = require("next/navigation");
949
+ var import_react2 = require("react");
950
+ var import_jsx_runtime2 = require("react/jsx-runtime");
951
+ function JmpGoogleTag({ gaId }) {
952
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
953
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
954
+ import_script.default,
955
+ {
956
+ src: `https://www.googletagmanager.com/gtag/js?id=${gaId}`,
957
+ strategy: "lazyOnload"
958
+ }
959
+ ),
960
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_script.default, { id: "jmp-ga4-init", strategy: "lazyOnload", children: `
961
+ window.dataLayer = window.dataLayer || [];
962
+ function gtag(){dataLayer.push(arguments);}
963
+ gtag('js', new Date());
964
+ gtag('config', '${gaId}', { send_page_view: true });
965
+ ` }),
966
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(JmpGoogleTagPagePath, { gaId })
967
+ ] });
968
+ }
969
+ function JmpGoogleTagPagePath({ gaId }) {
970
+ const pathname = (0, import_navigation.usePathname)();
971
+ const isFirstNavigation = (0, import_react2.useRef)(true);
972
+ (0, import_react2.useEffect)(() => {
973
+ if (isFirstNavigation.current) {
974
+ isFirstNavigation.current = false;
975
+ return;
976
+ }
977
+ const report = () => {
978
+ window.gtag?.("config", gaId, { page_path: pathname || "/" });
979
+ };
980
+ report();
981
+ const timer = window.setTimeout(report, 100);
982
+ return () => window.clearTimeout(timer);
983
+ }, [gaId, pathname]);
984
+ return null;
985
+ }
986
+
987
+ // src/next.tsx
988
+ var import_jsx_runtime3 = require("react/jsx-runtime");
989
+ function JmpLandingCaptureScript({
990
+ trackingKey = readJmpPublicEnvFromProcess().trackingKey
991
+ } = {}) {
992
+ if (!trackingKey?.trim()) {
993
+ return null;
994
+ }
995
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
996
+ import_script2.default,
997
+ {
998
+ id: "jmp-landing-capture",
999
+ strategy: "beforeInteractive",
1000
+ dangerouslySetInnerHTML: {
1001
+ __html: buildLandingCaptureInlineScript()
1002
+ }
1003
+ }
1004
+ );
1005
+ }
1006
+ function JmpNextPageViewTrackerInner({
1007
+ configOverrides
1008
+ }) {
1009
+ const pathname = (0, import_navigation2.usePathname)();
1010
+ const searchParams = (0, import_navigation2.useSearchParams)();
1011
+ const query = searchParams?.toString() ?? "";
1012
+ const path = query ? `${pathname}?${query}` : pathname;
1013
+ (0, import_react3.useLayoutEffect)(() => {
1014
+ const client = getOrCreateJmpAnalyticsForNextApp(configOverrides);
1015
+ void client?.trackPageView({ path });
1016
+ }, [path, configOverrides]);
1017
+ return null;
1018
+ }
1019
+ function JmpNextPageViewTracker({
1020
+ configOverrides
1021
+ }) {
1022
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react3.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(JmpNextPageViewTrackerInner, { configOverrides }) });
1023
+ }
1024
+ function useJmpTrackingActive(deferUntilConsent) {
1025
+ const consentGranted = (0, import_react3.useSyncExternalStore)(
1026
+ subscribeJmpTrackingConsent,
1027
+ () => isJmpTrackingConsentGranted(),
1028
+ () => false
1029
+ );
1030
+ return !deferUntilConsent || consentGranted;
1031
+ }
1032
+ function jmpConfigOverridesFromProps(props) {
1033
+ const { analyticsUrl, trackingKey } = props;
1034
+ if (!analyticsUrl?.trim() && !trackingKey?.trim()) {
1035
+ return void 0;
1036
+ }
1037
+ return {
1038
+ ...analyticsUrl?.trim() ? { baseUrl: analyticsUrl.trim() } : {},
1039
+ ...trackingKey?.trim() ? { trackingKey: trackingKey.trim() } : {}
1040
+ };
1041
+ }
1042
+ function JmpNextAnalyticsBootstrap({
1043
+ configOverrides
1044
+ }) {
1045
+ (0, import_react3.useLayoutEffect)(() => {
1046
+ getOrCreateJmpAnalyticsForNextApp(configOverrides);
1047
+ }, [configOverrides]);
1048
+ return null;
1049
+ }
1050
+ function JmpNextAnalytics({
1051
+ deferUntilConsent = readJmpPublicEnvFromProcess().requireConsent === true,
1052
+ analyticsUrl,
1053
+ trackingKey
1054
+ } = {}) {
1055
+ const active = useJmpTrackingActive(deferUntilConsent);
1056
+ const configOverrides = (0, import_react3.useMemo)(
1057
+ () => jmpConfigOverridesFromProps({ analyticsUrl, trackingKey }),
1058
+ [analyticsUrl, trackingKey]
1059
+ );
1060
+ if (!active) {
1061
+ return null;
1062
+ }
1063
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1064
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(JmpNextAnalyticsBootstrap, { configOverrides }),
1065
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(JmpLandingCaptureScript, { trackingKey }),
1066
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(JmpNextPageViewTracker, { configOverrides })
1067
+ ] });
1068
+ }
1069
+ function JmpSiteRoot({
1070
+ children,
1071
+ deferUntilConsent,
1072
+ analyticsUrl,
1073
+ trackingKey
1074
+ }) {
1075
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1076
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1077
+ JmpNextAnalytics,
1078
+ {
1079
+ deferUntilConsent,
1080
+ analyticsUrl,
1081
+ trackingKey
1082
+ }
1083
+ ),
1084
+ children
1085
+ ] });
1086
+ }
1087
+
1088
+ // src/next/site-root-server.tsx
1089
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1090
+ async function resolveGaMeasurementId(gaFromPortal) {
1091
+ const fromEnv = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID?.trim();
1092
+ if (fromEnv) {
1093
+ return fromEnv;
1094
+ }
1095
+ if (!gaFromPortal) {
1096
+ return null;
1097
+ }
1098
+ const config = getJmpContentConfig();
1099
+ if (!config) {
1100
+ return null;
1101
+ }
1102
+ try {
1103
+ const profile = await getJmpSiteProfile(config);
1104
+ return profile.ga_measurement_id?.trim() || null;
1105
+ } catch {
1106
+ return null;
1107
+ }
1108
+ }
1109
+ async function JmpSiteRootServer({
1110
+ children,
1111
+ deferUntilConsent,
1112
+ gaFromPortal = true
1113
+ }) {
1114
+ const pub = readJmpPublicEnvFromProcess();
1115
+ const site = getJmpSiteDefinition();
1116
+ const gaId = await resolveGaMeasurementId(gaFromPortal);
1117
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1118
+ gaId ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(JmpGoogleTag, { gaId }) : null,
1119
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1120
+ JmpSiteRoot,
1121
+ {
1122
+ analyticsUrl: pub.analyticsUrl ?? site?.analyticsPortalUrl,
1123
+ trackingKey: pub.trackingKey,
1124
+ deferUntilConsent,
1125
+ children
1126
+ }
1127
+ )
1128
+ ] });
1129
+ }
1130
+ // Annotate the CommonJS export names for ESM import in node:
1131
+ 0 && (module.exports = {
1132
+ JmpSiteRootServer
1133
+ });
1134
+ //# sourceMappingURL=site-root-server.cjs.map