@jmp-technologies/analytics 0.1.26 → 0.1.30

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 (86) hide show
  1. package/README.md +43 -0
  2. package/bin/jmp-init.mjs +34 -0
  3. package/dist/astro/client.cjs +227 -10
  4. package/dist/astro/client.cjs.map +1 -1
  5. package/dist/astro/client.d.cts +2 -2
  6. package/dist/astro/client.d.ts +2 -2
  7. package/dist/astro/client.js +2 -2
  8. package/dist/astro/content.cjs +340 -14
  9. package/dist/astro/content.cjs.map +1 -1
  10. package/dist/astro/content.d.cts +16 -3
  11. package/dist/astro/content.d.ts +16 -3
  12. package/dist/astro/content.js +11 -3
  13. package/dist/astro/integration.cjs +229 -11
  14. package/dist/astro/integration.cjs.map +1 -1
  15. package/dist/astro/integration.js +3 -3
  16. package/dist/astro/middleware.cjs +2 -1
  17. package/dist/astro/middleware.cjs.map +1 -1
  18. package/dist/astro/middleware.d.cts +2 -2
  19. package/dist/astro/middleware.d.ts +2 -2
  20. package/dist/astro/middleware.js +2 -2
  21. package/dist/astro/register.cjs +229 -11
  22. package/dist/astro/register.cjs.map +1 -1
  23. package/dist/astro/register.js +3 -3
  24. package/dist/{chunk-A4RRTY5D.js → chunk-AIFJ7DVO.js} +3 -2
  25. package/dist/{chunk-A4RRTY5D.js.map → chunk-AIFJ7DVO.js.map} +1 -1
  26. package/dist/{chunk-TFHOTBOL.js → chunk-FS4BZ7DR.js} +66 -6
  27. package/dist/chunk-FS4BZ7DR.js.map +1 -0
  28. package/dist/{chunk-RCOHQAGL.js → chunk-GTPKRBFR.js} +284 -12
  29. package/dist/chunk-GTPKRBFR.js.map +1 -0
  30. package/dist/{chunk-HODG4NJQ.js → chunk-HFLU7HQE.js} +2 -2
  31. package/dist/{chunk-WFTTIRDJ.js → chunk-LLTB7ZFC.js} +2 -2
  32. package/dist/{chunk-PKGUBYZR.js → chunk-LTPLLPOR.js} +3 -3
  33. package/dist/{chunk-XQZOGWF2.js → chunk-ZEC22LFP.js} +3 -3
  34. package/dist/{create-jmp-analytics-JKAsJAWb.d.ts → create-jmp-analytics-BeuuU6as.d.ts} +1 -1
  35. package/dist/{create-jmp-analytics-Mau-oxji.d.cts → create-jmp-analytics-Ce2CrhhR.d.cts} +1 -1
  36. package/dist/index.cjs +289 -11
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +16 -7
  39. package/dist/index.d.ts +16 -7
  40. package/dist/index.js +12 -2
  41. package/dist/next/content.cjs +343 -14
  42. package/dist/next/content.cjs.map +1 -1
  43. package/dist/next/content.d.cts +8 -5
  44. package/dist/next/content.d.ts +8 -5
  45. package/dist/next/content.js +14 -3
  46. package/dist/next/content.js.map +1 -1
  47. package/dist/next/instrumentation.cjs +229 -11
  48. package/dist/next/instrumentation.cjs.map +1 -1
  49. package/dist/next/instrumentation.js +2 -2
  50. package/dist/next/landing-pages.cjs +875 -0
  51. package/dist/next/landing-pages.cjs.map +1 -0
  52. package/dist/next/landing-pages.d.cts +103 -0
  53. package/dist/next/landing-pages.d.ts +103 -0
  54. package/dist/next/landing-pages.js +297 -0
  55. package/dist/next/landing-pages.js.map +1 -0
  56. package/dist/next/middleware.cjs +2 -1
  57. package/dist/next/middleware.cjs.map +1 -1
  58. package/dist/next/middleware.d.cts +2 -2
  59. package/dist/next/middleware.d.ts +2 -2
  60. package/dist/next/middleware.js +2 -2
  61. package/dist/next/site-root-server.cjs +229 -11
  62. package/dist/next/site-root-server.cjs.map +1 -1
  63. package/dist/next/site-root-server.js +4 -4
  64. package/dist/next.cjs +227 -10
  65. package/dist/next.cjs.map +1 -1
  66. package/dist/next.d.cts +3 -3
  67. package/dist/next.d.ts +3 -3
  68. package/dist/next.js +4 -4
  69. package/dist/react.cjs +227 -10
  70. package/dist/react.cjs.map +1 -1
  71. package/dist/react.d.cts +2 -2
  72. package/dist/react.d.ts +2 -2
  73. package/dist/react.js +3 -3
  74. package/dist/{site-config-CXUdGLqw.d.cts → site-config-B4uEj4xX.d.ts} +22 -2
  75. package/dist/{site-config-w_Db9YSk.d.ts → site-config-DIFmnwqv.d.cts} +22 -2
  76. package/dist/{track-page-view-CkuSYuco.d.cts → track-page-view-Bv0BAvxG.d.cts} +1 -1
  77. package/dist/{track-page-view-QRSk8vap.d.ts → track-page-view-CkgIp9-j.d.ts} +1 -1
  78. package/dist/{types-C1eq8E5u.d.ts → types-B2iP79lb.d.cts} +99 -2
  79. package/dist/{types-C1eq8E5u.d.cts → types-B2iP79lb.d.ts} +99 -2
  80. package/package.json +11 -2
  81. package/dist/chunk-RCOHQAGL.js.map +0 -1
  82. package/dist/chunk-TFHOTBOL.js.map +0 -1
  83. /package/dist/{chunk-HODG4NJQ.js.map → chunk-HFLU7HQE.js.map} +0 -0
  84. /package/dist/{chunk-WFTTIRDJ.js.map → chunk-LLTB7ZFC.js.map} +0 -0
  85. /package/dist/{chunk-PKGUBYZR.js.map → chunk-LTPLLPOR.js.map} +0 -0
  86. /package/dist/{chunk-XQZOGWF2.js.map → chunk-ZEC22LFP.js.map} +0 -0
