@uptrademedia/site-kit 1.0.5 → 1.0.8

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 (169) hide show
  1. package/dist/analytics/index.js +7 -7
  2. package/dist/analytics/index.mjs +3 -3
  3. package/dist/api-QUIPJJCX.js +77 -0
  4. package/dist/api-QUIPJJCX.js.map +1 -0
  5. package/dist/api-V3BA5PMX.mjs +4 -0
  6. package/dist/api-V3BA5PMX.mjs.map +1 -0
  7. package/dist/blog/index.d.mts +2 -2
  8. package/dist/blog/index.d.ts +2 -2
  9. package/dist/blog/index.js +40 -6
  10. package/dist/blog/index.js.map +1 -1
  11. package/dist/blog/index.mjs +40 -6
  12. package/dist/blog/index.mjs.map +1 -1
  13. package/dist/blog/server.d.mts +3 -2
  14. package/dist/blog/server.d.ts +3 -2
  15. package/dist/blog/server.js +13 -6
  16. package/dist/blog/server.js.map +1 -1
  17. package/dist/blog/server.mjs +13 -6
  18. package/dist/blog/server.mjs.map +1 -1
  19. package/dist/{chunk-FKVJOT2F.mjs → chunk-42EXHJTC.mjs} +196 -7
  20. package/dist/chunk-42EXHJTC.mjs.map +1 -0
  21. package/dist/{scanner-AZV5I6US.mjs → chunk-44OMJFCG.mjs} +354 -14
  22. package/dist/chunk-44OMJFCG.mjs.map +1 -0
  23. package/dist/chunk-4TGJYNHV.js +981 -0
  24. package/dist/chunk-4TGJYNHV.js.map +1 -0
  25. package/dist/chunk-4XPGGLVP.mjs +53 -0
  26. package/dist/{chunk-NYKRE2FL.mjs.map → chunk-4XPGGLVP.mjs.map} +1 -1
  27. package/dist/{generators-TO2FKJR6.mjs → chunk-6ONUXZDO.mjs} +26 -9
  28. package/dist/chunk-6ONUXZDO.mjs.map +1 -0
  29. package/dist/chunk-CG53ASWX.mjs +729 -0
  30. package/dist/chunk-CG53ASWX.mjs.map +1 -0
  31. package/dist/{scanner-ETJAMIT7.js → chunk-DERI27QC.js} +448 -102
  32. package/dist/chunk-DERI27QC.js.map +1 -0
  33. package/dist/chunk-DYM5ML2V.mjs +1518 -0
  34. package/dist/chunk-DYM5ML2V.mjs.map +1 -0
  35. package/dist/chunk-FLZZOX44.js +1526 -0
  36. package/dist/chunk-FLZZOX44.js.map +1 -0
  37. package/dist/{chunk-7H6I3ECV.mjs → chunk-FQVGK746.mjs} +63 -3
  38. package/dist/chunk-FQVGK746.mjs.map +1 -0
  39. package/dist/{chunk-GQ6ZOU2N.mjs → chunk-JGQPAXTL.mjs} +4 -4
  40. package/dist/{chunk-GQ6ZOU2N.mjs.map → chunk-JGQPAXTL.mjs.map} +1 -1
  41. package/dist/{chunk-V3F5J6CV.js → chunk-JUEVN4Q4.js} +196 -7
  42. package/dist/chunk-JUEVN4Q4.js.map +1 -0
  43. package/dist/chunk-KKMGTT7F.mjs +968 -0
  44. package/dist/chunk-KKMGTT7F.mjs.map +1 -0
  45. package/dist/{chunk-XQJX252G.mjs → chunk-MB3WR5KJ.mjs} +28 -18
  46. package/dist/chunk-MB3WR5KJ.mjs.map +1 -0
  47. package/dist/{chunk-2IHTEKHU.mjs → chunk-QD5CN2OI.mjs} +16 -7
  48. package/dist/chunk-QD5CN2OI.mjs.map +1 -0
  49. package/dist/{chunk-SBVEYCSV.js → chunk-QQB4FO4Q.js} +7 -7
  50. package/dist/{chunk-SBVEYCSV.js.map → chunk-QQB4FO4Q.js.map} +1 -1
  51. package/dist/{generators-YZWIGHCO.js → chunk-S2GXR5HY.js} +26 -9
  52. package/dist/chunk-S2GXR5HY.js.map +1 -0
  53. package/dist/{chunk-O2OHHBUD.js → chunk-TDK7DLCH.js} +30 -20
  54. package/dist/chunk-TDK7DLCH.js.map +1 -0
  55. package/dist/{chunk-QP5NCO2E.js → chunk-VDI7KYME.js} +67 -2
  56. package/dist/chunk-VDI7KYME.js.map +1 -0
  57. package/dist/chunk-VOR53RUR.js +753 -0
  58. package/dist/chunk-VOR53RUR.js.map +1 -0
  59. package/dist/{chunk-GAJLEDRD.js → chunk-ZKJ7JKFV.js} +16 -7
  60. package/dist/chunk-ZKJ7JKFV.js.map +1 -0
  61. package/dist/chunk-ZSMWDLMK.js +63 -0
  62. package/dist/{chunk-EQCVQC35.js.map → chunk-ZSMWDLMK.js.map} +1 -1
  63. package/dist/cli/index.js +37269 -0
  64. package/dist/cli/index.js.map +1 -0
  65. package/dist/cli/index.mjs +37233 -0
  66. package/dist/cli/index.mjs.map +1 -0
  67. package/dist/commerce/index.js +1 -1
  68. package/dist/commerce/index.mjs +1 -1
  69. package/dist/commerce/server.d.mts +12 -3
  70. package/dist/commerce/server.d.ts +12 -3
  71. package/dist/commerce/server.js +71 -70
  72. package/dist/commerce/server.js.map +1 -1
  73. package/dist/commerce/server.mjs +71 -70
  74. package/dist/commerce/server.mjs.map +1 -1
  75. package/dist/engage/index.d.mts +6 -4
  76. package/dist/engage/index.d.ts +6 -4
  77. package/dist/engage/index.js +8 -4
  78. package/dist/engage/index.mjs +2 -2
  79. package/dist/forms/index.js +1 -1
  80. package/dist/forms/index.mjs +1 -1
  81. package/dist/generators-5EU4PTVF.js +33 -0
  82. package/dist/generators-5EU4PTVF.js.map +1 -0
  83. package/dist/generators-TYPILCWD.mjs +4 -0
  84. package/dist/generators-TYPILCWD.mjs.map +1 -0
  85. package/dist/images/index.js +11 -11
  86. package/dist/images/index.mjs +4 -4
  87. package/dist/index.d.mts +154 -5
  88. package/dist/index.d.ts +154 -5
  89. package/dist/index.js +940 -24
  90. package/dist/index.js.map +1 -1
  91. package/dist/index.mjs +819 -7
  92. package/dist/index.mjs.map +1 -1
  93. package/dist/llms/index.d.mts +657 -0
  94. package/dist/llms/index.d.ts +657 -0
  95. package/dist/llms/index.js +101 -0
  96. package/dist/llms/index.js.map +1 -0
  97. package/dist/llms/index.mjs +4 -0
  98. package/dist/llms/index.mjs.map +1 -0
  99. package/dist/migrator-ARLHUNB3.mjs +4 -0
  100. package/dist/migrator-ARLHUNB3.mjs.map +1 -0
  101. package/dist/migrator-VZLBH3VY.js +37 -0
  102. package/dist/migrator-VZLBH3VY.js.map +1 -0
  103. package/dist/redirects/index.js +1 -1
  104. package/dist/redirects/index.mjs +1 -1
  105. package/dist/reputation/index.js +1 -1
  106. package/dist/reputation/index.mjs +1 -1
  107. package/dist/{routing-BWjUF7lp.d.ts → routing-CF91y6NO.d.ts} +1 -1
  108. package/dist/{routing-CgmRi9tD.d.mts → routing-CIOFpFCB.d.mts} +1 -1
  109. package/dist/scanner-7ZMUM2P5.mjs +4 -0
  110. package/dist/scanner-7ZMUM2P5.mjs.map +1 -0
  111. package/dist/scanner-OY7UF3WA.js +53 -0
  112. package/dist/scanner-OY7UF3WA.js.map +1 -0
  113. package/dist/seo/index.d.mts +267 -7
  114. package/dist/seo/index.d.ts +267 -7
  115. package/dist/seo/index.js +433 -24
  116. package/dist/seo/index.js.map +1 -1
  117. package/dist/seo/index.mjs +401 -11
  118. package/dist/seo/index.mjs.map +1 -1
  119. package/dist/seo/server.d.mts +11 -4
  120. package/dist/seo/server.d.ts +11 -4
  121. package/dist/seo/server.js +17 -17
  122. package/dist/seo/server.mjs +3 -3
  123. package/dist/setup/client.js +1 -1
  124. package/dist/setup/client.mjs +1 -1
  125. package/dist/setup/index.js +3 -3
  126. package/dist/setup/index.mjs +2 -2
  127. package/dist/setup/server.js +3 -3
  128. package/dist/setup/server.mjs +2 -2
  129. package/dist/sitemap/index.js +2 -2
  130. package/dist/sitemap/index.js.map +1 -1
  131. package/dist/sitemap/index.mjs +2 -2
  132. package/dist/sitemap/index.mjs.map +1 -1
  133. package/dist/{types-C0pJGfbH.d.mts → types-D6FHAVWX.d.mts} +99 -3
  134. package/dist/{types-C0pJGfbH.d.ts → types-D6FHAVWX.d.ts} +99 -3
  135. package/dist/{types-BN4OwtCO.d.mts → types-DI0jnhjJ.d.mts} +2 -0
  136. package/dist/{types-BN4OwtCO.d.ts → types-DI0jnhjJ.d.ts} +2 -0
  137. package/dist/{types-BmzutFwy.d.ts → types-j8X4vUhB.d.mts} +19 -2
  138. package/dist/{types-BmzutFwy.d.mts → types-j8X4vUhB.d.ts} +19 -2
  139. package/dist/{web-vitals-BH55V7EJ.js → web-vitals-444RLW3B.js} +11 -11
  140. package/dist/{web-vitals-BH55V7EJ.js.map → web-vitals-444RLW3B.js.map} +1 -1
  141. package/dist/{web-vitals-RJYPWAR3.mjs → web-vitals-KPICZIEF.mjs} +3 -3
  142. package/dist/{web-vitals-RJYPWAR3.mjs.map → web-vitals-KPICZIEF.mjs.map} +1 -1
  143. package/package.json +17 -10
  144. package/dist/api-N35S3EES.js +0 -57
  145. package/dist/api-N35S3EES.js.map +0 -1
  146. package/dist/api-SYBTK7Z7.mjs +0 -4
  147. package/dist/api-SYBTK7Z7.mjs.map +0 -1
  148. package/dist/chunk-2IHTEKHU.mjs.map +0 -1
  149. package/dist/chunk-7H6I3ECV.mjs.map +0 -1
  150. package/dist/chunk-BGJLOJ7T.mjs +0 -605
  151. package/dist/chunk-BGJLOJ7T.mjs.map +0 -1
  152. package/dist/chunk-EQCVQC35.js +0 -35
  153. package/dist/chunk-FKVJOT2F.mjs.map +0 -1
  154. package/dist/chunk-GAJLEDRD.js.map +0 -1
  155. package/dist/chunk-NYKRE2FL.mjs +0 -31
  156. package/dist/chunk-O2OHHBUD.js.map +0 -1
  157. package/dist/chunk-QAYJV4KK.js +0 -608
  158. package/dist/chunk-QAYJV4KK.js.map +0 -1
  159. package/dist/chunk-QP5NCO2E.js.map +0 -1
  160. package/dist/chunk-V3F5J6CV.js.map +0 -1
  161. package/dist/chunk-XQJX252G.mjs.map +0 -1
  162. package/dist/generators-TO2FKJR6.mjs.map +0 -1
  163. package/dist/generators-YZWIGHCO.js.map +0 -1
  164. package/dist/migrator-V6KS75EA.mjs +0 -265
  165. package/dist/migrator-V6KS75EA.mjs.map +0 -1
  166. package/dist/migrator-XKM7YQCY.js +0 -272
  167. package/dist/migrator-XKM7YQCY.js.map +0 -1
  168. package/dist/scanner-AZV5I6US.mjs.map +0 -1
  169. package/dist/scanner-ETJAMIT7.js.map +0 -1
