@jmp-technologies/analytics 0.1.20 → 0.1.22

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 +7 -7
  2. package/dist/astro/client.cjs +93 -108
  3. package/dist/astro/client.cjs.map +1 -1
  4. package/dist/astro/client.d.cts +3 -12
  5. package/dist/astro/client.d.ts +3 -12
  6. package/dist/astro/client.js +4 -2
  7. package/dist/astro/client.js.map +1 -1
  8. package/dist/astro/content.cjs +106 -98
  9. package/dist/astro/content.cjs.map +1 -1
  10. package/dist/astro/content.d.cts +2 -2
  11. package/dist/astro/content.d.ts +2 -2
  12. package/dist/astro/content.js +3 -2
  13. package/dist/astro/integration.cjs +68 -60
  14. package/dist/astro/integration.cjs.map +1 -1
  15. package/dist/astro/integration.js +3 -2
  16. package/dist/astro/integration.js.map +1 -1
  17. package/dist/astro/middleware.cjs +66 -63
  18. package/dist/astro/middleware.cjs.map +1 -1
  19. package/dist/astro/middleware.d.cts +2 -2
  20. package/dist/astro/middleware.d.ts +2 -2
  21. package/dist/astro/middleware.js +2 -2
  22. package/dist/astro/register.cjs +68 -60
  23. package/dist/astro/register.cjs.map +1 -1
  24. package/dist/astro/register.js +3 -2
  25. package/dist/{chunk-UDNKWFBM.js → chunk-3U2BSIYX.js} +5 -3
  26. package/dist/{chunk-UDNKWFBM.js.map → chunk-3U2BSIYX.js.map} +1 -1
  27. package/dist/chunk-4OOWA55U.js +215 -0
  28. package/dist/chunk-4OOWA55U.js.map +1 -0
  29. package/dist/{chunk-GFCBZN6S.js → chunk-AHRVNEFV.js} +80 -276
  30. package/dist/chunk-AHRVNEFV.js.map +1 -0
  31. package/dist/{chunk-ALTSW5DB.js → chunk-DQ6A6HTY.js} +12 -8
  32. package/dist/chunk-DQ6A6HTY.js.map +1 -0
  33. package/dist/{chunk-QIWGUF7V.js → chunk-IYFVJ2EY.js} +6 -4
  34. package/dist/{chunk-QIWGUF7V.js.map → chunk-IYFVJ2EY.js.map} +1 -1
  35. package/dist/{chunk-NZS4M3V3.js → chunk-TEFKM3GW.js} +2 -2
  36. package/dist/chunk-TEFKM3GW.js.map +1 -0
  37. package/dist/create-jmp-analytics-BdGOgPxl.d.ts +70 -0
  38. package/dist/create-jmp-analytics-DxhHOmtR.d.cts +70 -0
  39. package/dist/env-public-B6Y0DG68.d.cts +14 -0
  40. package/dist/env-public-B6Y0DG68.d.ts +14 -0
  41. package/dist/index.cjs +203 -198
  42. package/dist/index.cjs.map +1 -1
  43. package/dist/index.d.cts +16 -340
  44. package/dist/index.d.ts +16 -340
  45. package/dist/index.js +9 -5
  46. package/dist/landing-capture-C8pyZWuF.d.cts +4 -0
  47. package/dist/landing-capture-C8pyZWuF.d.ts +4 -0
  48. package/dist/next/content.cjs +106 -98
  49. package/dist/next/content.cjs.map +1 -1
  50. package/dist/next/content.d.cts +2 -1
  51. package/dist/next/content.d.ts +2 -1
  52. package/dist/next/content.js +3 -2
  53. package/dist/next/content.js.map +1 -1
  54. package/dist/next/instrumentation.cjs +68 -60
  55. package/dist/next/instrumentation.cjs.map +1 -1
  56. package/dist/next/instrumentation.js +4 -2
  57. package/dist/next/instrumentation.js.map +1 -1
  58. package/dist/next/middleware.cjs +66 -63
  59. package/dist/next/middleware.cjs.map +1 -1
  60. package/dist/next/middleware.d.cts +2 -2
  61. package/dist/next/middleware.d.ts +2 -2
  62. package/dist/next/middleware.js +2 -2
  63. package/dist/next.cjs +152 -123
  64. package/dist/next.cjs.map +1 -1
  65. package/dist/next.d.cts +15 -3
  66. package/dist/next.d.ts +15 -3
  67. package/dist/next.js +45 -7
  68. package/dist/next.js.map +1 -1
  69. package/dist/react.cjs +115 -118
  70. package/dist/react.cjs.map +1 -1
  71. package/dist/react.d.cts +2 -1
  72. package/dist/react.d.ts +2 -1
  73. package/dist/react.js +3 -2
  74. package/dist/site-config-BRuZWGSW.d.cts +46 -0
  75. package/dist/site-config-hkGMSeT7.d.ts +46 -0
  76. package/dist/{track-page-view-CoYo96n0.d.cts → track-page-view-BLS0YfL-.d.ts} +1 -1
  77. package/dist/{track-page-view-DAy0I0Vb.d.ts → track-page-view-DfCyWHqe.d.cts} +1 -1
  78. package/dist/types-BtiK_Acj.d.cts +224 -0
  79. package/dist/types-BtiK_Acj.d.ts +224 -0
  80. package/package.json +2 -4
  81. package/dist/chunk-ALTSW5DB.js.map +0 -1
  82. package/dist/chunk-GFCBZN6S.js.map +0 -1
  83. package/dist/chunk-NZS4M3V3.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -44,6 +44,7 @@ __export(index_exports, {
44
44
  isJmpBrowserAnalyticsEnvConfigured: () => isJmpBrowserAnalyticsEnvConfigured,
45
45
  isJmpServerContentEnvConfigured: () => isJmpServerContentEnvConfigured,
46
46
  isJmpTrackingConsentGranted: () => isJmpTrackingConsentGranted,
47
+ readJmpPublicEnvFromProcess: () => readJmpPublicEnvFromProcess,
47
48
  registerJmpContentWrappers: () => registerJmpContentWrappers,
48
49
  setJmpTrackingConsent: () => setJmpTrackingConsent,
49
50
  subscribeJmpTrackingConsent: () => subscribeJmpTrackingConsent,
@@ -312,72 +313,12 @@ function classifyContactHref(href) {
312
313
  return null;
313
314
  }
314
315
 
315
- // src/env-public.ts
316
- function readProcessEnv(name) {
317
- if (typeof process === "undefined" || !process.env) return void 0;
318
- const v = process.env[name];
319
- return typeof v === "string" && v.length > 0 ? v : void 0;
320
- }
321
- function firstDefined(...values) {
322
- for (const v of values) {
323
- if (v) return v;
324
- }
325
- return void 0;
326
- }
327
- function readJmpPublicEnvFromProcess(overrides) {
328
- const analyticsUrl = firstDefined(
329
- overrides?.analyticsUrl,
330
- readProcessEnv("NEXT_PUBLIC_JMP_ANALYTICS_URL"),
331
- readProcessEnv("PUBLIC_JMP_ANALYTICS_URL")
332
- );
333
- const trackingKey = firstDefined(
334
- overrides?.trackingKey,
335
- readProcessEnv("NEXT_PUBLIC_JMP_TRACKING_KEY"),
336
- readProcessEnv("PUBLIC_JMP_TRACKING_KEY")
337
- );
338
- const requireConsentRaw = firstDefined(
339
- overrides?.requireConsent !== void 0 ? String(overrides.requireConsent) : void 0,
340
- readProcessEnv("NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT"),
341
- readProcessEnv("PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT")
342
- );
343
- const autoContactRaw = firstDefined(
344
- overrides?.autoContactLinks !== void 0 ? String(overrides.autoContactLinks) : void 0,
345
- readProcessEnv("NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS"),
346
- readProcessEnv("PUBLIC_JMP_AUTO_CONTACT_LINKS")
347
- );
348
- return {
349
- analyticsUrl,
350
- trackingKey,
351
- requireConsent: requireConsentRaw === "true",
352
- autoContactLinks: autoContactRaw === "true"
353
- };
354
- }
355
-
356
- // src/site-config.ts
357
- var registeredSite = null;
358
- function defineJmpSite(definition) {
359
- registeredSite = definition;
360
- return definition;
361
- }
362
- function getJmpSiteDefinition() {
363
- return registeredSite;
364
- }
365
- function getJmpContentConfig() {
366
- const { analyticsUrl, trackingKey } = readJmpPublicEnvFromProcess();
367
- if (!analyticsUrl || !trackingKey) {
368
- return null;
369
- }
370
- const site = getJmpSiteDefinition();
371
- return {
372
- baseUrl: analyticsUrl,
373
- trackingKey,
374
- contentWrappers: site?.contentWrappers ?? void 0
375
- };
376
- }
377
-
378
- // src/index.ts
379
- var JMP_ANALYTICS_SDK_VERSION = "0.1.20";
316
+ // src/constants.ts
317
+ var JMP_ANALYTICS_SDK_VERSION = "0.1.21";
380
318
  var JMP_TRACKING_CONSENT_STORAGE_KEY = "jmp_analytics_consent_v1";
319
+ var DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 800;
320
+
321
+ // src/consent.ts
381
322
  var moduleTrackingConsentGranted = true;
382
323
  var trackingConsentListeners = /* @__PURE__ */ new Set();
383
324
  function readStoredTrackingConsent() {
@@ -390,6 +331,9 @@ function readStoredTrackingConsent() {
390
331
  return false;
391
332
  }
392
333
  }
334
+ function initJmpTrackingConsent(requireConsent) {
335
+ moduleTrackingConsentGranted = requireConsent ? readStoredTrackingConsent() : true;
336
+ }
393
337
  function isJmpTrackingConsentGranted() {
394
338
  return moduleTrackingConsentGranted;
395
339
  }
@@ -420,33 +364,8 @@ function setJmpTrackingConsent(granted) {
420
364
  listener();
421
365
  }
422
366
  }
423
- function captureAndGetLandingReferer() {
424
- if (typeof window === "undefined") {
425
- return null;
426
- }
427
- return captureLandingAttribution(window.location.hostname).landingReferer;
428
- }
429
- function mergeSessionUtms(metadata) {
430
- if (typeof window === "undefined") {
431
- return;
432
- }
433
- const { utm } = captureLandingAttribution(window.location.hostname);
434
- for (const key of JMP_UTM_PARAM_KEYS) {
435
- if (metadata[key] === void 0 && utm[key]) {
436
- metadata[key] = utm[key];
437
- }
438
- }
439
- }
440
- function splitPathAndSearch(pathInput) {
441
- const qIndex = pathInput.indexOf("?");
442
- if (qIndex === -1) {
443
- return { pathname: pathInput || "/", search: "" };
444
- }
445
- return {
446
- pathname: pathInput.slice(0, qIndex) || "/",
447
- search: pathInput.slice(qIndex + 1)
448
- };
449
- }
367
+
368
+ // src/http.ts
450
369
  function responseLooksLikeHtml(body) {
451
370
  const s = body.trimStart();
452
371
  return s.startsWith("<!") || s.toLowerCase().startsWith("<html") || s.startsWith("<") && /<html[\s>]/i.test(s.slice(0, 500));
@@ -479,24 +398,75 @@ function pathFromRequestUrl(url) {
479
398
  return url.startsWith("/") ? url : "/";
480
399
  }
481
400
  }
401
+ function resolveFetch(fetchImpl, context) {
402
+ const resolved = fetchImpl ?? (typeof globalThis !== "undefined" && globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
403
+ if (!resolved) {
404
+ throw new Error(`${context}: fetch is not available; pass fetchImpl in config`);
405
+ }
406
+ return resolved;
407
+ }
408
+ function formatApiErrorMessage(status, text, prefix) {
409
+ if (responseLooksLikeHtml(text)) {
410
+ return `${prefix} HTTP ${status} \u2014 response was HTML (not the JSON API). Check baseUrl points at the JMP Analytics dashboard.`;
411
+ }
412
+ let parsed = {};
413
+ try {
414
+ parsed = JSON.parse(text);
415
+ } catch {
416
+ parsed = { error: text };
417
+ }
418
+ const detail = parsed.error ?? text;
419
+ return [
420
+ `${prefix} HTTP ${status}`,
421
+ parsed.code ? `[${parsed.code}]` : null,
422
+ detail,
423
+ parsed.hint ? `Hint: ${parsed.hint}` : null,
424
+ parsed.expectedDomain ? `Domain in JMP admin: ${parsed.expectedDomain}` : null
425
+ ].filter(Boolean).join(" \u2014 ");
426
+ }
427
+
428
+ // src/tracker/helpers.ts
429
+ function captureAndGetLandingReferer() {
430
+ if (typeof window === "undefined") {
431
+ return null;
432
+ }
433
+ return captureLandingAttribution(window.location.hostname).landingReferer;
434
+ }
435
+ function mergeSessionUtms(metadata) {
436
+ if (typeof window === "undefined") {
437
+ return;
438
+ }
439
+ const { utm } = captureLandingAttribution(window.location.hostname);
440
+ for (const key of JMP_UTM_PARAM_KEYS) {
441
+ if (metadata[key] === void 0 && utm[key]) {
442
+ metadata[key] = utm[key];
443
+ }
444
+ }
445
+ }
446
+ function splitPathAndSearch(pathInput) {
447
+ const qIndex = pathInput.indexOf("?");
448
+ if (qIndex === -1) {
449
+ return { pathname: pathInput || "/", search: "" };
450
+ }
451
+ return {
452
+ pathname: pathInput.slice(0, qIndex) || "/",
453
+ search: pathInput.slice(qIndex + 1)
454
+ };
455
+ }
482
456
  function inferDevice() {
483
457
  if (typeof window === "undefined") {
484
458
  return "unknown";
485
459
  }
486
460
  return window.innerWidth < 768 ? "mobile" : "desktop";
487
461
  }
462
+
463
+ // src/tracker/create-jmp-analytics.ts
488
464
  function createJmpAnalytics(config) {
489
465
  const baseUrl = normalizeBaseUrl(config.baseUrl);
490
- const resolvedFetch = config.fetchImpl ?? (typeof globalThis !== "undefined" && globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
491
- if (!resolvedFetch) {
492
- throw new Error(
493
- "createJmpAnalytics: fetch is not available; pass fetchImpl in config"
494
- );
495
- }
496
- const fetchFn = resolvedFetch;
497
- moduleTrackingConsentGranted = config.requireConsent ? readStoredTrackingConsent() : true;
466
+ const fetchFn = resolveFetch(config.fetchImpl, "createJmpAnalytics");
467
+ initJmpTrackingConsent(config.requireConsent);
498
468
  function canSend() {
499
- return moduleTrackingConsentGranted;
469
+ return isJmpTrackingConsentGranted();
500
470
  }
501
471
  let lastDedupePath = "";
502
472
  let lastDedupeAt = 0;
@@ -528,32 +498,9 @@ function createJmpAnalytics(config) {
528
498
  });
529
499
  if (!res.ok) {
530
500
  const text = await res.text();
531
- if (responseLooksLikeHtml(text)) {
532
- throw new Error(
533
- `JMP Analytics HTTP ${res.status} \u2014 ${url} returned HTML (not the JSON API). Set baseUrl / NEXT_PUBLIC_JMP_ANALYTICS_URL to your JMP Analytics dashboard origin (the deployment that includes POST /api/events), not a marketing or client site unless that codebase ships the same API route.`
534
- );
535
- }
536
- let parsed = {};
537
- try {
538
- parsed = JSON.parse(text);
539
- } catch {
540
- parsed = { error: text };
541
- }
542
- const detail = parsed.error ?? text;
543
- const segments = [
544
- `JMP Analytics HTTP ${res.status}`,
545
- parsed.code ? `[${parsed.code}]` : null,
546
- detail,
547
- parsed.hint ? `Hint: ${parsed.hint}` : null,
548
- parsed.expectedDomain ? `Domain in JMP admin: ${parsed.expectedDomain}` : null
549
- ].filter(Boolean);
550
- const message = segments.join(" \u2014 ");
501
+ const message = formatApiErrorMessage(res.status, text, "JMP Analytics");
551
502
  if (config.debug) {
552
- console.debug("[@jmp-technologies/analytics]", "error response", {
553
- status: res.status,
554
- ...parsed,
555
- raw: text
556
- });
503
+ console.debug("[@jmp-technologies/analytics]", "error response", { status: res.status, raw: text });
557
504
  }
558
505
  throw new Error(message);
559
506
  }
@@ -580,32 +527,9 @@ function createJmpAnalytics(config) {
580
527
  });
581
528
  if (!res.ok) {
582
529
  const text = await res.text();
583
- if (responseLooksLikeHtml(text)) {
584
- throw new Error(
585
- `JMP Analytics HTTP ${res.status} \u2014 ${url} returned HTML (not the JSON API). Set baseUrl / NEXT_PUBLIC_JMP_ANALYTICS_URL to your JMP Analytics dashboard origin (the deployment that includes POST /api/leads).`
586
- );
587
- }
588
- let parsed = {};
589
- try {
590
- parsed = JSON.parse(text);
591
- } catch {
592
- parsed = { error: text };
593
- }
594
- const detail = parsed.error ?? text;
595
- const segments = [
596
- `JMP Analytics HTTP ${res.status}`,
597
- parsed.code ? `[${parsed.code}]` : null,
598
- detail,
599
- parsed.hint ? `Hint: ${parsed.hint}` : null,
600
- parsed.expectedDomain ? `Domain in JMP admin: ${parsed.expectedDomain}` : null
601
- ].filter(Boolean);
602
- const message = segments.join(" \u2014 ");
530
+ const message = formatApiErrorMessage(res.status, text, "JMP Analytics");
603
531
  if (config.debug) {
604
- console.debug("[@jmp-technologies/analytics]", "error response", {
605
- status: res.status,
606
- ...parsed,
607
- raw: text
608
- });
532
+ console.debug("[@jmp-technologies/analytics]", "error response", { status: res.status, raw: text });
609
533
  }
610
534
  throw new Error(message);
611
535
  }
@@ -869,6 +793,8 @@ function createJmpAnalytics(config) {
869
793
  isTrackingConsentGranted: isJmpTrackingConsentGranted
870
794
  };
871
795
  }
796
+
797
+ // src/server/page-view.ts
872
798
  async function trackJmpServerPageView(config, options = {}) {
873
799
  const baseUrl = normalizeBaseUrl(config.baseUrl);
874
800
  const resolvedFetch = config.fetchImpl ?? (typeof globalThis !== "undefined" && globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
@@ -910,6 +836,55 @@ async function trackJmpServerPageView(config, options = {}) {
910
836
  throw new Error(`JMP server analytics HTTP ${res.status} \u2014 ${text}`);
911
837
  }
912
838
  }
839
+
840
+ // src/content/fetch.ts
841
+ async function getContent(config, path) {
842
+ const text = await getContentText(config, path);
843
+ try {
844
+ return JSON.parse(text);
845
+ } catch {
846
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
847
+ const url = `${baseUrl}${path}`;
848
+ throw new Error(`JMP content HTTP 200 \u2014 ${url} returned invalid JSON.`);
849
+ }
850
+ }
851
+ async function getContentText(config, path) {
852
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
853
+ const resolvedFetch = config.fetchImpl ?? (typeof globalThis !== "undefined" && globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
854
+ if (!resolvedFetch) {
855
+ throw new Error("JMP content: fetch is not available; pass fetchImpl in config");
856
+ }
857
+ const url = `${baseUrl}${path}`;
858
+ if (config.debug) {
859
+ console.debug("[@jmp-technologies/analytics]", "GET", url);
860
+ }
861
+ const res = await resolvedFetch(url, {
862
+ method: "GET",
863
+ headers: {
864
+ "X-JMP-Tracking-Key": config.trackingKey
865
+ }
866
+ });
867
+ const text = await res.text();
868
+ if (!res.ok) {
869
+ if (responseLooksLikeHtml(text)) {
870
+ throw new Error(
871
+ `JMP content HTTP ${res.status} \u2014 ${url} returned HTML (not the JSON API). Set baseUrl to your JMP Analytics dashboard origin.`
872
+ );
873
+ }
874
+ let parsed = {};
875
+ try {
876
+ parsed = JSON.parse(text);
877
+ } catch {
878
+ parsed = { error: text };
879
+ }
880
+ throw new Error(
881
+ [`JMP content HTTP ${res.status}`, parsed.error, parsed.hint].filter(Boolean).join(" \u2014 ")
882
+ );
883
+ }
884
+ return text;
885
+ }
886
+
887
+ // src/content/api.ts
913
888
  async function getJmpBlogPosts(config) {
914
889
  const data = await getContent(
915
890
  config,
@@ -1005,6 +980,8 @@ async function registerJmpContentWrappers(config) {
1005
980
  const data = JSON.parse(text);
1006
981
  return { ok: true, wrappers: data.wrappers ?? wrappers };
1007
982
  }
983
+
984
+ // src/content/client.ts
1008
985
  function createJmpContentClient(config) {
1009
986
  return {
1010
987
  getBlogPosts: () => getJmpBlogPosts(config),
@@ -1016,58 +993,61 @@ function createJmpContentClient(config) {
1016
993
  registerContentWrappers: () => registerJmpContentWrappers(config)
1017
994
  };
1018
995
  }
1019
- async function getContent(config, path) {
1020
- const text = await getContentText(config, path);
1021
- try {
1022
- return JSON.parse(text);
1023
- } catch {
1024
- const baseUrl = normalizeBaseUrl(config.baseUrl);
1025
- const url = `${baseUrl}${path}`;
1026
- throw new Error(`JMP content HTTP 200 \u2014 ${url} returned invalid JSON.`);
996
+
997
+ // src/env-public.ts
998
+ function firstDefined(...values) {
999
+ for (const v of values) {
1000
+ if (v) return v;
1027
1001
  }
1002
+ return void 0;
1028
1003
  }
1029
- async function getContentText(config, path) {
1030
- const baseUrl = normalizeBaseUrl(config.baseUrl);
1031
- const resolvedFetch = config.fetchImpl ?? (typeof globalThis !== "undefined" && globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
1032
- if (!resolvedFetch) {
1033
- throw new Error("JMP content: fetch is not available; pass fetchImpl in config");
1034
- }
1035
- const url = `${baseUrl}${path}`;
1036
- if (config.debug) {
1037
- console.debug("[@jmp-technologies/analytics]", "GET", url);
1004
+ function readJmpPublicEnvFromProcessEnv() {
1005
+ if (typeof process === "undefined" || !process.env) {
1006
+ return {};
1038
1007
  }
1039
- const res = await resolvedFetch(url, {
1040
- method: "GET",
1041
- headers: {
1042
- "X-JMP-Tracking-Key": config.trackingKey
1043
- }
1044
- });
1045
- const text = await res.text();
1046
- if (!res.ok) {
1047
- if (responseLooksLikeHtml(text)) {
1048
- throw new Error(
1049
- `JMP content HTTP ${res.status} \u2014 ${url} returned HTML (not the JSON API). Set baseUrl to your JMP Analytics dashboard origin.`
1050
- );
1051
- }
1052
- let parsed = {};
1053
- try {
1054
- parsed = JSON.parse(text);
1055
- } catch {
1056
- parsed = { error: text };
1057
- }
1058
- throw new Error(
1059
- [`JMP content HTTP ${res.status}`, parsed.error, parsed.hint].filter(Boolean).join(" \u2014 ")
1060
- );
1061
- }
1062
- return text;
1008
+ const { env } = process;
1009
+ const analyticsUrl = firstDefined(
1010
+ env.NEXT_PUBLIC_JMP_ANALYTICS_URL,
1011
+ env.PUBLIC_JMP_ANALYTICS_URL
1012
+ );
1013
+ const trackingKey = firstDefined(
1014
+ env.NEXT_PUBLIC_JMP_TRACKING_KEY,
1015
+ env.PUBLIC_JMP_TRACKING_KEY
1016
+ );
1017
+ const requireConsentRaw = firstDefined(
1018
+ env.NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT,
1019
+ env.PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT
1020
+ );
1021
+ const autoContactRaw = firstDefined(
1022
+ env.NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS,
1023
+ env.PUBLIC_JMP_AUTO_CONTACT_LINKS
1024
+ );
1025
+ return {
1026
+ analyticsUrl,
1027
+ trackingKey,
1028
+ requireConsent: requireConsentRaw === "true",
1029
+ autoContactLinks: autoContactRaw === "true"
1030
+ };
1063
1031
  }
1064
- var DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 800;
1032
+ function readJmpPublicEnvFromProcess(overrides) {
1033
+ const fromEnv = readJmpPublicEnvFromProcessEnv();
1034
+ return {
1035
+ analyticsUrl: firstDefined(overrides?.analyticsUrl, fromEnv.analyticsUrl),
1036
+ trackingKey: firstDefined(overrides?.trackingKey, fromEnv.trackingKey),
1037
+ requireConsent: overrides?.requireConsent ?? fromEnv.requireConsent,
1038
+ autoContactLinks: overrides?.autoContactLinks ?? fromEnv.autoContactLinks
1039
+ };
1040
+ }
1041
+
1042
+ // src/env/browser.ts
1065
1043
  function getJmpBrowserAnalyticsConfigFromEnv(overrides) {
1066
1044
  const pub = readJmpPublicEnvFromProcess();
1067
- if (!pub.analyticsUrl || !pub.trackingKey) return null;
1045
+ const baseUrl = overrides?.baseUrl ?? pub.analyticsUrl;
1046
+ const trackingKey = overrides?.trackingKey ?? pub.trackingKey;
1047
+ if (!baseUrl || !trackingKey) return null;
1068
1048
  return {
1069
- baseUrl: pub.analyticsUrl,
1070
- trackingKey: pub.trackingKey,
1049
+ baseUrl,
1050
+ trackingKey,
1071
1051
  pageViewDedupeMs: DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
1072
1052
  ...overrides,
1073
1053
  requireConsent: overrides?.requireConsent ?? pub.requireConsent,
@@ -1076,8 +1056,10 @@ function getJmpBrowserAnalyticsConfigFromEnv(overrides) {
1076
1056
  }
1077
1057
  function getJmpServerContentConfigFromEnv(overrides) {
1078
1058
  const pub = readJmpPublicEnvFromProcess();
1079
- if (!pub.analyticsUrl || !pub.trackingKey) return null;
1080
- return { baseUrl: pub.analyticsUrl, trackingKey: pub.trackingKey, ...overrides };
1059
+ const baseUrl = overrides?.baseUrl ?? pub.analyticsUrl;
1060
+ const trackingKey = overrides?.trackingKey ?? pub.trackingKey;
1061
+ if (!baseUrl || !trackingKey) return null;
1062
+ return { baseUrl, trackingKey, ...overrides };
1081
1063
  }
1082
1064
  function isJmpBrowserAnalyticsEnvConfigured() {
1083
1065
  const pub = readJmpPublicEnvFromProcess();
@@ -1100,6 +1082,28 @@ function createJmpContentClientFromServerEnv(overrides) {
1100
1082
  if (!config) return null;
1101
1083
  return createJmpContentClient(config);
1102
1084
  }
1085
+
1086
+ // src/site-config.ts
1087
+ var registeredSite = null;
1088
+ function defineJmpSite(definition) {
1089
+ registeredSite = definition;
1090
+ return definition;
1091
+ }
1092
+ function getJmpSiteDefinition() {
1093
+ return registeredSite;
1094
+ }
1095
+ function getJmpContentConfig() {
1096
+ const { analyticsUrl, trackingKey } = readJmpPublicEnvFromProcess();
1097
+ if (!analyticsUrl || !trackingKey) {
1098
+ return null;
1099
+ }
1100
+ const site = getJmpSiteDefinition();
1101
+ return {
1102
+ baseUrl: analyticsUrl,
1103
+ trackingKey,
1104
+ contentWrappers: site?.contentWrappers ?? void 0
1105
+ };
1106
+ }
1103
1107
  // Annotate the CommonJS export names for ESM import in node:
1104
1108
  0 && (module.exports = {
1105
1109
  BOOKING_LINK_HOSTS,
@@ -1126,6 +1130,7 @@ function createJmpContentClientFromServerEnv(overrides) {
1126
1130
  isJmpBrowserAnalyticsEnvConfigured,
1127
1131
  isJmpServerContentEnvConfigured,
1128
1132
  isJmpTrackingConsentGranted,
1133
+ readJmpPublicEnvFromProcess,
1129
1134
  registerJmpContentWrappers,
1130
1135
  setJmpTrackingConsent,
1131
1136
  subscribeJmpTrackingConsent,