package/dist/next.cjs CHANGED
@@ -95,7 +95,7 @@ function readJmpPublicEnvFromProcess(overrides) {
95
95
  }
96
96
 
97
97
  // src/constants.ts
98
- var JMP_ANALYTICS_SDK_VERSION = "0.1.25";
98
+ var JMP_ANALYTICS_SDK_VERSION = "0.1.26";
99
99
  var JMP_TRACKING_CONSENT_STORAGE_KEY = "jmp_analytics_consent_v1";
100
100
  var DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 2500;
101
101
 
@@ -835,6 +835,209 @@ function getJmpSiteDefinition() {
835
835
  return registeredSite;
836
836
  }
837
837
 
838
+ // src/content/manifest.ts
839
+ var JMP_CONTENT_MANIFEST_VERSION = 1;
840
+ var TRUST_SECTIONS = /* @__PURE__ */ new Set([
841
+ "summary",
842
+ "testimonials",
843
+ "reviews",
844
+ "stats",
845
+ "logos",
846
+ "credentials"
847
+ ]);
848
+ function normalizeKey(value) {
849
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
850
+ }
851
+ function isValidExtraKey(key) {
852
+ return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(key);
853
+ }
854
+ var MAX_EXTERNAL_ADMIN_LINKS = 10;
855
+ var MAX_EXTERNAL_ADMIN_LINK_LABEL_LENGTH = 80;
856
+ var EXTERNAL_ADMIN_LINK_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
857
+ function tryNormalizeHttpUrl(input) {
858
+ if (typeof input !== "string" || !input.trim()) {
859
+ return null;
860
+ }
861
+ try {
862
+ const url = new URL(input.trim());
863
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
864
+ return null;
865
+ }
866
+ return url.toString().replace(/\/$/, "");
867
+ } catch {
868
+ return null;
869
+ }
870
+ }
871
+ function normalizeShopifyExternalSource(shopify) {
872
+ if (!shopify || typeof shopify !== "object") {
873
+ return null;
874
+ }
875
+ const adminUrl = tryNormalizeHttpUrl(shopify.adminUrl);
876
+ const storeUrl = tryNormalizeHttpUrl(shopify.storeUrl);
877
+ if (!adminUrl && !storeUrl) {
878
+ return null;
879
+ }
880
+ return {
881
+ ...adminUrl ? { adminUrl } : {},
882
+ ...storeUrl ? { storeUrl } : {}
883
+ };
884
+ }
885
+ function normalizeExternalAdminLinkEntries(links) {
886
+ if (!Array.isArray(links)) {
887
+ return [];
888
+ }
889
+ const seenIds = /* @__PURE__ */ new Set();
890
+ const out = [];
891
+ for (const raw of links) {
892
+ if (!raw || typeof raw !== "object" || out.length >= MAX_EXTERNAL_ADMIN_LINKS) {
893
+ continue;
894
+ }
895
+ const id = typeof raw.id === "string" ? raw.id.trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") : "";
896
+ const label = typeof raw.label === "string" ? raw.label.trim().slice(0, MAX_EXTERNAL_ADMIN_LINK_LABEL_LENGTH) : "";
897
+ const url = tryNormalizeHttpUrl(raw.url);
898
+ if (!id || !label || !url || !EXTERNAL_ADMIN_LINK_ID_PATTERN.test(id) || seenIds.has(id)) {
899
+ continue;
900
+ }
901
+ seenIds.add(id);
902
+ out.push({ id, label, url });
903
+ }
904
+ return out;
905
+ }
906
+ function normalizeExternalSources(externalSources) {
907
+ if (!externalSources || typeof externalSources !== "object") {
908
+ return null;
909
+ }
910
+ const studioUrl = tryNormalizeHttpUrl(externalSources.sanity?.studioUrl);
911
+ const shopify = normalizeShopifyExternalSource(externalSources.shopify);
912
+ const links = normalizeExternalAdminLinkEntries(externalSources.links);
913
+ if (!studioUrl && !shopify && links.length === 0) {
914
+ return null;
915
+ }
916
+ return {
917
+ ...studioUrl ? { sanity: { studioUrl } } : {},
918
+ ...shopify ? { shopify } : {},
919
+ ...links.length > 0 ? { links } : {}
920
+ };
921
+ }
922
+ function normalizeJmpContentManifest(input) {
923
+ if (!input || typeof input !== "object") {
924
+ return null;
925
+ }
926
+ const routes = normalizeRoutes(input.routes);
927
+ const externalSources = normalizeExternalSources(input.externalSources);
928
+ const trust = normalizeTrust(input.trust);
929
+ const contact = normalizeContact(input.contact);
930
+ if (routes.length === 0 && !externalSources && !trust && !contact) {
931
+ return null;
932
+ }
933
+ return {
934
+ version: JMP_CONTENT_MANIFEST_VERSION,
935
+ ...routes.length > 0 ? { routes } : {},
936
+ ...externalSources ? { externalSources } : {},
937
+ ...trust ? { trust } : {},
938
+ ...contact ? { contact } : {}
939
+ };
940
+ }
941
+ function normalizeRoutes(routes) {
942
+ if (!Array.isArray(routes)) {
943
+ return [];
944
+ }
945
+ const seen = /* @__PURE__ */ new Set();
946
+ const out = [];
947
+ for (const raw of routes) {
948
+ if (!raw || typeof raw !== "object") continue;
949
+ const wrapper = typeof raw.wrapper === "string" ? raw.wrapper.trim().toLowerCase() : "";
950
+ const pattern = typeof raw.pattern === "string" ? raw.pattern.trim() : "";
951
+ if (!wrapper || !pattern) continue;
952
+ const dedupe = `${wrapper}:${pattern}`;
953
+ if (seen.has(dedupe)) continue;
954
+ seen.add(dedupe);
955
+ out.push({
956
+ wrapper,
957
+ pattern,
958
+ ...typeof raw.index === "string" && raw.index.trim() ? { index: raw.index.trim() } : {},
959
+ ...typeof raw.label === "string" && raw.label.trim() ? { label: raw.label.trim() } : {}
960
+ });
961
+ }
962
+ return out;
963
+ }
964
+ function normalizeTrust(trust) {
965
+ if (!trust || typeof trust !== "object") return null;
966
+ const blocks = normalizeTrustBlocks(trust.blocks);
967
+ const labels = normalizeTrustLabels(trust.labels);
968
+ const mergeTestimonialsReviews = trust.mergeTestimonialsReviews === true;
969
+ if (blocks.length === 0 && !labels && !mergeTestimonialsReviews) return null;
970
+ return {
971
+ ...blocks.length > 0 ? { blocks } : {},
972
+ ...labels ? { labels } : {},
973
+ ...mergeTestimonialsReviews ? { mergeTestimonialsReviews: true } : {}
974
+ };
975
+ }
976
+ function normalizeTrustBlocks(blocks) {
977
+ if (!Array.isArray(blocks)) return [];
978
+ const seen = /* @__PURE__ */ new Set();
979
+ const out = [];
980
+ for (const raw of blocks) {
981
+ if (!raw || typeof raw !== "object") continue;
982
+ const section = typeof raw.section === "string" ? raw.section.trim().toLowerCase() : "";
983
+ if (!TRUST_SECTIONS.has(section) || seen.has(section)) continue;
984
+ seen.add(section);
985
+ out.push({
986
+ section,
987
+ ...typeof raw.label === "string" && raw.label.trim() ? { label: raw.label.trim() } : {}
988
+ });
989
+ }
990
+ return out;
991
+ }
992
+ function normalizeTrustLabels(labels) {
993
+ if (!labels || typeof labels !== "object") return null;
994
+ const out = {};
995
+ for (const [key, value] of Object.entries(labels)) {
996
+ if (TRUST_SECTIONS.has(key) && typeof value === "string" && value.trim()) {
997
+ out[key] = value.trim();
998
+ }
999
+ }
1000
+ return Object.keys(out).length > 0 ? out : null;
1001
+ }
1002
+ function normalizeContact(contact) {
1003
+ if (!contact || typeof contact !== "object") return null;
1004
+ const extras = normalizeContactExtras(contact.extras);
1005
+ return extras.length > 0 ? { extras } : null;
1006
+ }
1007
+ function normalizeContactExtras(extras) {
1008
+ if (!Array.isArray(extras)) return [];
1009
+ const seen = /* @__PURE__ */ new Set();
1010
+ const out = [];
1011
+ for (const raw of extras) {
1012
+ if (!raw || typeof raw !== "object") continue;
1013
+ const label = typeof raw.label === "string" ? raw.label.trim() : "";
1014
+ const key = normalizeKey(
1015
+ typeof raw.key === "string" && raw.key.trim() ? raw.key : label
1016
+ );
1017
+ if (!key || !label || !isValidExtraKey(key) || seen.has(key)) continue;
1018
+ seen.add(key);
1019
+ out.push({ key, label });
1020
+ }
1021
+ return out;
1022
+ }
1023
+ function stableJmpManifestFingerprint(manifest) {
1024
+ return manifest ? JSON.stringify(manifest) : "";
1025
+ }
1026
+ function inferWrapperSlotsFromManifest(manifest) {
1027
+ const slots = /* @__PURE__ */ new Set();
1028
+ for (const route of manifest?.routes ?? []) {
1029
+ slots.add(route.wrapper);
1030
+ }
1031
+ for (const block of manifest?.trust?.blocks ?? []) {
1032
+ slots.add(`trust.${block.section}`);
1033
+ slots.add("trust");
1034
+ }
1035
+ if (manifest?.contact?.extras?.length) {
1036
+ slots.add("contact");
1037
+ }
1038
+ return [...slots];
1039
+ }
1040
+
838
1041
  // src/content/wrapper-discovery.ts