package/dist/seo/index.js CHANGED
@@ -3,15 +3,206 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var chunkHCFPU7TU_js = require('../chunk-HCFPU7TU.js');
6
- var chunkSBVEYCSV_js = require('../chunk-SBVEYCSV.js');
7
- var chunkQP5NCO2E_js = require('../chunk-QP5NCO2E.js');
8
- require('../chunk-EQCVQC35.js');
6
+ var chunkQQB4FO4Q_js = require('../chunk-QQB4FO4Q.js');
7
+ var chunkVDI7KYME_js = require('../chunk-VDI7KYME.js');
8
+ require('../chunk-ZSMWDLMK.js');
9
+ var react = require('react');
10
+ require('server-only');
9
11
  var jsxRuntime = require('react/jsx-runtime');
10
12
 
13
+ function getSecureApiConfig() {
14
+ const apiUrl = process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.uptrademedia.com";
15
+ const apiKey = process.env.UPTRADE_API_KEY || "";
16
+ const projectId = process.env.UPTRADE_PROJECT_ID || "";
17
+ if (!apiKey) {
18
+ throw new Error("@uptrade/seo: UPTRADE_API_KEY environment variable is required for server-side SEO functions");
19
+ }
20
+ return { apiUrl, apiKey, projectId };
21
+ }
22
+ async function secureApiPost(endpoint, body = {}) {
23
+ const { apiUrl, apiKey } = getSecureApiConfig();
24
+ try {
25
+ const response = await fetch(`${apiUrl}${endpoint}`, {
26
+ method: "POST",
27
+ headers: {
28
+ "Content-Type": "application/json",
29
+ "x-api-key": apiKey
30
+ },
31
+ body: JSON.stringify(body),
32
+ next: { revalidate: 60 }
33
+ // Cache for 60 seconds
34
+ });
35
+ if (!response.ok) {
36
+ console.error(`@uptrade/seo: API error ${response.status}: ${response.statusText}`);
37
+ return null;
38
+ }
39
+ return await response.json();
40
+ } catch (error) {
41
+ console.error("@uptrade/seo: Network error:", error);
42
+ return null;
43
+ }
44
+ }
45
+ var getSEOPageData = react.cache(async (projectId, path) => {
46
+ const result = await secureApiPost("/api/public/seo/page", {
47
+ projectId,
48
+ path
49
+ });
50
+ return result?.page || null;
51
+ });
52
+ var getSchemaMarkups2 = react.cache(async (projectId, path, options) => {
53
+ const result = await secureApiPost("/api/public/seo/schemas", {
54
+ projectId,
55
+ path,
56
+ includeTypes: options?.includeTypes,
57
+ excludeTypes: options?.excludeTypes
58
+ });
59
+ return result?.schemas || [];
60
+ });
61
+ var getFAQData2 = react.cache(async (projectId, path) => {
62
+ const result = await secureApiPost("/api/public/seo/faq", {
63
+ projectId,
64
+ path
65
+ });
66
+ return result?.faq || null;
67
+ });
68
+ var getInternalLinks2 = react.cache(async (projectId, sourcePath, options) => {
69
+ const result = await secureApiPost("/api/public/seo/internal-links", {
70
+ projectId,
71
+ sourcePath,
72
+ position: options?.position,
73
+ limit: options?.limit
74
+ });
75
+ return result?.links || [];
76
+ });
77
+ var getContentBlock2 = react.cache(async (projectId, path, section) => {
78
+ const result = await secureApiPost("/api/public/seo/content", {
79
+ projectId,
80
+ path,
81
+ section
82
+ });
83
+ return result?.content || null;
84
+ });
85
+ var getABTest = react.cache(async (projectId, path, field) => {
86
+ const result = await secureApiPost("/api/public/seo/ab-test", {
87
+ projectId,
88
+ path,
89
+ field
90
+ });
91
+ return result?.test || null;
92
+ });
93
+ async function recordABImpression(testId, variant, sessionId) {
94
+ await secureApiPost("/api/public/seo/ab-impression", { testId, variant, sessionId });
95
+ }
96
+ var getRedirectData = react.cache(async (projectId, path) => {
97
+ const result = await secureApiPost("/api/public/seo/redirect", {
98
+ projectId,
99
+ path
100
+ });
101
+ return result?.redirect || null;
102
+ });
103
+ var getManagedScripts2 = react.cache(async (projectId, position, currentPath) => {
104
+ const result = await secureApiPost("/api/public/seo/scripts", {
105
+ projectId,
106
+ position,
107
+ currentPath
108
+ });
109
+ return result?.scripts || [];
110
+ });
111
+ var getRobotsData = react.cache(async (projectId, path) => {
112
+ const result = await secureApiPost("/api/public/seo/page", {
113
+ projectId,
114
+ path
115
+ });
116
+ return result?.page?.managed_robots || null;
117
+ });
118
+ var getSitemapEntries = react.cache(async (projectId, options) => {
119
+ const result = await secureApiPost("/api/public/seo/sitemap", {
120
+ projectId,
121
+ publishedOnly: options?.publishedOnly
122
+ });
123
+ return result?.entries || [];
124
+ });
125
+ async function registerSitemap(entries) {
126
+ const { apiUrl, apiKey, projectId } = getSecureApiConfig();
127
+ try {
128
+ const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {
129
+ method: "POST",
130
+ headers: {
131
+ "Content-Type": "application/json",
132
+ "x-api-key": apiKey
133
+ },
134
+ body: JSON.stringify({ projectId, entries })
135
+ });
136
+ if (!response.ok) {
137
+ console.error(`@uptrade/seo: Sitemap registration failed: ${response.statusText}`);
138
+ return { success: false, created: 0, updated: 0 };
139
+ }
140
+ return await response.json();
141
+ } catch (error) {
142
+ console.error("@uptrade/seo: Sitemap registration error:", error);
143
+ return { success: false, created: 0, updated: 0 };
144
+ }
145
+ }
146
+ function getSignalApiConfig() {
147
+ const apiUrl = process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || "https://signal.uptrademedia.com";
148
+ const apiKey = process.env.UPTRADE_API_KEY || "";
149
+ return { apiUrl, apiKey };
150
+ }
151
+ async function signalApiGet(endpoint) {
152
+ const { apiUrl, apiKey } = getSignalApiConfig();
153
+ if (!apiKey) {
154
+ return null;
155
+ }
156
+ try {
157
+ const response = await fetch(`${apiUrl}${endpoint}`, {
158
+ method: "GET",
159
+ headers: {
160
+ "Content-Type": "application/json",
161
+ "x-api-key": apiKey
162
+ },
163
+ next: { revalidate: 300 }
164
+ // Cache for 5 minutes
165
+ });
166
+ if (!response.ok) {
167
+ return null;
168
+ }
169
+ const result = await response.json();
170
+ return result?.data || result;
171
+ } catch (error) {
172
+ console.error("@uptrade/seo: Signal API error:", error);
173
+ return null;
174
+ }
175
+ }
176
+ var getEntities2 = react.cache(async (projectId, options) => {
177
+ let endpoint = `/skills/seo/entities/${projectId}`;
178
+ if (options?.type) {
179
+ endpoint += `?type=${options.type}`;
180
+ }
181
+ const result = await signalApiGet(endpoint);
182
+ return result || [];
183
+ });
184
+ var getPrimaryEntity = react.cache(async (projectId) => {
185
+ return signalApiGet(`/skills/seo/entities/${projectId}/primary`);
186
+ });
187
+ var getEntityEnhancedSchema2 = react.cache(async (projectId, pagePath) => {
188
+ const result = await signalApiGet(
189
+ `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`
190
+ );
191
+ return result?.schemas || [];
192
+ });
193
+ var getVisibilityScore = react.cache(async (projectId, pagePath) => {
194
+ const result = await signalApiGet(`/skills/seo/visibility/${projectId}`);
195
+ if (!result) return null;
196
+ return result.find((s) => s.page_path === pagePath) || null;
197
+ });
198
+ var getVisibilitySummary = react.cache(async (projectId) => {
199
+ return signalApiGet(`/skills/seo/visibility/${projectId}/summary`);
200
+ });
201
+
11
202
  // src/seo/getManagedMetadata.ts
