@jmp-technologies/analytics 0.1.27 → 0.1.32

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 (100) hide show
  1. package/dist/astro/client.cjs +256 -11
  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 +308 -13
  7. package/dist/astro/content.cjs.map +1 -1
  8. package/dist/astro/content.d.cts +12 -3
  9. package/dist/astro/content.d.ts +12 -3
  10. package/dist/astro/content.js +9 -3
  11. package/dist/astro/integration.cjs +228 -10
  12. package/dist/astro/integration.cjs.map +1 -1
  13. package/dist/astro/integration.js +3 -3
  14. package/dist/astro/middleware.cjs +2 -1
  15. package/dist/astro/middleware.cjs.map +1 -1
  16. package/dist/astro/middleware.d.cts +2 -2
  17. package/dist/astro/middleware.d.ts +2 -2
  18. package/dist/astro/middleware.js +2 -2
  19. package/dist/astro/register.cjs +228 -10
  20. package/dist/astro/register.cjs.map +1 -1
  21. package/dist/astro/register.js +3 -3
  22. package/dist/{chunk-KZ4WVDGL.js → chunk-7623G3XL.js} +3 -3
  23. package/dist/{chunk-A4RRTY5D.js → chunk-AIFJ7DVO.js} +3 -2
  24. package/dist/{chunk-A4RRTY5D.js.map → chunk-AIFJ7DVO.js.map} +1 -1
  25. package/dist/{chunk-YCVHRMM6.js → chunk-G5BMWPQ6.js} +2 -3
  26. package/dist/{chunk-YCVHRMM6.js.map → chunk-G5BMWPQ6.js.map} +1 -1
  27. package/dist/{chunk-HODG4NJQ.js → chunk-HFLU7HQE.js} +2 -2
  28. package/dist/{chunk-PG3IOI5O.js → chunk-HKMDWTA2.js} +53 -6
  29. package/dist/chunk-HKMDWTA2.js.map +1 -0
  30. package/dist/{chunk-DNYJF7BG.js → chunk-KPTMZQCY.js} +3 -3
  31. package/dist/{chunk-FNWE2DT5.js → chunk-NDSPSAWQ.js} +18 -8
  32. package/dist/chunk-NDSPSAWQ.js.map +1 -0
  33. package/dist/{chunk-UVYF33XE.js → chunk-NI7R6QZQ.js} +293 -13
  34. package/dist/chunk-NI7R6QZQ.js.map +1 -0
  35. package/dist/chunk-RI3KKDPX.js +75 -0
  36. package/dist/chunk-RI3KKDPX.js.map +1 -0
  37. package/dist/{create-jmp-analytics-D4Qw_d6o.d.cts → create-jmp-analytics-D1dUsqCQ.d.cts} +1 -2
  38. package/dist/{create-jmp-analytics-DpG5Hdl5.d.ts → create-jmp-analytics-htx2oOEf.d.ts} +1 -2
  39. package/dist/index.cjs +295 -12
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.cts +8 -6
  42. package/dist/index.d.ts +8 -6
  43. package/dist/index.js +10 -2
  44. package/dist/next/content.cjs +310 -13
  45. package/dist/next/content.cjs.map +1 -1
  46. package/dist/next/content.d.cts +7 -5
  47. package/dist/next/content.d.ts +7 -5
  48. package/dist/next/content.js +11 -3
  49. package/dist/next/content.js.map +1 -1
  50. package/dist/next/instrumentation.cjs +228 -10
  51. package/dist/next/instrumentation.cjs.map +1 -1
  52. package/dist/next/instrumentation.js +2 -2
  53. package/dist/next/landing-capture-script-server.cjs +1 -2
  54. package/dist/next/landing-capture-script-server.cjs.map +1 -1
  55. package/dist/next/landing-capture-script-server.js +1 -1
  56. package/dist/next/landing-pages.cjs +228 -12
  57. package/dist/next/landing-pages.cjs.map +1 -1
  58. package/dist/next/landing-pages.d.cts +4 -16
  59. package/dist/next/landing-pages.d.ts +4 -16
  60. package/dist/next/landing-pages.js +13 -67
  61. package/dist/next/landing-pages.js.map +1 -1
  62. package/dist/next/locations.cjs +737 -0
  63. package/dist/next/locations.cjs.map +1 -0
  64. package/dist/next/locations.d.cts +55 -0
  65. package/dist/next/locations.d.ts +55 -0
  66. package/dist/next/locations.js +158 -0
  67. package/dist/next/locations.js.map +1 -0
  68. package/dist/next/middleware.cjs +2 -1
  69. package/dist/next/middleware.cjs.map +1 -1
  70. package/dist/next/middleware.d.cts +2 -2
  71. package/dist/next/middleware.d.ts +2 -2
  72. package/dist/next/middleware.js +2 -2
  73. package/dist/next/site-root-server.cjs +259 -14
  74. package/dist/next/site-root-server.cjs.map +1 -1
  75. package/dist/next/site-root-server.js +5 -5
  76. package/dist/next.cjs +270 -17
  77. package/dist/next.cjs.map +1 -1
  78. package/dist/next.d.cts +3 -3
  79. package/dist/next.d.ts +3 -3
  80. package/dist/next.js +4 -4
  81. package/dist/react.cjs +389 -136
  82. package/dist/react.cjs.map +1 -1
  83. package/dist/react.d.cts +2 -2
  84. package/dist/react.d.ts +2 -2
  85. package/dist/react.js +3 -3
  86. package/dist/{site-config-UTzDG-UG.d.ts → site-config-B7USGGzu.d.cts} +22 -2
  87. package/dist/{site-config-CJqYnZm7.d.cts → site-config-C4bcUoLI.d.ts} +22 -2
  88. package/dist/{track-page-view-tX0Magkd.d.cts → track-page-view-C4TbbULE.d.cts} +1 -1
  89. package/dist/{track-page-view-CMAqyhD_.d.ts → track-page-view-RiB-xgIx.d.ts} +1 -1
  90. package/dist/{types-B-111Wht.d.ts → types-DRljY1Yy.d.cts} +92 -2
  91. package/dist/{types-B-111Wht.d.cts → types-DRljY1Yy.d.ts} +92 -2
  92. package/dist/utils-BajG58pj.d.cts +15 -0
  93. package/dist/utils-CHT3SQFv.d.ts +15 -0
  94. package/package.json +7 -2
  95. package/dist/chunk-FNWE2DT5.js.map +0 -1
  96. package/dist/chunk-PG3IOI5O.js.map +0 -1
  97. package/dist/chunk-UVYF33XE.js.map +0 -1
  98. /package/dist/{chunk-KZ4WVDGL.js.map → chunk-7623G3XL.js.map} +0 -0
  99. /package/dist/{chunk-HODG4NJQ.js.map → chunk-HFLU7HQE.js.map} +0 -0
  100. /package/dist/{chunk-DNYJF7BG.js.map → chunk-KPTMZQCY.js.map} +0 -0