839
1042
  var WRAPPER_SLOT_ORDER = [
840
1043
  "blog",
@@ -854,16 +1057,22 @@ var syncHandler = null;
854
1057
  function getDiscoveredContentWrappers() {
855
1058
  return sortWrapperSlots([...discovered]);
856
1059
  }
1060
+ function resolveContentManifestForReport(config) {
1061
+ return normalizeJmpContentManifest(config.contentManifest);
1062
+ }
857
1063
  function resolveContentWrappersForReport(config) {
858
1064
  const explicit = config.contentWrappers ?? [];
859
1065
  const auto = getDiscoveredContentWrappers();
1066
+ const fromManifest = inferWrapperSlotsFromManifest(
1067
+ resolveContentManifestForReport(config)
1068
+ );
860
1069
  if (config.contentWrapperMode === "manual") {
861
- return sortWrapperSlots([...explicit]);
1070
+ return sortWrapperSlots([...explicit, ...fromManifest]);
862
1071
  }
863
1072
  if (config.contentWrapperMode === "explicit-only") {
864
- return sortWrapperSlots([...explicit]);
1073
+ return sortWrapperSlots([...explicit, ...fromManifest]);
865
1074
  }
866
- const merged = /* @__PURE__ */ new Set([...explicit, ...auto]);
1075
+ const merged = /* @__PURE__ */ new Set([...explicit, ...auto, ...fromManifest]);
867
1076
  return sortWrapperSlots([...merged]);
868
1077
  }
869
1078
  function hasReportedContentWrappers(dedupeKey) {
@@ -893,7 +1102,8 @@ async function registerJmpContentWrappers(config) {
893
1102
  if (!wrappers.length) {
894
1103
  return { ok: false, skipped: true };
895
1104
  }
896
- const dedupeKey = `${config.trackingKey}:${[...wrappers].sort().join(",")}`;
1105
+ const manifest = resolveContentManifestForReport(config);
1106
+ const dedupeKey = `${config.trackingKey}:${[...wrappers].sort().join(",")}:${stableJmpManifestFingerprint(manifest)}`;
897
1107
  if (hasReportedContentWrappers(dedupeKey)) {
898
1108
  return { ok: true, wrappers };
899
1109
  }
@@ -906,7 +1116,17 @@ async function registerJmpContentWrappers(config) {
906
1116
  }
907
1117
  const url = `${baseUrl}/api/content/capabilities`;
908
1118
  if (config.debug) {
909
- console.debug("[@jmp-technologies/analytics]", "POST", url, { wrappers });
1119
+ console.debug("[@jmp-technologies/analytics]", "POST", url, {
1120
+ wrappers,
1121
+ manifest
1122
+ });
1123
+ }
1124
+ const body = {
1125
+ wrappers,
1126
+ sdkVersion: JMP_ANALYTICS_SDK_VERSION
1127
+ };
1128
+ if (manifest) {
1129
+ body.manifest = manifest;
910
1130
  }
911
1131
  const res = await resolvedFetch(url, {
912
1132
  method: "POST",
@@ -914,10 +1134,7 @@ async function registerJmpContentWrappers(config) {
914
1134
  "Content-Type": "application/json",
915
1135
  "X-JMP-Tracking-Key": config.trackingKey
916
1136
  },
917
- body: JSON.stringify({
918
- wrappers,
919
- sdkVersion: JMP_ANALYTICS_SDK_VERSION
920
- })
1137
+ body: JSON.stringify(body)
921
1138
  });
922
1139
  const text = await res.text();
923
1140
  if (!res.ok) {