12
203
  async function getManagedMetadata(options) {
13
204
  const { projectId, path, fallback = {}, overrides = {} } = options;
14
- const pageData = await chunkQP5NCO2E_js.getSEOPageData(projectId, path);
205
+ const pageData = await getSEOPageData(projectId, path);
15
206
  if (!pageData) {
16
207
  return {
17
208
  ...fallback,
@@ -29,8 +220,8 @@ async function getManagedMetadata(options) {
29
220
  } else if (fallback.title) {
30
221
  metadata.title = fallback.title;
31
222
  }
32
- if (pageData.managed_description) {
33
- metadata.description = pageData.managed_description;
223
+ if (pageData.managed_meta_description || pageData.managed_description) {
224
+ metadata.description = pageData.managed_meta_description || pageData.managed_description;
34
225
  } else if (fallback.description) {
35
226
  metadata.description = fallback.description;
36
227
  }
@@ -49,7 +240,7 @@ async function getManagedMetadata(options) {
49
240
  };
50
241
  }
51
242
  const ogTitle = pageData.managed_og_title || pageData.managed_title;
52
- const ogDescription = pageData.managed_og_description || pageData.managed_description;
243
+ const ogDescription = pageData.managed_og_description || pageData.managed_meta_description || pageData.managed_description;
53
244
  const ogImage = pageData.managed_og_image;
54
245
  if (ogTitle || ogDescription || ogImage) {
55
246
  metadata.openGraph = {
@@ -75,7 +266,7 @@ async function getManagedMetadata(options) {
75
266
  }
76
267
  async function getABVariant(options) {
77
268
  const { projectId, path, field, sessionId } = options;
78
- const test = await chunkQP5NCO2E_js.getABTest(projectId, path, field);
269
+ const test = await getABTest(projectId, path, field);
79
270
  if (!test) {
80
271
  return null;
81
272
  }
@@ -88,7 +279,7 @@ async function getABVariant(options) {
88
279
  } else {
89
280
  variant = Math.random() < test.traffic_split ? "a" : "b";
90
281
  }
91
- chunkQP5NCO2E_js.recordABImpression(test.id, variant, sessionId).catch(() => {
282
+ recordABImpression(test.id, variant, sessionId).catch(() => {
92
283
  });
93
284
  return {
94
285
  testId: test.id,
@@ -119,21 +310,47 @@ async function getManagedMetadataWithAB(options) {
119
310
  }
120
311
  return metadata;
121
312
  }
313
+ var DEFAULT_SPEAKABLE_SELECTORS = [
314
+ "h1",
315
+ '[data-speakable="true"]',
316
+ ".page-summary",
317
+ ".key-points",
318
+ '.aeo-block[data-speakable="true"]'
319
+ ];
122
320
  async function ManagedSchema({
123
321
  projectId,
124
322
  path,
125
323
  additionalSchemas = [],
126
324
  includeTypes,
127
- excludeTypes
325
+ excludeTypes,
326
+ speakable,
327
+ pageType = "WebPage",
328
+ pageName,
329
+ pageUrl,
330
+ includeEntityGraph = false
128
331
  }) {
129
- const schemas = await chunkQP5NCO2E_js.getSchemaMarkups(projectId, path, {
332
+ const schemas = await chunkVDI7KYME_js.getSchemaMarkups(projectId, path, {
130
333
  includeTypes,
131
334
  excludeTypes
132
335
  });
336
+ let entitySchemas = [];
337
+ if (includeEntityGraph) {
338
+ entitySchemas = await chunkVDI7KYME_js.getEntityEnhancedSchema(projectId, path);
339
+ }
133
340
  const allSchemas = [
341
+ ...entitySchemas,
134
342
  ...schemas.map((s) => s.schema_json),
135
343
  ...additionalSchemas
136
344
  ];
345
+ if (speakable && pageName && pageUrl) {
346
+ const speakableSchema = createSpeakableWebPageSchema(
347
+ pageType,
348
+ pageName,
349
+ pageUrl,
350
+ typeof speakable === "object" ? speakable : void 0
351
+ );
352
+ allSchemas.push(speakableSchema);
353
+ }
137
354
  if (allSchemas.length === 0) {
138
355
  return null;
139
356
  }
@@ -162,6 +379,25 @@ function createSchema(type, data) {
162
379
  ...data
163
380
  };
164
381
  }
382
+ function createSpeakableWebPageSchema(type, name, url, speakable) {
383
+ const speakableSpec = {
384
+ "@type": "SpeakableSpecification"
385
+ };
386
+ if (speakable?.cssSelector?.length) {
387
+ speakableSpec.cssSelector = speakable.cssSelector;
388
+ } else if (speakable?.xpath?.length) {
389
+ speakableSpec.xpath = speakable.xpath;
390
+ } else {
391
+ speakableSpec.cssSelector = DEFAULT_SPEAKABLE_SELECTORS;
392
+ }
393
+ return {
394
+ "@context": "https://schema.org",
395
+ "@type": type,
396
+ name,
397
+ url,
398
+ speakable: speakableSpec
399
+ };
400
+ }
165
401
  function createBreadcrumbSchema(baseUrl, path, labels) {
166
402
  const segments = path.split("/").filter(Boolean);
167
403
  const items = segments.map((segment, index) => {
@@ -219,7 +455,7 @@ async function ManagedFAQ({
219
455
  includeSchema = true,
220
456
  showTitle = true
221
457
  }) {
222
- const faqData = await chunkQP5NCO2E_js.getFAQData(projectId, path);
458
+ const faqData = await chunkVDI7KYME_js.getFAQData(projectId, path);
223
459
  if (!faqData || !faqData.items?.length) {
224
460
  return null;
225
461
  }
@@ -268,7 +504,7 @@ async function ManagedInternalLinks({
268
504
  className,
269
505
  renderLink
270
506
  }) {
271
- const links = await chunkQP5NCO2E_js.getInternalLinks(projectId, path, { position, limit });
507
+ const links = await chunkVDI7KYME_js.getInternalLinks(projectId, path, { position, limit });
272
508
  if (!links.length) {
273
509
  return null;
274
510
  }
@@ -301,33 +537,80 @@ async function ManagedInternalLinks({
301
537
  function renderMarkdown(content) {
302
538
  return content.replace(/^### (.*$)/gim, "<h3>$1</h3>").replace(/^## (.*$)/gim, "<h2>$1</h2>").replace(/^# (.*$)/gim, "<h1>$1</h1>").replace(/\*\*(.*)\*\*/gim, "<strong>$1</strong>").replace(/\*(.*)\*/gim, "<em>$1</em>").replace(/\[(.*?)\]\((.*?)\)/gim, '<a href="$2">$1</a>').replace(/\n\n/gim, "</p><p>").replace(/^(.+)$/gim, "<p>$1</p>");
303
539
  }
540
+ function injectEntityAnnotations(html, entities) {
541
+ if (!entities.length) return html;
542
+ let annotatedHtml = html;
543
+ const sortedEntities = [...entities].sort((a, b) => b.name.length - a.name.length);
544
+ for (const entity of sortedEntities) {
545
+ if (entity.name.length < 3) continue;
546
+ const regex = new RegExp(
547
+ `(?<![\\w-])(?<!data-sonor-entity=")${escapeRegExp(entity.name)}(?![\\w-])`,
548
+ "gi"
549
+ );
550
+ const schemaType = getSchemaTypeForEntity(entity.entity_type);
551
+ annotatedHtml = annotatedHtml.replace(regex, (match) => {
552
+ return `<span class="aeo-entity aeo-entity-${entity.entity_type}" data-sonor-entity="${entity.id}" data-sonor-entity-type="${entity.entity_type}" data-sonor-entity-name="${entity.name}" itemscope itemtype="https://schema.org/${schemaType}"><span itemprop="name">${match}</span></span>`;
553
+ });
554
+ }
555
+ return annotatedHtml;
556
+ }
557
+ function escapeRegExp(string) {
558
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
559
+ }
560
+ function getSchemaTypeForEntity(entityType) {
561
+ const typeMap = {
562
+ organization: "Organization",
563
+ person: "Person",
564
+ service: "Service",
565
+ product: "Product",
566
+ location: "Place",
567
+ concept: "Thing",
568
+ credential: "EducationalOccupationalCredential"
569
+ };
570
+ return typeMap[entityType] || "Thing";
571
+ }
304
572
  async function ManagedContent({
305
573
  projectId,
306
574
  path,
307
575
  section,
308
576
  fallback,
309
577
  className,
310
- components = {}
578
+ components = {},
579
+ injectEntityAnnotations: shouldInjectEntities = false
311
580
  }) {
312
- const block = await chunkQP5NCO2E_js.getContentBlock(projectId, path, section);
581
+ const block = await chunkVDI7KYME_js.getContentBlock(projectId, path, section);
313
582
  if (!block) {
314
583
  if (fallback) {
315
584
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback });
316
585
  }
317
586
  return null;
318
587
  }
588
+ let entities = [];
589
+ if (shouldInjectEntities) {
590
+ try {
591
+ entities = await chunkVDI7KYME_js.getEntities(projectId);
592
+ } catch (err) {
593
+ console.warn("@uptrade/seo: Failed to fetch entities for annotation:", err);
594
+ }
595
+ }
319
596
  const containerClass = className || `uptrade-content uptrade-content--${section}`;
597
+ const processHtml = (html) => {
598
+ if (shouldInjectEntities && entities.length > 0) {
599
+ return injectEntityAnnotations(html, entities);
600
+ }
601
+ return html;
602
+ };
320
603
  switch (block.content_type) {
321
604
  case "html":
322
605
  return /* @__PURE__ */ jsxRuntime.jsx(
323
606
  "div",
324
607
  {
325
608
  className: containerClass,
326
- dangerouslySetInnerHTML: { __html: block.content }
609
+ dangerouslySetInnerHTML: { __html: processHtml(block.content) }
327
610
  }
328
611
  );
329
612
  case "markdown":
330
- const htmlContent = renderMarkdown(block.content);
613
+ const htmlContent = processHtml(renderMarkdown(block.content));
331
614
  return /* @__PURE__ */ jsxRuntime.jsx(
332
615
  "div",
333
616
  {
@@ -366,14 +649,14 @@ async function ManagedContent({
366
649
  }
367
650
  }
368
651
  async function getManagedContentData(projectId, path, section) {
369
- return chunkQP5NCO2E_js.getContentBlock(projectId, path, section);
652
+ return chunkVDI7KYME_js.getContentBlock(projectId, path, section);
370
653
  }
371
654
  async function ManagedScripts({
372
655
  projectId,
373
656
  position,
374
657
  path
375
658
  }) {
376
- const scripts = await chunkQP5NCO2E_js.getManagedScripts(projectId, position, path);
659
+ const scripts = await chunkVDI7KYME_js.getManagedScripts(projectId, position, path);
377
660
  if (!scripts.length) {
378
661
  return null;
379
662
  }
@@ -402,13 +685,120 @@ async function ManagedNoScripts({
402
685
  projectId,
403
686
  path
404
687
  }) {
405
- const scripts = await chunkQP5NCO2E_js.getManagedScripts(projectId, "body-start", path);
688
+ const scripts = await chunkVDI7KYME_js.getManagedScripts(projectId, "body-start", path);
406
689
  const noscriptContent = scripts.filter((s) => s.attributes?.noscript).map((s) => s.attributes?.noscript).join("");
407
690
  if (!noscriptContent) {
408
691
  return null;
409
692
  }
410
693
  return /* @__PURE__ */ jsxRuntime.jsx("noscript", { dangerouslySetInnerHTML: { __html: noscriptContent } });
411
694
  }
695
+ function getApiConfig() {
696
+ const apiUrl = process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.uptrademedia.com";
697
+ return { apiUrl };
698
+ }
699
+ var getLocationSection = react.cache(async (projectId, path, section) => {
700
+ const { apiUrl } = getApiConfig();
701
+ try {
702
+ const response = await fetch(`${apiUrl}/api/public/seo/location-content`, {
703
+ method: "POST",
704
+ headers: { "Content-Type": "application/json" },
705
+ body: JSON.stringify({
706
+ project_id: projectId,
707
+ path,
708
+ section
709
+ }),
710
+ next: { revalidate: 3600 }
711
+ // Cache for 1 hour
712
+ });
713
+ if (!response.ok) {
714
+ console.error(`LocationPageContent: Failed to fetch section "${section}" for path "${path}"`);
715
+ return null;
716
+ }
717
+ const data = await response.json();
718
+ return data;
719
+ } catch (error) {
720
+ console.error("LocationPageContent: API error:", error);
721
+ return null;
722
+ }
723
+ });
724
+ function HeroRenderer({ data, className }) {
725
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: className || "location-hero", children: [
726
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { children: data.title }),
727
+ data.subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "subtitle", children: data.subtitle }),
728
+ data.stats && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "stats-grid", children: data.stats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "stat", children: [
729
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "stat-value", children: stat.value }),
730
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "stat-label", children: stat.label })
731
+ ] }, i)) }),
732
+ data.cta_text && data.cta_href && /* @__PURE__ */ jsxRuntime.jsx("a", { href: data.cta_href, className: "cta-button", children: data.cta_text })
733
+ ] });
734
+ }
735
+ function TextRenderer({ data, className }) {
736
+ if (data.html) {
737
+ return /* @__PURE__ */ jsxRuntime.jsx(
738
+ "section",
739
+ {
740
+ className: className || "location-text",
741
+ dangerouslySetInnerHTML: { __html: data.html }
742
+ }
743
+ );
744
+ }
745
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: className || "location-text", children: [
746
+ data.heading && /* @__PURE__ */ jsxRuntime.jsx("h2", { children: data.heading }),
747
+ data.paragraphs.map((p, i) => /* @__PURE__ */ jsxRuntime.jsx("p", { children: p }, i))
748
+ ] });
749
+ }
750
+ function ServicesGridRenderer({ data, className }) {
751
+ return /* @__PURE__ */ jsxRuntime.jsx("section", { className: className || "location-services-grid", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "services-list", children: data.services.map((service, i) => /* @__PURE__ */ jsxRuntime.jsxs("a", { href: service.href, className: "service-card", children: [
752
+ service.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "service-icon", children: service.icon }),
753
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: service.title }),
754
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: service.description })
755
+ ] }, i)) }) });
756
+ }
757
+ function DefaultRenderer({ data, className }) {
758
+ if (process.env.NODE_ENV === "development") {
759
+ return /* @__PURE__ */ jsxRuntime.jsx("section", { className, children: /* @__PURE__ */ jsxRuntime.jsx("pre", { style: { fontSize: "12px", background: "#f0f0f0", padding: "1rem" }, children: JSON.stringify(data, null, 2) }) });
760
+ }
761
+ if (typeof data.content === "string") {
762
+ return /* @__PURE__ */ jsxRuntime.jsx(
763
+ "section",
764
+ {
765
+ className,
766
+ dangerouslySetInnerHTML: { __html: data.content }
767
+ }
768
+ );
769
+ }
770
+ return null;
771
+ }
772
+ async function LocationPageContent({
773
+ projectId,
774
+ path,
775
+ section,
776
+ fallback = null,
777
+ className,
778
+ render
779
+ }) {
780
+ const data = await getLocationSection(projectId, path, section);
781
+ if (!data) {
782
+ return fallback;
783
+ }
784
+ if (render) {
785
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render(data) });
786
+ }
787
+ switch (data.type) {
788
+ case "hero":
789
+ return /* @__PURE__ */ jsxRuntime.jsx(HeroRenderer, { data: data.content, className });
790
+ case "text":
791
+ case "intro":
792
+ case "about":
793
+ case "about_location":
794
+ return /* @__PURE__ */ jsxRuntime.jsx(TextRenderer, { data: data.content, className });
795
+ case "services_grid":
796
+ case "services":
797
+ return /* @__PURE__ */ jsxRuntime.jsx(ServicesGridRenderer, { data: data.content, className });
798
+ default:
799
+ return /* @__PURE__ */ jsxRuntime.jsx(DefaultRenderer, { data, className });
800
+ }
801
+ }
412
802
 
