@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/react.cjs CHANGED
@@ -286,7 +286,7 @@ function classifyContactHref(href) {
286
286
  }
287
287
 
288
288
  // src/constants.ts
289
- var JMP_ANALYTICS_SDK_VERSION = "0.1.25";
289
+ var JMP_ANALYTICS_SDK_VERSION = "0.1.26";
290
290
  var JMP_TRACKING_CONSENT_STORAGE_KEY = "jmp_analytics_consent_v1";
291
291
  var DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 2500;
292
292
 
@@ -753,6 +753,209 @@ function createJmpAnalytics(config) {
753
753
  };
754
754
  }
755
755
 
756
+ // src/content/manifest.ts
757
+ var JMP_CONTENT_MANIFEST_VERSION = 1;
758
+ var TRUST_SECTIONS = /* @__PURE__ */ new Set([
759
+ "summary",
760
+ "testimonials",
761
+ "reviews",
762
+ "stats",
763
+ "logos",
764
+ "credentials"
765
+ ]);
766
+ function normalizeKey(value) {
767
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
768
+ }
769
+ function isValidExtraKey(key) {
770
+ return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(key);
771
+ }
772
+ var MAX_EXTERNAL_ADMIN_LINKS = 10;
773
+ var MAX_EXTERNAL_ADMIN_LINK_LABEL_LENGTH = 80;
774
+ var EXTERNAL_ADMIN_LINK_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
775
+ function tryNormalizeHttpUrl(input) {
776
+ if (typeof input !== "string" || !input.trim()) {
777
+ return null;
778
+ }
779
+ try {
780
+ const url = new URL(input.trim());
781
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
782
+ return null;
783
+ }
784
+ return url.toString().replace(/\/$/, "");
785
+ } catch {
786
+ return null;
787
+ }
788
+ }
789
+ function normalizeShopifyExternalSource(shopify) {
790
+ if (!shopify || typeof shopify !== "object") {
791
+ return null;
792
+ }
793
+ const adminUrl = tryNormalizeHttpUrl(shopify.adminUrl);
794
+ const storeUrl = tryNormalizeHttpUrl(shopify.storeUrl);
795
+ if (!adminUrl && !storeUrl) {
796
+ return null;
797
+ }
798
+ return {
799
+ ...adminUrl ? { adminUrl } : {},
800
+ ...storeUrl ? { storeUrl } : {}
801
+ };
802
+ }
803
+ function normalizeExternalAdminLinkEntries(links) {
804
+ if (!Array.isArray(links)) {
805
+ return [];
806
+ }
807
+ const seenIds = /* @__PURE__ */ new Set();
808
+ const out = [];
809
+ for (const raw of links) {
810
+ if (!raw || typeof raw !== "object" || out.length >= MAX_EXTERNAL_ADMIN_LINKS) {
811
+ continue;
812
+ }
813
+ const id = typeof raw.id === "string" ? raw.id.trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") : "";
814
+ const label = typeof raw.label === "string" ? raw.label.trim().slice(0, MAX_EXTERNAL_ADMIN_LINK_LABEL_LENGTH) : "";
815
+ const url = tryNormalizeHttpUrl(raw.url);
816
+ if (!id || !label || !url || !EXTERNAL_ADMIN_LINK_ID_PATTERN.test(id) || seenIds.has(id)) {
817
+ continue;
818
+ }
819
+ seenIds.add(id);
820
+ out.push({ id, label, url });
821
+ }
822
+ return out;
823
+ }
824
+ function normalizeExternalSources(externalSources) {
825
+ if (!externalSources || typeof externalSources !== "object") {
826
+ return null;
827
+ }
828
+ const studioUrl = tryNormalizeHttpUrl(externalSources.sanity?.studioUrl);
829
+ const shopify = normalizeShopifyExternalSource(externalSources.shopify);
830
+ const links = normalizeExternalAdminLinkEntries(externalSources.links);
831
+ if (!studioUrl && !shopify && links.length === 0) {
832
+ return null;
833
+ }
834
+ return {
835
+ ...studioUrl ? { sanity: { studioUrl } } : {},
836
+ ...shopify ? { shopify } : {},
837
+ ...links.length > 0 ? { links } : {}
838
+ };
839
+ }
840
+ function normalizeJmpContentManifest(input) {
841
+ if (!input || typeof input !== "object") {
842
+ return null;
843
+ }
844
+ const routes = normalizeRoutes(input.routes);
845
+ const externalSources = normalizeExternalSources(input.externalSources);
846
+ const trust = normalizeTrust(input.trust);
847
+ const contact = normalizeContact(input.contact);
848
+ if (routes.length === 0 && !externalSources && !trust && !contact) {
849
+ return null;
850
+ }
851
+ return {
852
+ version: JMP_CONTENT_MANIFEST_VERSION,
853
+ ...routes.length > 0 ? { routes } : {},
854
+ ...externalSources ? { externalSources } : {},
855
+ ...trust ? { trust } : {},
856
+ ...contact ? { contact } : {}
857
+ };
858
+ }
859
+ function normalizeRoutes(routes) {
860
+ if (!Array.isArray(routes)) {
861
+ return [];
862
+ }
863
+ const seen = /* @__PURE__ */ new Set();
864
+ const out = [];
865
+ for (const raw of routes) {
866
+ if (!raw || typeof raw !== "object") continue;
867
+ const wrapper = typeof raw.wrapper === "string" ? raw.wrapper.trim().toLowerCase() : "";
868
+ const pattern = typeof raw.pattern === "string" ? raw.pattern.trim() : "";
869
+ if (!wrapper || !pattern) continue;
870
+ const dedupe = `${wrapper}:${pattern}`;
871
+ if (seen.has(dedupe)) continue;
872
+ seen.add(dedupe);
873
+ out.push({
874
+ wrapper,
875
+ pattern,
876
+ ...typeof raw.index === "string" && raw.index.trim() ? { index: raw.index.trim() } : {},
877
+ ...typeof raw.label === "string" && raw.label.trim() ? { label: raw.label.trim() } : {}
878
+ });
879
+ }
880
+ return out;
881
+ }
882
+ function normalizeTrust(trust) {
883
+ if (!trust || typeof trust !== "object") return null;
884
+ const blocks = normalizeTrustBlocks(trust.blocks);
885
+ const labels = normalizeTrustLabels(trust.labels);
886
+ const mergeTestimonialsReviews = trust.mergeTestimonialsReviews === true;
887
+ if (blocks.length === 0 && !labels && !mergeTestimonialsReviews) return null;
888
+ return {
889
+ ...blocks.length > 0 ? { blocks } : {},
890
+ ...labels ? { labels } : {},
891
+ ...mergeTestimonialsReviews ? { mergeTestimonialsReviews: true } : {}
892
+ };
893
+ }
894
+ function normalizeTrustBlocks(blocks) {
895
+ if (!Array.isArray(blocks)) return [];
896
+ const seen = /* @__PURE__ */ new Set();
897
+ const out = [];
898
+ for (const raw of blocks) {
899
+ if (!raw || typeof raw !== "object") continue;
900
+ const section = typeof raw.section === "string" ? raw.section.trim().toLowerCase() : "";
901
+ if (!TRUST_SECTIONS.has(section) || seen.has(section)) continue;
902
+ seen.add(section);
903
+ out.push({
904
+ section,
905
+ ...typeof raw.label === "string" && raw.label.trim() ? { label: raw.label.trim() } : {}
906
+ });
907
+ }
908
+ return out;
909
+ }
910
+ function normalizeTrustLabels(labels) {
911
+ if (!labels || typeof labels !== "object") return null;
912
+ const out = {};
913
+ for (const [key, value] of Object.entries(labels)) {
914
+ if (TRUST_SECTIONS.has(key) && typeof value === "string" && value.trim()) {
915
+ out[key] = value.trim();
916
+ }
917
+ }
918
+ return Object.keys(out).length > 0 ? out : null;
919
+ }
920
+ function normalizeContact(contact) {
921
+ if (!contact || typeof contact !== "object") return null;
922
+ const extras = normalizeContactExtras(contact.extras);
923
+ return extras.length > 0 ? { extras } : null;
924
+ }
925
+ function normalizeContactExtras(extras) {
926
+ if (!Array.isArray(extras)) return [];
927
+ const seen = /* @__PURE__ */ new Set();
928
+ const out = [];
929
+ for (const raw of extras) {
930
+ if (!raw || typeof raw !== "object") continue;
931
+ const label = typeof raw.label === "string" ? raw.label.trim() : "";
932
+ const key = normalizeKey(
933
+ typeof raw.key === "string" && raw.key.trim() ? raw.key : label
934
+ );
935
+ if (!key || !label || !isValidExtraKey(key) || seen.has(key)) continue;
936
+ seen.add(key);
937
+ out.push({ key, label });
938
+ }
939
+ return out;
940
+ }
941
+ function stableJmpManifestFingerprint(manifest) {
942
+ return manifest ? JSON.stringify(manifest) : "";
943
+ }
944
+ function inferWrapperSlotsFromManifest(manifest) {
945
+ const slots = /* @__PURE__ */ new Set();
946
+ for (const route of manifest?.routes ?? []) {
947
+ slots.add(route.wrapper);
948
+ }
949
+ for (const block of manifest?.trust?.blocks ?? []) {
950
+ slots.add(`trust.${block.section}`);
951
+ slots.add("trust");
952
+ }
953
+ if (manifest?.contact?.extras?.length) {
954
+ slots.add("contact");
955
+ }
956
+ return [...slots];
957
+ }
958
+
756
959
  // src/content/wrapper-discovery.ts
