@jmp-technologies/analytics 0.1.38 → 0.1.40

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 (89) hide show
  1. package/README.md +6 -2
  2. package/ai-crawler-agents.json +63 -0
  3. package/dist/astro/client.cjs +257 -6
  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 +1 -1
  8. package/dist/astro/content.cjs +264 -7
  9. package/dist/astro/content.cjs.map +1 -1
  10. package/dist/astro/content.d.cts +3 -3
  11. package/dist/astro/content.d.ts +3 -3
  12. package/dist/astro/content.js +2 -2
  13. package/dist/astro/integration.cjs +257 -6
  14. package/dist/astro/integration.cjs.map +1 -1
  15. package/dist/astro/integration.js +2 -2
  16. package/dist/astro/middleware.d.cts +2 -2
  17. package/dist/astro/middleware.d.ts +2 -2
  18. package/dist/astro/register.cjs +257 -6
  19. package/dist/astro/register.cjs.map +1 -1
  20. package/dist/astro/register.js +2 -2
  21. package/dist/{chunk-WHUHCTBQ.js → chunk-34LFIP3R.js} +2 -2
  22. package/dist/{chunk-NCF3J4HV.js → chunk-BRLCGVFJ.js} +2 -2
  23. package/dist/{chunk-PQOTEV6O.js → chunk-IY6Y636W.js} +2 -2
  24. package/dist/{chunk-EBU4DKHW.js → chunk-JC3G4XNR.js} +333 -8
  25. package/dist/chunk-JC3G4XNR.js.map +1 -0
  26. package/dist/{chunk-JVFN7MF2.js → chunk-VSZRQSUN.js} +2 -2
  27. package/dist/constants-DTZMYgi4.d.cts +12 -0
  28. package/dist/constants-DTZMYgi4.d.ts +12 -0
  29. package/dist/{create-jmp-analytics-DMSXmVIH.d.cts → create-jmp-analytics-B7VqQJca.d.cts} +1 -1
  30. package/dist/{create-jmp-analytics-JZ3pqNBQ.d.ts → create-jmp-analytics-BGt16QGY.d.ts} +1 -1
  31. package/dist/index.cjs +340 -7
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +31 -13
  34. package/dist/index.d.ts +31 -13
  35. package/dist/index.js +17 -1
  36. package/dist/next/content.cjs +268 -7
  37. package/dist/next/content.cjs.map +1 -1
  38. package/dist/next/content.d.cts +3 -2
  39. package/dist/next/content.d.ts +3 -2
  40. package/dist/next/content.js +7 -2
  41. package/dist/next/content.js.map +1 -1
  42. package/dist/next/instrumentation.cjs +257 -6
  43. package/dist/next/instrumentation.cjs.map +1 -1
  44. package/dist/next/instrumentation.js +1 -1
  45. package/dist/next/landing-pages.cjs +264 -7
  46. package/dist/next/landing-pages.cjs.map +1 -1
  47. package/dist/next/landing-pages.d.cts +2 -2
  48. package/dist/next/landing-pages.d.ts +2 -2
  49. package/dist/next/landing-pages.js +2 -2
  50. package/dist/next/locations.cjs +265 -8
  51. package/dist/next/locations.cjs.map +1 -1
  52. package/dist/next/locations.d.cts +3 -3
  53. package/dist/next/locations.d.ts +3 -3
  54. package/dist/next/locations.js +3 -3
  55. package/dist/next/locations.js.map +1 -1
  56. package/dist/next/middleware.cjs.map +1 -1
  57. package/dist/next/middleware.d.cts +2 -2
  58. package/dist/next/middleware.d.ts +2 -2
  59. package/dist/next/middleware.js.map +1 -1
  60. package/dist/next/site-root-server.cjs +264 -7
  61. package/dist/next/site-root-server.cjs.map +1 -1
  62. package/dist/next/site-root-server.d.cts +1 -1
  63. package/dist/next/site-root-server.d.ts +1 -1
  64. package/dist/next/site-root-server.js +3 -3
  65. package/dist/next/site-root-server.js.map +1 -1
  66. package/dist/next.cjs +257 -6
  67. package/dist/next.cjs.map +1 -1
  68. package/dist/next.d.cts +3 -3
  69. package/dist/next.d.ts +3 -3
  70. package/dist/next.js +3 -3
  71. package/dist/react.cjs +257 -6
  72. package/dist/react.cjs.map +1 -1
  73. package/dist/react.d.cts +2 -2
  74. package/dist/react.d.ts +2 -2
  75. package/dist/react.js +2 -2
  76. package/dist/{site-config-BZJS8Hp_.d.cts → site-config-CZl4PIbg.d.cts} +1 -1
  77. package/dist/{site-config-BLnwuRC2.d.ts → site-config-Cq5K8hUp.d.ts} +1 -1
  78. package/dist/{track-page-view-DGKRUIxm.d.ts → track-page-view-BSlE0yI9.d.ts} +1 -1
  79. package/dist/{track-page-view-BJQqn2Bg.d.cts → track-page-view-M9y_5WqT.d.cts} +1 -1
  80. package/dist/{types-CYrgEwUF.d.ts → types-DH_8sBu9.d.cts} +35 -0
  81. package/dist/{types-CYrgEwUF.d.cts → types-DH_8sBu9.d.ts} +35 -0
  82. package/dist/{utils-B1Nt3sBU.d.ts → utils-C2JRomti.d.ts} +1 -1
  83. package/dist/{utils-U6TGMIAB.d.cts → utils-JfjoqC-z.d.cts} +1 -1
  84. package/package.json +2 -1
  85. package/dist/chunk-EBU4DKHW.js.map +0 -1
  86. /package/dist/{chunk-WHUHCTBQ.js.map → chunk-34LFIP3R.js.map} +0 -0
  87. /package/dist/{chunk-NCF3J4HV.js.map → chunk-BRLCGVFJ.js.map} +0 -0
  88. /package/dist/{chunk-PQOTEV6O.js.map → chunk-IY6Y636W.js.map} +0 -0
  89. /package/dist/{chunk-JVFN7MF2.js.map → chunk-VSZRQSUN.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -20,10 +20,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ AI_CRAWLER_ROBOTS_USER_AGENTS: () => AI_CRAWLER_ROBOTS_USER_AGENTS,
23
24
  BOOKING_LINK_HOSTS: () => BOOKING_LINK_HOSTS,
24
25
  DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS: () => DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
26
+ JMP_AI_CRAWLER_WAF_USER_AGENTS: () => JMP_AI_CRAWLER_WAF_USER_AGENTS,
25
27
  JMP_ANALYTICS_SDK_VERSION: () => JMP_ANALYTICS_SDK_VERSION,
28
+ JMP_CONTENT_CACHE_TAG: () => JMP_CONTENT_CACHE_TAG,
29
+ JMP_CONTENT_REVALIDATE_SECONDS: () => JMP_CONTENT_REVALIDATE_SECONDS,
26
30
  JMP_TRACKING_CONSENT_STORAGE_KEY: () => JMP_TRACKING_CONSENT_STORAGE_KEY,
31
+ buildAiCrawlerRobotsTxt: () => buildAiCrawlerRobotsTxt,
27
32
  buildLandingCaptureInlineScript: () => buildLandingCaptureInlineScript,
28
33
  classifyContactHref: () => classifyContactHref,
29
34
  createJmpAnalytics: () => createJmpAnalytics,
@@ -56,7 +61,10 @@ __export(index_exports, {
56
61
  isJmpBrowserAnalyticsEnvConfigured: () => isJmpBrowserAnalyticsEnvConfigured,
57
62
  isJmpServerContentEnvConfigured: () => isJmpServerContentEnvConfigured,
58
63
  isJmpTrackingConsentGranted: () => isJmpTrackingConsentGranted,
64
+ jmpAiCrawlerVercelWafRoute: () => jmpAiCrawlerVercelWafRoute,
65
+ jmpAiCrawlerWafUserAgentPattern: () => jmpAiCrawlerWafUserAgentPattern,
59
66
  markContentWrapper: () => markContentWrapper,
67
+ mergeJmpRobotsTxt: () => mergeJmpRobotsTxt,
60
68
  normalizeJmpContentManifest: () => normalizeJmpContentManifest,
61
69
  readJmpPublicEnvFromProcess: () => readJmpPublicEnvFromProcess,
62
70
  registerJmpContentWrappers: () => registerJmpContentWrappers,
@@ -350,12 +358,14 @@ function extractMailtoTarget(href) {
350
358
  }
351
359
 
352
360
  // package.json
353
- var version = "0.1.38";
361
+ var version = "0.1.40";
354
362
 
355
363
  // src/constants.ts
356
364
  var JMP_ANALYTICS_SDK_VERSION = version;
357
365
  var JMP_TRACKING_CONSENT_STORAGE_KEY = "jmp_analytics_consent_v1";
358
366
  var DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 2500;
367
+ var JMP_CONTENT_CACHE_TAG = "jmp-content";
368
+ var JMP_CONTENT_REVALIDATE_SECONDS = 3600;
359
369
 
360
370
  // src/consent.ts
361
371
  var moduleTrackingConsentGranted = true;
@@ -1092,7 +1102,8 @@ function normalizeJmpContentManifest(input) {
1092
1102
  const externalSources = normalizeExternalSources(input.externalSources);
1093
1103
  const trust = normalizeTrust(input.trust);
1094
1104
  const contact = normalizeContact(input.contact);
1095
- if (routes.length === 0 && !externalSources && !trust && !contact) {
1105
+ const defaults = normalizeManifestDefaults(input.defaults);
1106
+ if (routes.length === 0 && !externalSources && !trust && !contact && !defaults) {
1096
1107
  return null;
1097
1108
  }
1098
1109
  return {
@@ -1100,7 +1111,8 @@ function normalizeJmpContentManifest(input) {
1100
1111
  ...routes.length > 0 ? { routes } : {},
1101
1112
  ...externalSources ? { externalSources } : {},
1102
1113
  ...trust ? { trust } : {},
1103
- ...contact ? { contact } : {}
1114
+ ...contact ? { contact } : {},
1115
+ ...defaults ? { defaults } : {}
1104
1116
  };
1105
1117
  }
1106
1118
  function normalizeRoutes(routes) {
@@ -1164,10 +1176,132 @@ function normalizeTrustLabels(labels) {
1164
1176
  }
1165
1177
  return Object.keys(out).length > 0 ? out : null;
1166
1178
  }
1179
+ function readDefaultText(value, max = 500) {
1180
+ if (typeof value !== "string") return void 0;
1181
+ const trimmed = value.trim();
1182
+ if (!trimmed) return void 0;
1183
+ return trimmed.slice(0, max);
1184
+ }
1185
+ function normalizeManifestDefaults(defaults) {
1186
+ if (!defaults || typeof defaults !== "object") return null;
1187
+ const contactRaw = defaults.contact;
1188
+ const contact = {};
1189
+ if (contactRaw && typeof contactRaw === "object") {
1190
+ const displayName = readDefaultText(contactRaw.displayName, 120);
1191
+ const email = readDefaultText(contactRaw.email, 200);
1192
+ const phone = readDefaultText(contactRaw.phone, 40);
1193
+ const address = readDefaultText(contactRaw.address, 400);
1194
+ const hours = readDefaultText(contactRaw.hours, 400);
1195
+ const serviceArea = readDefaultText(contactRaw.serviceArea, 200);
1196
+ const googleMapsUrl = readDefaultText(contactRaw.googleMapsUrl, 2048);
1197
+ const linkedinUrl = readDefaultText(contactRaw.linkedinUrl, 2048);
1198
+ const instagramUrl = readDefaultText(contactRaw.instagramUrl, 2048);
1199
+ const facebookUrl = readDefaultText(contactRaw.facebookUrl, 2048);
1200
+ const xUrl = readDefaultText(contactRaw.xUrl, 2048);
1201
+ const youtubeUrl = readDefaultText(contactRaw.youtubeUrl, 2048);
1202
+ if (displayName) contact.displayName = displayName;
1203
+ if (email) contact.email = email;
1204
+ if (phone) contact.phone = phone;
1205
+ if (address) contact.address = address;
1206
+ if (hours) contact.hours = hours;
1207
+ if (serviceArea) contact.serviceArea = serviceArea;
1208
+ if (googleMapsUrl) contact.googleMapsUrl = googleMapsUrl;
1209
+ if (linkedinUrl) contact.linkedinUrl = linkedinUrl;
1210
+ if (instagramUrl) contact.instagramUrl = instagramUrl;
1211
+ if (facebookUrl) contact.facebookUrl = facebookUrl;
1212
+ if (xUrl) contact.xUrl = xUrl;
1213
+ if (youtubeUrl) contact.youtubeUrl = youtubeUrl;
1214
+ if (contactRaw.extras && typeof contactRaw.extras === "object") {
1215
+ const extras = {};
1216
+ for (const [rawKey, rawValue] of Object.entries(contactRaw.extras)) {
1217
+ if (Object.keys(extras).length >= 10) break;
1218
+ const key = normalizeKey(rawKey);
1219
+ const value = readDefaultText(rawValue, 200);
1220
+ if (key && isValidExtraKey(key) && value) extras[key] = value;
1221
+ }
1222
+ if (Object.keys(extras).length > 0) contact.extras = extras;
1223
+ }
1224
+ }
1225
+ const faq = [];
1226
+ if (Array.isArray(defaults.faq)) {
1227
+ for (const raw of defaults.faq) {
1228
+ if (!raw || typeof raw !== "object" || faq.length >= 40) continue;
1229
+ const question = readDefaultText(raw.question, 300);
1230
+ const answer = readDefaultText(raw.answer, 8e3);
1231
+ if (!question || !answer) continue;
1232
+ const category = readDefaultText(raw.category, 80);
1233
+ faq.push({ question, answer, ...category ? { category } : {} });
1234
+ }
1235
+ }
1236
+ const trustRaw = defaults.trust;
1237
+ const trust = {};
1238
+ if (trustRaw && typeof trustRaw === "object") {
1239
+ const assign = (key, max) => {
1240
+ const value = readDefaultText(trustRaw[key], max);
1241
+ if (value) trust[key] = value;
1242
+ };
1243
+ assign("googleReviewsUrl", 2048);
1244
+ assign("googlePlaceId", 128);
1245
+ assign("yelpUrl", 2048);
1246
+ assign("trustpilotUrl", 2048);
1247
+ assign("disclaimer", 1e3);
1248
+ }
1249
+ const hasContact = Object.keys(contact).length > 0;
1250
+ const hasTrust = Object.keys(trust).length > 0;
1251
+ if (!hasContact && faq.length === 0 && !hasTrust) return null;
1252
+ return {
1253
+ ...hasContact ? { contact } : {},
1254
+ ...faq.length > 0 ? { faq } : {},
1255
+ ...hasTrust ? { trust } : {}
1256
+ };
1257
+ }
1167
1258
  function normalizeContact(contact) {
1168
1259
  if (!contact || typeof contact !== "object") return null;
1169
1260
  const extras = normalizeContactExtras(contact.extras);
1170
- return extras.length > 0 ? { extras } : null;
1261
+ const leadInbox = normalizeLeadInbox(contact.leadInbox);
1262
+ if (extras.length === 0 && !leadInbox) return null;
1263
+ return {
1264
+ ...extras.length > 0 ? { extras } : {},
1265
+ ...leadInbox ? { leadInbox } : {}
1266
+ };
1267
+ }
1268
+ function normalizeLeadInbox(raw) {
1269
+ if (!raw || typeof raw !== "object") return null;
1270
+ const list = normalizeInboxKeyList(raw.list, 8);
1271
+ const detail = normalizeInboxKeyList(raw.detail, 24);
1272
+ const labels = normalizeInboxLabels(raw.labels);
1273
+ if (!list && !detail && !labels) return null;
1274
+ return {
1275
+ ...list ? { list } : {},
1276
+ ...detail ? { detail } : {},
1277
+ ...labels ? { labels } : {}
1278
+ };
1279
+ }
1280
+ function normalizeInboxKeyList(raw, max) {
1281
+ if (!Array.isArray(raw)) return void 0;
1282
+ const seen = /* @__PURE__ */ new Set();
1283
+ const out = [];
1284
+ for (const item of raw) {
1285
+ if (typeof item !== "string" || out.length >= max) continue;
1286
+ const key = item.trim();
1287
+ const token = key.replace(/[^a-zA-Z0-9]+/g, "").toLowerCase();
1288
+ if (!key || !token || seen.has(token)) continue;
1289
+ seen.add(token);
1290
+ out.push(key);
1291
+ }
1292
+ return out.length > 0 ? out : void 0;
1293
+ }
1294
+ function normalizeInboxLabels(raw) {
1295
+ if (!raw || typeof raw !== "object") return void 0;
1296
+ const out = {};
1297
+ for (const [key, value] of Object.entries(raw)) {
1298
+ if (typeof value !== "string") continue;
1299
+ const label = value.trim().slice(0, 60);
1300
+ const token = key.trim();
1301
+ if (!token || !label) continue;
1302
+ out[token] = label;
1303
+ }
1304
+ return Object.keys(out).length > 0 ? out : void 0;
1171
1305
  }
1172
1306
  function normalizeContactExtras(extras) {
1173
1307
  if (!Array.isArray(extras)) return [];
@@ -1197,7 +1331,7 @@ function inferWrapperSlotsFromManifest(manifest) {
1197
1331
  slots.add(`trust.${block.section}`);
1198
1332
  slots.add("trust");
1199
1333
  }
1200
- if (manifest?.contact?.extras?.length) {
1334
+ if (manifest?.contact?.extras?.length || manifest?.contact?.leadInbox) {
1201
1335
  slots.add("contact");
1202
1336
  }
1203
1337
  return [...slots];
@@ -1231,7 +1365,11 @@ async function getContentText(config, path) {
1231
1365
  }
1232
1366
  const res = await resolvedFetch(url, {
1233
1367
  method: "GET",
1234
- headers: jmpContentRequestHeaders(config)
1368
+ headers: jmpContentRequestHeaders(config),
1369
+ next: {
1370
+ revalidate: JMP_CONTENT_REVALIDATE_SECONDS,
1371
+ tags: [JMP_CONTENT_CACHE_TAG]
1372
+ }
1235
1373
  });
1236
1374
  const text = await res.text();
1237
1375
  if (!res.ok) {
@@ -1322,7 +1460,65 @@ function getDiscoveredContentWrappers() {
1322
1460
  return sortWrapperSlots([...discovered]);
1323
1461
  }
1324
1462
  function resolveContentManifestForReport(config) {
1325
- return normalizeJmpContentManifest(config.contentManifest);
1463
+ const site = getJmpSiteDefinition();
1464
+ const fallback = site?.contactFallback;
1465
+ const existing = config.contentManifest;
1466
+ const fromFallback = fallbackToManifestDefaults(fallback);
1467
+ if (!existing && !fromFallback) {
1468
+ return null;
1469
+ }
1470
+ const merged = {
1471
+ ...existing ?? {},
1472
+ defaults: {
1473
+ ...fromFallback ?? {},
1474
+ ...existing?.defaults ?? {},
1475
+ contact: {
1476
+ ...fromFallback?.contact ?? {},
1477
+ ...existing?.defaults?.contact ?? {},
1478
+ extras: {
1479
+ ...fromFallback?.contact?.extras ?? {},
1480
+ ...existing?.defaults?.contact?.extras ?? {}
1481
+ }
1482
+ },
1483
+ trust: {
1484
+ ...fromFallback?.trust ?? {},
1485
+ ...existing?.defaults?.trust ?? {}
1486
+ },
1487
+ faq: existing?.defaults?.faq?.length ? existing.defaults.faq : fromFallback?.faq
1488
+ }
1489
+ };
1490
+ return normalizeJmpContentManifest(merged);
1491
+ }
1492
+ function fallbackToManifestDefaults(fallback) {
1493
+ if (!fallback) return null;
1494
+ const contact = {};
1495
+ if (fallback.displayName?.trim()) contact.displayName = fallback.displayName.trim();
1496
+ if (fallback.email?.trim()) contact.email = fallback.email.trim();
1497
+ if (typeof fallback.phone === "string" && fallback.phone.trim()) {
1498
+ contact.phone = fallback.phone.trim();
1499
+ }
1500
+ if (fallback.address?.trim()) contact.address = fallback.address.trim();
1501
+ if (fallback.hours?.trim()) contact.hours = fallback.hours.trim();
1502
+ if (fallback.serviceArea?.trim()) contact.serviceArea = fallback.serviceArea.trim();
1503
+ if (fallback.googleMapsUrl?.trim()) {
1504
+ contact.googleMapsUrl = fallback.googleMapsUrl.trim();
1505
+ }
1506
+ if (fallback.linkedin?.trim()) contact.linkedinUrl = fallback.linkedin.trim();
1507
+ if (fallback.instagram?.trim()) contact.instagramUrl = fallback.instagram.trim();
1508
+ if (fallback.facebook?.trim()) contact.facebookUrl = fallback.facebook.trim();
1509
+ if (fallback.x?.trim()) contact.xUrl = fallback.x.trim();
1510
+ if (fallback.youtube?.trim()) contact.youtubeUrl = fallback.youtube.trim();
1511
+ const trust = {};
1512
+ if (fallback.googleMapsUrl?.trim()) {
1513
+ trust.googleReviewsUrl = fallback.googleMapsUrl.trim();
1514
+ }
1515
+ const hasContact = Object.keys(contact).length > 0;
1516
+ const hasTrust = Object.keys(trust).length > 0;
1517
+ if (!hasContact && !hasTrust) return null;
1518
+ return {
1519
+ ...hasContact ? { contact } : {},
1520
+ ...hasTrust ? { trust } : {}
1521
+ };
1326
1522
  }
1327
1523
  function resolveContentWrappersForReport(config) {
1328
1524
  const explicit = config.contentWrappers ?? [];
@@ -1681,6 +1877,135 @@ async function registerJmpContentWrappers(config) {
1681
1877
  }
1682
1878
  setContentWrapperSyncHandler(registerJmpContentWrappers);
1683
1879
 
1880
+ // ai-crawler-agents.json
1881
+ var ai_crawler_agents_default = {
1882
+ robotsUserAgents: [
1883
+ "GPTBot",
1884
+ "ChatGPT-User",
1885
+ "OAI-SearchBot",
1886
+ "OAI-AdsBot",
1887
+ "ClaudeBot",
1888
+ "Claude-User",
1889
+ "Claude-SearchBot",
1890
+ "Claude-Web",
1891
+ "PerplexityBot",
1892
+ "Perplexity-User",
1893
+ "Google-Extended",
1894
+ "GoogleOther",
1895
+ "GoogleOther-Image",
1896
+ "GoogleOther-Video",
1897
+ "Google-CloudVertexBot",
1898
+ "Meta-ExternalAgent",
1899
+ "Meta-ExternalFetcher",
1900
+ "FacebookBot",
1901
+ "Applebot",
1902
+ "Applebot-Extended",
1903
+ "CCBot",
1904
+ "Bytespider",
1905
+ "cohere-ai",
1906
+ "cohere-training-data-crawler",
1907
+ "YouBot",
1908
+ "MistralAI-User",
1909
+ "GrokBot",
1910
+ "Grok-DeepSearch",
1911
+ "xAI-Grok",
1912
+ "xAI-Bot"
1913
+ ],
1914
+ wafUserAgents: [
1915
+ "GPTBot",
1916
+ "ChatGPT-User",
1917
+ "OAI-SearchBot",
1918
+ "OAI-AdsBot",
1919
+ "ClaudeBot",
1920
+ "Claude-User",
1921
+ "Claude-SearchBot",
1922
+ "Claude-Web",
1923
+ "PerplexityBot",
1924
+ "Perplexity-User",
1925
+ "Google-Extended",
1926
+ "GoogleOther",
1927
+ "Google-CloudVertexBot",
1928
+ "Meta-ExternalAgent",
1929
+ "Meta-ExternalFetcher",
1930
+ "FacebookBot",
1931
+ "Applebot-Extended",
1932
+ "CCBot",
1933
+ "Bytespider",
1934
+ "cohere-ai",
1935
+ "cohere-training-data-crawler",
1936
+ "YouBot",
1937
+ "MistralAI-User",
1938
+ "GrokBot",
1939
+ "Grok-DeepSearch",
1940
+ "xAI-Grok",
1941
+ "xAI-Bot"
1942
+ ]
1943
+ };
1944
+
1945
+ // src/ai-crawlers.ts
1946
+ var AI_CRAWLER_ROBOTS_USER_AGENTS = ai_crawler_agents_default.robotsUserAgents;
1947
+ var JMP_AI_CRAWLER_WAF_USER_AGENTS = ai_crawler_agents_default.wafUserAgents;
1948
+ function buildAiCrawlerRobotsTxt(blockAiCrawlers) {
1949
+ if (!blockAiCrawlers) {
1950
+ return [
1951
+ "# JMP AI crawler policy",
1952
+ "# AI crawler blocking is disabled for this website.",
1953
+ ""
1954
+ ].join("\n");
1955
+ }
1956
+ return [
1957
+ "# JMP AI crawler policy",
1958
+ "# Blocks known AI training, answer, and fetch bots that honor robots.txt.",
1959
+ ...AI_CRAWLER_ROBOTS_USER_AGENTS.flatMap((agent) => [
1960
+ `User-agent: ${agent}`,
1961
+ "Disallow: /",
1962
+ ""
1963
+ ])
1964
+ ].join("\n");
1965
+ }
1966
+ function jmpAiCrawlerWafUserAgentPattern() {
1967
+ return JMP_AI_CRAWLER_WAF_USER_AGENTS.map(escapeRegExp).join("|");
1968
+ }
1969
+ function jmpAiCrawlerVercelWafRoute() {
1970
+ return {
1971
+ src: "/(.*)",
1972
+ has: [
1973
+ {
1974
+ type: "header",
1975
+ key: "user-agent",
1976
+ value: `(?i).*(${jmpAiCrawlerWafUserAgentPattern()}).*`
1977
+ }
1978
+ ],
1979
+ mitigate: { action: "deny" }
1980
+ };
1981
+ }
1982
+ function mergeJmpRobotsTxt(jmpBody, options) {
1983
+ const trimmed = jmpBody.trim();
1984
+ const sitemapLine = `Sitemap: ${options.siteUrl.replace(/\/$/, "")}/sitemap.xml`;
1985
+ const hasSitemap = /(?:^|\n)\s*Sitemap:/i.test(trimmed);
1986
+ const prefixes = options.privatePathPrefixes ?? [];
1987
+ const missingDisallows = prefixes.filter(
1988
+ (prefix) => !trimmed.includes(`Disallow: ${prefix}`)
1989
+ );
1990
+ const parts = [trimmed];
1991
+ if (options.ensureAiCrawlerDisallows && !/User-agent:\s*GPTBot/i.test(trimmed)) {
1992
+ parts.unshift(buildAiCrawlerRobotsTxt(true).trim());
1993
+ }
1994
+ if (missingDisallows.length > 0) {
1995
+ const lines = prefixes.map((prefix) => `Disallow: ${prefix}`);
1996
+ parts.push(`User-agent: *
1997
+ ${lines.join("\n")}`);
1998
+ }
1999
+ if (!hasSitemap) {
2000
+ parts.push(sitemapLine);
2001
+ }
2002
+ return `${parts.join("\n\n")}
2003
+ `;
2004
+ }
2005
+ function escapeRegExp(value) {
2006
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2007
+ }
2008
+
1684
2009
  // src/content/client.ts
1685
2010
  function createJmpContentClient(config) {
1686
2011
  return {
@@ -1746,10 +2071,15 @@ function createJmpContentClientFromServerEnv(overrides) {
1746
2071
  }
1747
2072
  // Annotate the CommonJS export names for ESM import in node:
1748
2073
  0 && (module.exports = {
2074
+ AI_CRAWLER_ROBOTS_USER_AGENTS,
1749
2075
  BOOKING_LINK_HOSTS,
1750
2076
  DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
2077
+ JMP_AI_CRAWLER_WAF_USER_AGENTS,
1751
2078
  JMP_ANALYTICS_SDK_VERSION,
2079
+ JMP_CONTENT_CACHE_TAG,
2080
+ JMP_CONTENT_REVALIDATE_SECONDS,
1752
2081
  JMP_TRACKING_CONSENT_STORAGE_KEY,
2082
+ buildAiCrawlerRobotsTxt,
1753
2083
  buildLandingCaptureInlineScript,
1754
2084
  classifyContactHref,
1755
2085
  createJmpAnalytics,
@@ -1782,7 +2112,10 @@ function createJmpContentClientFromServerEnv(overrides) {
1782
2112
  isJmpBrowserAnalyticsEnvConfigured,
1783
2113
  isJmpServerContentEnvConfigured,
1784
2114
  isJmpTrackingConsentGranted,
2115
+ jmpAiCrawlerVercelWafRoute,
2116
+ jmpAiCrawlerWafUserAgentPattern,
1785
2117
  markContentWrapper,
2118
+ mergeJmpRobotsTxt,
1786
2119
  normalizeJmpContentManifest,
1787
2120
  readJmpPublicEnvFromProcess,
1788
2121
  registerJmpContentWrappers,