413
803
  Object.defineProperty(exports, "SitemapSync", {
414
804
  enumerable: true,
@@ -416,20 +806,21 @@ Object.defineProperty(exports, "SitemapSync", {
416
806
  });
417
807
  Object.defineProperty(exports, "generateSitemap", {
418
808
  enumerable: true,
419
- get: function () { return chunkSBVEYCSV_js.generateSitemap; }
809
+ get: function () { return chunkQQB4FO4Q_js.generateSitemap; }
420
810
  });
421
811
  Object.defineProperty(exports, "getRedirect", {
422
812
  enumerable: true,
423
- get: function () { return chunkSBVEYCSV_js.getRedirect; }
813
+ get: function () { return chunkQQB4FO4Q_js.getRedirect; }
424
814
  });
425
815
  Object.defineProperty(exports, "getRobotsDirective", {
426
816
  enumerable: true,
427
- get: function () { return chunkSBVEYCSV_js.getRobotsDirective; }
817
+ get: function () { return chunkQQB4FO4Q_js.getRobotsDirective; }
428
818
  });
429
819
  Object.defineProperty(exports, "isIndexable", {
430
820
  enumerable: true,
431
- get: function () { return chunkSBVEYCSV_js.isIndexable; }
821
+ get: function () { return chunkQQB4FO4Q_js.isIndexable; }
432
822
  });
823
+ exports.LocationPageContent = LocationPageContent;
433
824
  exports.ManagedContent = ManagedContent;
434
825
  exports.ManagedFAQ = ManagedFAQ;
435
826
  exports.ManagedInternalLinks = ManagedInternalLinks;
@@ -439,9 +830,27 @@ exports.ManagedScripts = ManagedScripts;
439
830
  exports.createBreadcrumbSchema = createBreadcrumbSchema;
440
831
  exports.createSchema = createSchema;
441
832
  exports.default = ManagedSchema;
833
+ exports.getABTest = getABTest;
442
834
  exports.getABVariant = getABVariant;
835
+ exports.getContentBlock = getContentBlock2;
836
+ exports.getEntities = getEntities2;
837
+ exports.getEntityEnhancedSchema = getEntityEnhancedSchema2;
838
+ exports.getFAQData = getFAQData2;
839
+ exports.getInternalLinks = getInternalLinks2;
840
+ exports.getLocationSection = getLocationSection;
443
841
  exports.getManagedContentData = getManagedContentData;
444
842
  exports.getManagedMetadata = getManagedMetadata;
445
843
  exports.getManagedMetadataWithAB = getManagedMetadataWithAB;
844
+ exports.getManagedScripts = getManagedScripts2;
845
+ exports.getPrimaryEntity = getPrimaryEntity;
846
+ exports.getRedirectData = getRedirectData;
847
+ exports.getRobotsData = getRobotsData;
848
+ exports.getSEOPageData = getSEOPageData;
849
+ exports.getSchemaMarkups = getSchemaMarkups2;
850
+ exports.getSitemapEntries = getSitemapEntries;
851
+ exports.getVisibilityScore = getVisibilityScore;
852
+ exports.getVisibilitySummary = getVisibilitySummary;
853
+ exports.recordABImpression = recordABImpression;
854
+ exports.registerSitemap = registerSitemap;
446
855
  //# sourceMappingURL=index.js.map
447
856
  //# sourceMappingURL=index.js.map