757
960
  var WRAPPER_SLOT_ORDER = [
758
961
  "blog",
@@ -772,16 +975,22 @@ var syncHandler = null;
772
975
  function getDiscoveredContentWrappers() {
773
976
  return sortWrapperSlots([...discovered]);
774
977
  }
978
+ function resolveContentManifestForReport(config) {
979
+ return normalizeJmpContentManifest(config.contentManifest);
980
+ }
775
981
  function resolveContentWrappersForReport(config) {
776
982
  const explicit = config.contentWrappers ?? [];
777
983
  const auto = getDiscoveredContentWrappers();
984
+ const fromManifest = inferWrapperSlotsFromManifest(
985
+ resolveContentManifestForReport(config)
986
+ );
778
987
  if (config.contentWrapperMode === "manual") {
779
- return sortWrapperSlots([...explicit]);
988
+ return sortWrapperSlots([...explicit, ...fromManifest]);
780
989
  }
781
990
  if (config.contentWrapperMode === "explicit-only") {
782
- return sortWrapperSlots([...explicit]);
991
+ return sortWrapperSlots([...explicit, ...fromManifest]);
783
992
  }
784
- const merged = /* @__PURE__ */ new Set([...explicit, ...auto]);
993
+ const merged = /* @__PURE__ */ new Set([...explicit, ...auto, ...fromManifest]);
785
994
  return sortWrapperSlots([...merged]);
786
995
  }
787
996
  function hasReportedContentWrappers(dedupeKey) {
@@ -811,7 +1020,8 @@ async function registerJmpContentWrappers(config) {
811
1020
  if (!wrappers.length) {
812
1021
  return { ok: false, skipped: true };
813
1022
  }
814
- const dedupeKey = `${config.trackingKey}:${[...wrappers].sort().join(",")}`;
1023
+ const manifest = resolveContentManifestForReport(config);
1024
+ const dedupeKey = `${config.trackingKey}:${[...wrappers].sort().join(",")}:${stableJmpManifestFingerprint(manifest)}`;
815
1025
  if (hasReportedContentWrappers(dedupeKey)) {
816
1026
  return { ok: true, wrappers };
817
1027
  }
@@ -824,7 +1034,17 @@ async function registerJmpContentWrappers(config) {
824
1034
  }
825
1035
  const url = `${baseUrl}/api/content/capabilities`;
826
1036
  if (config.debug) {
827
- console.debug("[@jmp-technologies/analytics]", "POST", url, { wrappers });
1037
+ console.debug("[@jmp-technologies/analytics]", "POST", url, {
1038
+ wrappers,
1039
+ manifest
1040
+ });
1041
+ }
1042
+ const body = {
1043
+ wrappers,
1044
+ sdkVersion: JMP_ANALYTICS_SDK_VERSION
1045
+ };
1046
+ if (manifest) {
1047
+ body.manifest = manifest;
828
1048
  }
829
1049
  const res = await resolvedFetch(url, {
830
1050
  method: "POST",
@@ -832,10 +1052,7 @@ async function registerJmpContentWrappers(config) {
832
1052
  "Content-Type": "application/json",
833
1053
  "X-JMP-Tracking-Key": config.trackingKey
834
1054
  },
835
- body: JSON.stringify({
836
- wrappers,
837
- sdkVersion: JMP_ANALYTICS_SDK_VERSION
838
- })
1055
+ body: JSON.stringify(body)
839
1056
  });
840
1057
  const text = await res.text();
841
1058
  if (!res.ok) {