package/dist/index.js CHANGED
@@ -15,6 +15,8 @@ import {
15
15
  getJmpLandingPageDetail,
16
16
  getJmpLandingPageSitemap,
17
17
  getJmpLandingPages,
18
+ getJmpLocationDetail,
19
+ getJmpLocations,
18
20
  getJmpRobotsTxt,
19
21
  getJmpServerContentConfigFromEnv,
20
22
  getJmpSiteProfile,
@@ -25,11 +27,13 @@ import {
25
27
  isJmpServerContentEnvConfigured,
26
28
  isJmpTrackingConsentGranted,
27
29
  markContentWrapper,
30
+ normalizeJmpContentManifest,
28
31
  registerJmpContentWrappers,
29
32
  resetContentWrapperDiscoveryForTests,
30
33
  setJmpTrackingConsent,
34
+ stableJmpManifestFingerprint,
31
35
  subscribeJmpTrackingConsent
32
- } from "./chunk-UVYF33XE.js";
36
+ } from "./chunk-NI7R6QZQ.js";
33
37
  import {
34
38
  buildLandingCaptureInlineScript
35
39
  } from "./chunk-TCZ6TC2L.js";
@@ -39,7 +43,7 @@ import {
39
43
  getJmpSiteDefinition,
40
44
  readJmpPublicEnvFromProcess,
41
45
  trackJmpServerPageView
42
- } from "./chunk-A4RRTY5D.js";
46
+ } from "./chunk-AIFJ7DVO.js";
43
47
  export {
44
48
  BOOKING_LINK_HOSTS,
45
49
  DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
@@ -60,6 +64,8 @@ export {
60
64
  getJmpLandingPageDetail,
61
65
  getJmpLandingPageSitemap,
62
66
  getJmpLandingPages,
67
+ getJmpLocationDetail,
68
+ getJmpLocations,
63
69
  getJmpRobotsTxt,
64
70
  getJmpServerContentConfigFromEnv,
65
71
  getJmpSiteDefinition,
@@ -71,10 +77,12 @@ export {
71
77
  isJmpServerContentEnvConfigured,
72
78
  isJmpTrackingConsentGranted,
73
79
  markContentWrapper,
80
+ normalizeJmpContentManifest,
74
81
  readJmpPublicEnvFromProcess,
75
82
  registerJmpContentWrappers,
76
83
  resetContentWrapperDiscoveryForTests,
77
84
  setJmpTrackingConsent,
85
+ stableJmpManifestFingerprint,
78
86
  subscribeJmpTrackingConsent,
79
87
  trackJmpServerPageView
80
88
  };
@@ -24,6 +24,7 @@ __export(content_exports, {
24
24
  filterFeaturedTrustQuotes: () => filterFeaturedTrustQuotes2,
25
25
  getJmpContentConfig: () => getJmpContentConfig,
26
26
  getResolvedSiteContact: () => getResolvedSiteContact2,
27
+ listResolvedSocialUrls: () => listResolvedSocialUrls,
27
28
  loadBlogPost: () => loadBlogPost2,
28
29
  loadBlogPosts: () => loadBlogPosts2,
29
30
  loadFaqBySlug: () => loadFaqBySlug2,
@@ -31,6 +32,8 @@ __export(content_exports, {
31
32
  loadLandingPageDetail: () => loadLandingPageDetail2,
32
33
  loadLandingPageSitemap: () => loadLandingPageSitemap2,
33
34
  loadLandingPages: () => loadLandingPages2,
35
+ loadLocationDetail: () => loadLocationDetail2,
36
+ loadLocations: () => loadLocations2,
34
37
  loadSiteProfile: () => loadSiteProfile2,
35
38
  loadTrustBundle: () => loadTrustBundle2,
36
39
  resolveSiteContact: () => resolveSiteContact2
@@ -53,6 +56,209 @@ function normalizeBaseUrl(baseUrl) {
53
56
  return baseUrl.replace(/\/$/, "");
54
57
  }
55
58
 
59
+ // src/content/manifest.ts
60
+ var JMP_CONTENT_MANIFEST_VERSION = 1;
61
+ var TRUST_SECTIONS = /* @__PURE__ */ new Set([
62
+ "summary",
63
+ "testimonials",
64
+ "reviews",
65
+ "stats",
66
+ "logos",
67
+ "credentials"
68
+ ]);
69
+ function normalizeKey(value) {
70
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
71
+ }
72
+ function isValidExtraKey(key) {
73
+ return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(key);
74
+ }
75
+ var MAX_EXTERNAL_ADMIN_LINKS = 10;
76
+ var MAX_EXTERNAL_ADMIN_LINK_LABEL_LENGTH = 80;
77
+ var EXTERNAL_ADMIN_LINK_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
78
+ function tryNormalizeHttpUrl(input) {
79
+ if (typeof input !== "string" || !input.trim()) {
80
+ return null;
81
+ }
82
+ try {
83
+ const url = new URL(input.trim());
84
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
85
+ return null;
86
+ }
87
+ return url.toString().replace(/\/$/, "");
88
+ } catch {
89
+ return null;
90
+ }
91
+ }
92
+ function normalizeShopifyExternalSource(shopify) {
93
+ if (!shopify || typeof shopify !== "object") {
94
+ return null;
95
+ }
96
+ const adminUrl = tryNormalizeHttpUrl(shopify.adminUrl);
97
+ const storeUrl = tryNormalizeHttpUrl(shopify.storeUrl);
98
+ if (!adminUrl && !storeUrl) {
99
+ return null;
100
+ }
101
+ return {
102
+ ...adminUrl ? { adminUrl } : {},
103
+ ...storeUrl ? { storeUrl } : {}
104
+ };
105
+ }
106
+ function normalizeExternalAdminLinkEntries(links) {
107
+ if (!Array.isArray(links)) {
108
+ return [];
109
+ }
110
+ const seenIds = /* @__PURE__ */ new Set();
111
+ const out = [];
112
+ for (const raw of links) {
113
+ if (!raw || typeof raw !== "object" || out.length >= MAX_EXTERNAL_ADMIN_LINKS) {
114
+ continue;
115
+ }
116
+ const id = typeof raw.id === "string" ? raw.id.trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") : "";
117
+ const label = typeof raw.label === "string" ? raw.label.trim().slice(0, MAX_EXTERNAL_ADMIN_LINK_LABEL_LENGTH) : "";
118
+ const url = tryNormalizeHttpUrl(raw.url);
119
+ if (!id || !label || !url || !EXTERNAL_ADMIN_LINK_ID_PATTERN.test(id) || seenIds.has(id)) {
120
+ continue;
121
+ }
122
+ seenIds.add(id);
123
+ out.push({ id, label, url });
124
+ }
125
+ return out;
126
+ }
127
+ function normalizeExternalSources(externalSources) {
128
+ if (!externalSources || typeof externalSources !== "object") {
129
+ return null;
130
+ }
131
+ const studioUrl = tryNormalizeHttpUrl(externalSources.sanity?.studioUrl);
132
+ const shopify = normalizeShopifyExternalSource(externalSources.shopify);
133
+ const links = normalizeExternalAdminLinkEntries(externalSources.links);
134
+ if (!studioUrl && !shopify && links.length === 0) {
135
+ return null;
136
+ }
137
+ return {
138
+ ...studioUrl ? { sanity: { studioUrl } } : {},
139
+ ...shopify ? { shopify } : {},
140
+ ...links.length > 0 ? { links } : {}
141
+ };
142
+ }
143
+ function normalizeJmpContentManifest(input) {
144
+ if (!input || typeof input !== "object") {
145
+ return null;
146
+ }
147
+ const routes = normalizeRoutes(input.routes);
148
+ const externalSources = normalizeExternalSources(input.externalSources);
149
+ const trust = normalizeTrust(input.trust);
150
+ const contact = normalizeContact(input.contact);
151
+ if (routes.length === 0 && !externalSources && !trust && !contact) {
152
+ return null;
153
+ }
154
+ return {
155
+ version: JMP_CONTENT_MANIFEST_VERSION,
156
+ ...routes.length > 0 ? { routes } : {},
157
+ ...externalSources ? { externalSources } : {},
158
+ ...trust ? { trust } : {},
159
+ ...contact ? { contact } : {}
160
+ };
161
+ }
162
+ function normalizeRoutes(routes) {
163
+ if (!Array.isArray(routes)) {
164
+ return [];
165
+ }
166
+ const seen = /* @__PURE__ */ new Set();
167
+ const out = [];
168
+ for (const raw of routes) {
169
+ if (!raw || typeof raw !== "object") continue;
170
+ const wrapper = typeof raw.wrapper === "string" ? raw.wrapper.trim().toLowerCase() : "";
171
+ const pattern = typeof raw.pattern === "string" ? raw.pattern.trim() : "";
172
+ if (!wrapper || !pattern) continue;
173
+ const dedupe = `${wrapper}:${pattern}`;
174
+ if (seen.has(dedupe)) continue;
175
+ seen.add(dedupe);
176
+ out.push({
177
+ wrapper,
178
+ pattern,
179
+ ...typeof raw.index === "string" && raw.index.trim() ? { index: raw.index.trim() } : {},
180
+ ...typeof raw.label === "string" && raw.label.trim() ? { label: raw.label.trim() } : {}
181
+ });
182
+ }
183
+ return out;
184
+ }
185
+ function normalizeTrust(trust) {
186
+ if (!trust || typeof trust !== "object") return null;
187
+ const blocks = normalizeTrustBlocks(trust.blocks);
188
+ const labels = normalizeTrustLabels(trust.labels);
189
+ const mergeTestimonialsReviews = trust.mergeTestimonialsReviews === true;
190
+ if (blocks.length === 0 && !labels && !mergeTestimonialsReviews) return null;
191
+ return {
192
+ ...blocks.length > 0 ? { blocks } : {},
193
+ ...labels ? { labels } : {},
194
+ ...mergeTestimonialsReviews ? { mergeTestimonialsReviews: true } : {}
195
+ };
196
+ }
197
+ function normalizeTrustBlocks(blocks) {
198
+ if (!Array.isArray(blocks)) return [];
199
+ const seen = /* @__PURE__ */ new Set();
200
+ const out = [];
201
+ for (const raw of blocks) {
202
+ if (!raw || typeof raw !== "object") continue;
203
+ const section = typeof raw.section === "string" ? raw.section.trim().toLowerCase() : "";
204
+ if (!TRUST_SECTIONS.has(section) || seen.has(section)) continue;
205
+ seen.add(section);
206
+ out.push({
207
+ section,
208
+ ...typeof raw.label === "string" && raw.label.trim() ? { label: raw.label.trim() } : {}
209
+ });
210
+ }
211
+ return out;
212
+ }
213
+ function normalizeTrustLabels(labels) {
214
+ if (!labels || typeof labels !== "object") return null;
215
+ const out = {};
216
+ for (const [key, value] of Object.entries(labels)) {
217
+ if (TRUST_SECTIONS.has(key) && typeof value === "string" && value.trim()) {
218
+ out[key] = value.trim();
219
+ }
220
+ }
221
+ return Object.keys(out).length > 0 ? out : null;
222
+ }
223
+ function normalizeContact(contact) {
224
+ if (!contact || typeof contact !== "object") return null;
225
+ const extras = normalizeContactExtras(contact.extras);
226
+ return extras.length > 0 ? { extras } : null;
227
+ }
228
+ function normalizeContactExtras(extras) {
229
+ if (!Array.isArray(extras)) return [];
230
+ const seen = /* @__PURE__ */ new Set();
231
+ const out = [];
232
+ for (const raw of extras) {
233
+ if (!raw || typeof raw !== "object") continue;
234
+ const label = typeof raw.label === "string" ? raw.label.trim() : "";
235
+ const key = normalizeKey(
236
+ typeof raw.key === "string" && raw.key.trim() ? raw.key : label
237
+ );
238
+ if (!key || !label || !isValidExtraKey(key) || seen.has(key)) continue;
239
+ seen.add(key);
240
+ out.push({ key, label });
241
+ }
242
+ return out;
243
+ }
244
+ function stableJmpManifestFingerprint(manifest) {
245
+ return manifest ? JSON.stringify(manifest) : "";
246
+ }
247
+ function inferWrapperSlotsFromManifest(manifest) {
248
+ const slots = /* @__PURE__ */ new Set();
249
+ for (const route of manifest?.routes ?? []) {
250
+ slots.add(route.wrapper);
251
+ }
252
+ for (const block of manifest?.trust?.blocks ?? []) {
253
+ slots.add(`trust.${block.section}`);
254
+ slots.add("trust");
255
+ }
256
+ if (manifest?.contact?.extras?.length) {
257
+ slots.add("contact");
258
+ }
259
+ return [...slots];
260
+ }
261
+
56
262
  // src/content/fetch.ts
57
263
  async function getContent(config, path) {
58
264
  const text = await getContentText(config, path);
@@ -167,16 +373,22 @@ function inferTrustWrapperSlots(bundle) {
167
373
  function getDiscoveredContentWrappers() {
168
374
  return sortWrapperSlots([...discovered]);
169
375
  }
376
+ function resolveContentManifestForReport(config) {
377
+ return normalizeJmpContentManifest(config.contentManifest);
378
+ }
170
379
  function resolveContentWrappersForReport(config) {
171
380
  const explicit = config.contentWrappers ?? [];
172
381
  const auto = getDiscoveredContentWrappers();
382
+ const fromManifest = inferWrapperSlotsFromManifest(
383
+ resolveContentManifestForReport(config)
384
+ );
173
385
  if (config.contentWrapperMode === "manual") {
174
- return sortWrapperSlots([...explicit]);
386
+ return sortWrapperSlots([...explicit, ...fromManifest]);
175
387
  }
176
388
  if (config.contentWrapperMode === "explicit-only") {
177
- return sortWrapperSlots([...explicit]);
389
+ return sortWrapperSlots([...explicit, ...fromManifest]);
178
390
  }
179
- const merged = /* @__PURE__ */ new Set([...explicit, ...auto]);
391
+ const merged = /* @__PURE__ */ new Set([...explicit, ...auto, ...fromManifest]);
180
392
  return sortWrapperSlots([...merged]);
181
393
  }
182
394
  function hasReportedContentWrappers(dedupeKey) {
@@ -304,6 +516,35 @@ async function getJmpLandingPageSitemap(config) {
304
516
  afterContentWrapperUse(config);
305
517
  return data.entries;
306
518
  }
519
+ async function getJmpLocations(config) {
520
+ const data = await getContent(
521
+ config,
522
+ "/api/content/locations"
523
+ );
524
+ markContentWrapper("locations");
525
+ afterContentWrapperUse(config);
526
+ return data.locations;
527
+ }
528
+ async function getJmpLocationDetail(config, slug) {
529
+ const normalized = slug.trim();
530
+ if (!normalized) {
531
+ return null;
532
+ }
533
+ try {
534
+ const detail = await getContent(
535
+ config,
536
+ `/api/content/locations/${encodeURIComponent(normalized)}`
537
+ );
538
+ markContentWrapper("locations");
539
+ afterContentWrapperUse(config);
540
+ return detail;
541
+ } catch (error) {
542
+ if (error instanceof Error && error.message.includes("HTTP 404")) {
543
+ return null;
544
+ }
545
+ throw error;
546
+ }
547
+ }
307
548
  async function getJmpTrustBundle(config) {
308
549
  const bundle = await getContent(config, "/api/content/trust");
309
550
  markTrustBundleWrappers(bundle);
@@ -324,7 +565,8 @@ async function registerJmpContentWrappers(config) {
324
565
  if (!wrappers.length) {
325
566
  return { ok: false, skipped: true };
326
567
  }
327
- const dedupeKey = `${config.trackingKey}:${[...wrappers].sort().join(",")}`;
568
+ const manifest = resolveContentManifestForReport(config);
569
+ const dedupeKey = `${config.trackingKey}:${[...wrappers].sort().join(",")}:${stableJmpManifestFingerprint(manifest)}`;
328
570
  if (hasReportedContentWrappers(dedupeKey)) {
329
571
  return { ok: true, wrappers };
330
572
  }
@@ -337,7 +579,17 @@ async function registerJmpContentWrappers(config) {
337
579
  }
338
580
  const url = `${baseUrl}/api/content/capabilities`;
339
581
  if (config.debug) {
340
- console.debug("[@jmp-technologies/analytics]", "POST", url, { wrappers });
582
+ console.debug("[@jmp-technologies/analytics]", "POST", url, {
583
+ wrappers,
584
+ manifest
585
+ });
586
+ }
587
+ const body = {
588
+ wrappers,
589
+ sdkVersion: JMP_ANALYTICS_SDK_VERSION
590
+ };
591
+ if (manifest) {
592
+ body.manifest = manifest;
341
593
  }
342
594
  const res = await resolvedFetch(url, {
343
595
  method: "POST",
@@ -345,10 +597,7 @@ async function registerJmpContentWrappers(config) {
345
597
  "Content-Type": "application/json",
346
598
  "X-JMP-Tracking-Key": config.trackingKey
347
599
  },
348
- body: JSON.stringify({
349
- wrappers,
350
- sdkVersion: JMP_ANALYTICS_SDK_VERSION
351
- })
600
+ body: JSON.stringify(body)
352
601
  });
353
602
  const text = await res.text();
354
603
  if (!res.ok) {
@@ -427,7 +676,8 @@ function getJmpContentConfig() {
427
676
  return {
428
677
  baseUrl: analyticsUrl,
429
678
  trackingKey,
430
- contentWrappers: site?.contentWrappers ?? void 0
679
+ contentWrappers: site?.contentWrappers ?? void 0,
680
+ contentManifest: site?.contentManifest ?? void 0
431
681
  };
432
682
  }
433
683
 
@@ -437,7 +687,8 @@ var DEFAULT_EXTRA_KEYS = {
437
687
  dashboardDemoUrl: ["dashboard-demo-url", "sample-dashboard-url"],
438
688
  profilePhotoSrc: ["profile-photo-url", "profile_photo_url"],
439
689
  hours: ["hours", "business-hours"],
440
- serviceArea: ["service-area", "service_area", "service-area-text"]
690
+ serviceArea: ["service-area", "service_area", "service-area-text"],
691
+ googleMapsEmbedUrl: ["google-maps-embed-url", "google_maps_embed_url"]
441
692
  };
442
693
  function sortBlogPosts(posts) {
443
694
  return [...posts].sort((a, b) => {
@@ -488,7 +739,13 @@ function resolveSiteContact(profile) {
488
739
  ...site?.contactExtraKeys
489
740
  };
490
741
  const email = profile?.email?.trim() || fallback.email || "";
491
- const linkedin = profile?.social?.linkedin?.trim() || fallback.linkedin || null;
742
+ const social = {
743
+ linkedin: profile?.social?.linkedin?.trim() || fallback.linkedin || null,
744
+ instagram: profile?.social?.instagram?.trim() || fallback.instagram || null,
745
+ facebook: profile?.social?.facebook?.trim() || fallback.facebook || null,
746
+ x: profile?.social?.x?.trim() || fallback.x || null,
747
+ youtube: profile?.social?.youtube?.trim() || fallback.youtube || null
748
+ };
492
749
  const phone = profile?.phone?.trim() || fallback.phone || null;
493
750
  return {
494
751
  displayName: profile?.display_name?.trim() || profile?.name?.trim() || fallback.displayName || "",
@@ -496,8 +753,12 @@ function resolveSiteContact(profile) {
496
753
  dashboardDemoUrl: readProfileExtra(profile, extraKeys.dashboardDemoUrl ?? []) || fallback.dashboardDemoUrl || "",
497
754
  profilePhotoSrc: readProfileExtra(profile, extraKeys.profilePhotoSrc ?? []) || fallback.profilePhotoSrc || "",
498
755
  email,
499
- linkedin,
756
+ linkedin: social.linkedin,
757
+ social,
500
758
  phone,
759
+ address: profile?.address?.trim() || fallback.address || null,
760
+ googleMapsUrl: profile?.google_maps_url?.trim() || fallback.googleMapsUrl || null,
761
+ googleMapsEmbedUrl: readProfileExtra(profile, extraKeys.googleMapsEmbedUrl ?? []) || fallback.googleMapsEmbedUrl || null,
501
762
  hours: readProfileExtra(profile, extraKeys.hours ?? []) || fallback.hours || null,
502
763
  serviceArea: readProfileExtra(profile, extraKeys.serviceArea ?? []) || fallback.serviceArea || null,
503
764
  privacyUrl: profile?.legal?.privacy_policy_url?.trim() || fallback.privacyUrl || "/privacy",
@@ -512,6 +773,15 @@ async function getResolvedSiteContact() {
512
773
  const profile = await loadSiteProfile();
513
774
  return resolveSiteContact(profile);
514
775
  }
776
+ function listResolvedSocialUrls(social) {
777
+ return [
778
+ social.linkedin,
779
+ social.instagram,
780
+ social.facebook,
781
+ social.x,
782
+ social.youtube
783
+ ].filter((url) => Boolean(url));
784
+ }
515
785
  async function loadBlogPosts() {
516
786
  const c = getJmpContentConfig();
517
787
  if (!c) {
@@ -588,6 +858,28 @@ async function loadLandingPageSitemap() {
588
858
  return [];
589
859
  }
590
860
  }
861
+ async function loadLocations() {
862
+ const c = getJmpContentConfig();
863
+ if (!c) {
864
+ return [];
865
+ }
866
+ try {
867
+ return await getJmpLocations(c);
868
+ } catch {
869
+ return [];
870
+ }
871
+ }
872
+ async function loadLocationDetail(slug) {
873
+ const c = getJmpContentConfig();
874
+ if (!c) {
875
+ return null;
876
+ }
877
+ try {
878
+ return await getJmpLocationDetail(c, slug);
879
+ } catch {
880
+ return null;
881
+ }
882
+ }
591
883
  async function loadTrustBundle() {
592
884
  const c = getJmpContentConfig();
593
885
  if (!c) {
@@ -625,6 +917,8 @@ var loadFaqBySlug2 = loadFaqBySlug;
625
917
  var loadLandingPages2 = (0, import_react.cache)(loadLandingPages);
626
918
  var loadLandingPageDetail2 = loadLandingPageDetail;
627
919
  var loadLandingPageSitemap2 = (0, import_react.cache)(loadLandingPageSitemap);
920
+ var loadLocations2 = (0, import_react.cache)(loadLocations);
921
+ var loadLocationDetail2 = loadLocationDetail;
628
922
  var loadTrustBundle2 = (0, import_react.cache)(loadTrustBundle);
629
923
  // Annotate the CommonJS export names for ESM import in node:
630
924
  0 && (module.exports = {
@@ -632,6 +926,7 @@ var loadTrustBundle2 = (0, import_react.cache)(loadTrustBundle);
632
926
  filterFeaturedTrustQuotes,
633
927
  getJmpContentConfig,
634
928
  getResolvedSiteContact,
929
+ listResolvedSocialUrls,
635
930
  loadBlogPost,
636
931
  loadBlogPosts,
637
932
  loadFaqBySlug,
@@ -639,6 +934,8 @@ var loadTrustBundle2 = (0, import_react.cache)(loadTrustBundle);
639
934
  loadLandingPageDetail,
640
935
  loadLandingPageSitemap,
641
936
  loadLandingPages,
937
+ loadLocationDetail,
938
+ loadLocations,
642
939
  loadSiteProfile,
643
940
  loadTrustBundle,
644
941
  resolveSiteContact