@uptrademedia/site-kit 1.0.5 → 1.0.7

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 +432 -24
  116. package/dist/seo/index.js.map +1 -1
  117. package/dist/seo/index.mjs +400 -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 +9 -2
  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,17 @@
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
 
11
13
  // src/seo/getManagedMetadata.ts
12
14
  async function getManagedMetadata(options) {
13
15
  const { projectId, path, fallback = {}, overrides = {} } = options;
14
- const pageData = await chunkQP5NCO2E_js.getSEOPageData(projectId, path);
16
+ const pageData = await chunkVDI7KYME_js.getSEOPageData(projectId, path);
15
17
  if (!pageData) {
16
18
  return {
17
19
  ...fallback,
@@ -29,8 +31,8 @@ async function getManagedMetadata(options) {
29
31
  } else if (fallback.title) {
30
32
  metadata.title = fallback.title;
31
33
  }
32
- if (pageData.managed_description) {
33
- metadata.description = pageData.managed_description;
34
+ if (pageData.managed_meta_description || pageData.managed_description) {
35
+ metadata.description = pageData.managed_meta_description || pageData.managed_description;
34
36
  } else if (fallback.description) {
35
37
  metadata.description = fallback.description;
36
38
  }
@@ -49,7 +51,7 @@ async function getManagedMetadata(options) {
49
51
  };
50
52
  }
51
53
  const ogTitle = pageData.managed_og_title || pageData.managed_title;
52
- const ogDescription = pageData.managed_og_description || pageData.managed_description;
54
+ const ogDescription = pageData.managed_og_description || pageData.managed_meta_description || pageData.managed_description;
53
55
  const ogImage = pageData.managed_og_image;
54
56
  if (ogTitle || ogDescription || ogImage) {
55
57
  metadata.openGraph = {
@@ -75,7 +77,7 @@ async function getManagedMetadata(options) {
75
77
  }
76
78
  async function getABVariant(options) {
77
79
  const { projectId, path, field, sessionId } = options;
78
- const test = await chunkQP5NCO2E_js.getABTest(projectId, path, field);
80
+ const test = await chunkVDI7KYME_js.getABTest(projectId, path, field);
79
81
  if (!test) {
80
82
  return null;
81
83
  }
@@ -88,7 +90,7 @@ async function getABVariant(options) {
88
90
  } else {
89
91
  variant = Math.random() < test.traffic_split ? "a" : "b";
90
92
  }
91
- chunkQP5NCO2E_js.recordABImpression(test.id, variant, sessionId).catch(() => {
93
+ chunkVDI7KYME_js.recordABImpression(test.id, variant, sessionId).catch(() => {
92
94
  });
93
95
  return {
94
96
  testId: test.id,
@@ -119,21 +121,235 @@ async function getManagedMetadataWithAB(options) {
119
121
  }
120
122
  return metadata;
121
123
  }
124
+ function getSecureApiConfig() {
125
+ const apiUrl = process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.uptrademedia.com";
126
+ const apiKey = process.env.UPTRADE_API_KEY || "";
127
+ const projectId = process.env.UPTRADE_PROJECT_ID || "";
128
+ if (!apiKey) {
129
+ throw new Error("@uptrade/seo: UPTRADE_API_KEY environment variable is required for server-side SEO functions");
130
+ }
131
+ return { apiUrl, apiKey, projectId };
132
+ }
133
+ async function secureApiPost(endpoint, body = {}) {
134
+ const { apiUrl, apiKey } = getSecureApiConfig();
135
+ try {
136
+ const response = await fetch(`${apiUrl}${endpoint}`, {
137
+ method: "POST",
138
+ headers: {
139
+ "Content-Type": "application/json",
140
+ "x-api-key": apiKey
141
+ },
142
+ body: JSON.stringify(body),
143
+ next: { revalidate: 60 }
144
+ // Cache for 60 seconds
145
+ });
146
+ if (!response.ok) {
147
+ console.error(`@uptrade/seo: API error ${response.status}: ${response.statusText}`);
148
+ return null;
149
+ }
150
+ return await response.json();
151
+ } catch (error) {
152
+ console.error("@uptrade/seo: Network error:", error);
153
+ return null;
154
+ }
155
+ }
156
+ var getSEOPageData2 = react.cache(async (projectId, path) => {
157
+ const result = await secureApiPost("/api/public/seo/page", {
158
+ projectId,
159
+ path
160
+ });
161
+ return result?.page || null;
162
+ });
163
+ var getSchemaMarkups2 = react.cache(async (projectId, path, options) => {
164
+ const result = await secureApiPost("/api/public/seo/schemas", {
165
+ projectId,
166
+ path,
167
+ includeTypes: options?.includeTypes,
168
+ excludeTypes: options?.excludeTypes
169
+ });
170
+ return result?.schemas || [];
171
+ });
172
+ var getFAQData2 = react.cache(async (projectId, path) => {
173
+ const result = await secureApiPost("/api/public/seo/faq", {
174
+ projectId,
175
+ path
176
+ });
177
+ return result?.faq || null;
178
+ });
179
+ var getInternalLinks2 = react.cache(async (projectId, sourcePath, options) => {
180
+ const result = await secureApiPost("/api/public/seo/internal-links", {
181
+ projectId,
182
+ sourcePath,
183
+ position: options?.position,
184
+ limit: options?.limit
185
+ });
186
+ return result?.links || [];
187
+ });
188
+ var getContentBlock2 = react.cache(async (projectId, path, section) => {
189
+ const result = await secureApiPost("/api/public/seo/content", {
190
+ projectId,
191
+ path,
192
+ section
193
+ });
194
+ return result?.content || null;
195
+ });
196
+ var getABTest2 = react.cache(async (projectId, path, field) => {
197
+ const result = await secureApiPost("/api/public/seo/ab-test", {
198
+ projectId,
199
+ path,
200
+ field
201
+ });
202
+ return result?.test || null;
203
+ });
204
+ async function recordABImpression2(testId, variant, sessionId) {
205
+ await secureApiPost("/api/public/seo/ab-impression", { testId, variant, sessionId });
206
+ }
207
+ var getRedirectData = react.cache(async (projectId, path) => {
208
+ const result = await secureApiPost("/api/public/seo/redirect", {
209
+ projectId,
210
+ path
211
+ });
212
+ return result?.redirect || null;
213
+ });
214
+ var getManagedScripts2 = react.cache(async (projectId, position, currentPath) => {
215
+ const result = await secureApiPost("/api/public/seo/scripts", {
216
+ projectId,
217
+ position,
218
+ currentPath
219
+ });
220
+ return result?.scripts || [];
221
+ });
222
+ var getRobotsData = react.cache(async (projectId, path) => {
223
+ const result = await secureApiPost("/api/public/seo/page", {
224
+ projectId,
225
+ path
226
+ });
227
+ return result?.page?.managed_robots || null;
228
+ });
229
+ var getSitemapEntries = react.cache(async (projectId, options) => {
230
+ const result = await secureApiPost("/api/public/seo/sitemap", {
231
+ projectId,
232
+ publishedOnly: options?.publishedOnly
233
+ });
234
+ return result?.entries || [];
235
+ });
236
+ async function registerSitemap(entries) {
237
+ const { apiUrl, apiKey, projectId } = getSecureApiConfig();
238
+ try {
239
+ const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {
240
+ method: "POST",
241
+ headers: {
242
+ "Content-Type": "application/json",
243
+ "x-api-key": apiKey
244
+ },
245
+ body: JSON.stringify({ projectId, entries })
246
+ });
247
+ if (!response.ok) {
248
+ console.error(`@uptrade/seo: Sitemap registration failed: ${response.statusText}`);
249
+ return { success: false, created: 0, updated: 0 };
250
+ }
251
+ return await response.json();
252
+ } catch (error) {
253
+ console.error("@uptrade/seo: Sitemap registration error:", error);
254
+ return { success: false, created: 0, updated: 0 };
255
+ }
256
+ }
257
+ function getSignalApiConfig() {
258
+ const apiUrl = process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || "https://signal.uptrademedia.com";
259
+ const apiKey = process.env.UPTRADE_API_KEY || "";
260
+ return { apiUrl, apiKey };
261
+ }
262
+ async function signalApiGet(endpoint) {
263
+ const { apiUrl, apiKey } = getSignalApiConfig();
264
+ if (!apiKey) {
265
+ return null;
266
+ }
267
+ try {
268
+ const response = await fetch(`${apiUrl}${endpoint}`, {
269
+ method: "GET",
270
+ headers: {
271
+ "Content-Type": "application/json",
272
+ "x-api-key": apiKey
273
+ },
274
+ next: { revalidate: 300 }
275
+ // Cache for 5 minutes
276
+ });
277
+ if (!response.ok) {
278
+ return null;
279
+ }
280
+ const result = await response.json();
281
+ return result?.data || result;
282
+ } catch (error) {
283
+ console.error("@uptrade/seo: Signal API error:", error);
284
+ return null;
285
+ }
286
+ }
287
+ var getEntities2 = react.cache(async (projectId, options) => {
288
+ let endpoint = `/skills/seo/entities/${projectId}`;
289
+ if (options?.type) {
290
+ endpoint += `?type=${options.type}`;
291
+ }
292
+ const result = await signalApiGet(endpoint);
293
+ return result || [];
294
+ });
295
+ var getPrimaryEntity = react.cache(async (projectId) => {
296
+ return signalApiGet(`/skills/seo/entities/${projectId}/primary`);
297
+ });
298
+ var getEntityEnhancedSchema2 = react.cache(async (projectId, pagePath) => {
299
+ const result = await signalApiGet(
300
+ `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`
301
+ );
302
+ return result?.schemas || [];
303
+ });
304
+ var getVisibilityScore = react.cache(async (projectId, pagePath) => {
305
+ const result = await signalApiGet(`/skills/seo/visibility/${projectId}`);
306
+ if (!result) return null;
307
+ return result.find((s) => s.page_path === pagePath) || null;
308
+ });
309
+ var getVisibilitySummary = react.cache(async (projectId) => {
310
+ return signalApiGet(`/skills/seo/visibility/${projectId}/summary`);
311
+ });
312
+ var DEFAULT_SPEAKABLE_SELECTORS = [
313
+ "h1",
314
+ '[data-speakable="true"]',
315
+ ".page-summary",
316
+ ".key-points",
317
+ '.aeo-block[data-speakable="true"]'
318
+ ];
122
319
  async function ManagedSchema({
123
320
  projectId,
124
321
  path,
125
322
  additionalSchemas = [],
126
323
  includeTypes,
127
- excludeTypes
324
+ excludeTypes,
325
+ speakable,
326
+ pageType = "WebPage",
327
+ pageName,
328
+ pageUrl,
329
+ includeEntityGraph = false
128
330
  }) {
129
- const schemas = await chunkQP5NCO2E_js.getSchemaMarkups(projectId, path, {
331
+ const schemas = await chunkVDI7KYME_js.getSchemaMarkups(projectId, path, {
130
332
  includeTypes,
131
333
  excludeTypes
132
334
  });
335
+ let entitySchemas = [];
336
+ if (includeEntityGraph) {
337
+ entitySchemas = await chunkVDI7KYME_js.getEntityEnhancedSchema(projectId, path);
338
+ }
133
339
  const allSchemas = [
340
+ ...entitySchemas,
134
341
  ...schemas.map((s) => s.schema_json),
135
342
  ...additionalSchemas
136
343
  ];
344
+ if (speakable && pageName && pageUrl) {
345
+ const speakableSchema = createSpeakableWebPageSchema(
346
+ pageType,
347
+ pageName,
348
+ pageUrl,
349
+ typeof speakable === "object" ? speakable : void 0
350
+ );
351
+ allSchemas.push(speakableSchema);
352
+ }
137
353
  if (allSchemas.length === 0) {
138
354
  return null;
139
355
  }
@@ -162,6 +378,25 @@ function createSchema(type, data) {
162
378
  ...data
163
379
  };
164
380
  }
381
+ function createSpeakableWebPageSchema(type, name, url, speakable) {
382
+ const speakableSpec = {
383
+ "@type": "SpeakableSpecification"
384
+ };
385
+ if (speakable?.cssSelector?.length) {
386
+ speakableSpec.cssSelector = speakable.cssSelector;
387
+ } else if (speakable?.xpath?.length) {
388
+ speakableSpec.xpath = speakable.xpath;
389
+ } else {
390
+ speakableSpec.cssSelector = DEFAULT_SPEAKABLE_SELECTORS;
391
+ }
392
+ return {
393
+ "@context": "https://schema.org",
394
+ "@type": type,
395
+ name,
396
+ url,
397
+ speakable: speakableSpec
398
+ };
399
+ }
165
400
  function createBreadcrumbSchema(baseUrl, path, labels) {
166
401
  const segments = path.split("/").filter(Boolean);
167
402
  const items = segments.map((segment, index) => {
@@ -219,7 +454,7 @@ async function ManagedFAQ({
219
454
  includeSchema = true,
220
455
  showTitle = true
221
456
  }) {
222
- const faqData = await chunkQP5NCO2E_js.getFAQData(projectId, path);
457
+ const faqData = await chunkVDI7KYME_js.getFAQData(projectId, path);
223
458
  if (!faqData || !faqData.items?.length) {
224
459
  return null;
225
460
  }
@@ -268,7 +503,7 @@ async function ManagedInternalLinks({
268
503
  className,
269
504
  renderLink
270
505
  }) {
271
- const links = await chunkQP5NCO2E_js.getInternalLinks(projectId, path, { position, limit });
506
+ const links = await chunkVDI7KYME_js.getInternalLinks(projectId, path, { position, limit });
272
507
  if (!links.length) {
273
508
  return null;
274
509
  }
@@ -301,33 +536,80 @@ async function ManagedInternalLinks({
301
536
  function renderMarkdown(content) {
302
537
  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
538
  }
539
+ function injectEntityAnnotations(html, entities) {
540
+ if (!entities.length) return html;
541
+ let annotatedHtml = html;
542
+ const sortedEntities = [...entities].sort((a, b) => b.name.length - a.name.length);
543
+ for (const entity of sortedEntities) {
544
+ if (entity.name.length < 3) continue;
545
+ const regex = new RegExp(
546
+ `(?<![\\w-])(?<!data-sonor-entity=")${escapeRegExp(entity.name)}(?![\\w-])`,
547
+ "gi"
548
+ );
549
+ const schemaType = getSchemaTypeForEntity(entity.entity_type);
550
+ annotatedHtml = annotatedHtml.replace(regex, (match) => {
551
+ 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>`;
552
+ });
553
+ }
554
+ return annotatedHtml;
555
+ }
556
+ function escapeRegExp(string) {
557
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
558
+ }
559
+ function getSchemaTypeForEntity(entityType) {
560
+ const typeMap = {
561
+ organization: "Organization",
562
+ person: "Person",
563
+ service: "Service",
564
+ product: "Product",
565
+ location: "Place",
566
+ concept: "Thing",
567
+ credential: "EducationalOccupationalCredential"
568
+ };
569
+ return typeMap[entityType] || "Thing";
570
+ }
304
571
  async function ManagedContent({
305
572
  projectId,
306
573
  path,
307
574
  section,
308
575
  fallback,
309
576
  className,
310
- components = {}
577
+ components = {},
578
+ injectEntityAnnotations: shouldInjectEntities = false
311
579
  }) {
312
- const block = await chunkQP5NCO2E_js.getContentBlock(projectId, path, section);
580
+ const block = await chunkVDI7KYME_js.getContentBlock(projectId, path, section);
313
581
  if (!block) {
314
582
  if (fallback) {
315
583
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback });
316
584
  }
317
585
  return null;
318
586
  }
587
+ let entities = [];
588
+ if (shouldInjectEntities) {
589
+ try {
590
+ entities = await chunkVDI7KYME_js.getEntities(projectId);
591
+ } catch (err) {
592
+ console.warn("@uptrade/seo: Failed to fetch entities for annotation:", err);
593
+ }
594
+ }
319
595
  const containerClass = className || `uptrade-content uptrade-content--${section}`;
596
+ const processHtml = (html) => {
597
+ if (shouldInjectEntities && entities.length > 0) {
598
+ return injectEntityAnnotations(html, entities);
599
+ }
600
+ return html;
601
+ };
320
602
  switch (block.content_type) {
321
603
  case "html":
322
604
  return /* @__PURE__ */ jsxRuntime.jsx(
323
605
  "div",
324
606
  {
325
607
  className: containerClass,
326
- dangerouslySetInnerHTML: { __html: block.content }
608
+ dangerouslySetInnerHTML: { __html: processHtml(block.content) }
327
609
  }
328
610
  );
329
611
  case "markdown":
330
- const htmlContent = renderMarkdown(block.content);
612
+ const htmlContent = processHtml(renderMarkdown(block.content));
331
613
  return /* @__PURE__ */ jsxRuntime.jsx(
332
614
  "div",
333
615
  {
@@ -366,14 +648,14 @@ async function ManagedContent({
366
648
  }
367
649
  }
368
650
  async function getManagedContentData(projectId, path, section) {
369
- return chunkQP5NCO2E_js.getContentBlock(projectId, path, section);
651
+ return chunkVDI7KYME_js.getContentBlock(projectId, path, section);
370
652
  }
371
653
  async function ManagedScripts({
372
654
  projectId,
373
655
  position,
374
656
  path
375
657
  }) {
376
- const scripts = await chunkQP5NCO2E_js.getManagedScripts(projectId, position, path);
658
+ const scripts = await chunkVDI7KYME_js.getManagedScripts(projectId, position, path);
377
659
  if (!scripts.length) {
378
660
  return null;
379
661
  }
@@ -402,13 +684,120 @@ async function ManagedNoScripts({
402
684
  projectId,
403
685
  path
404
686
  }) {
405
- const scripts = await chunkQP5NCO2E_js.getManagedScripts(projectId, "body-start", path);
687
+ const scripts = await chunkVDI7KYME_js.getManagedScripts(projectId, "body-start", path);
406
688
  const noscriptContent = scripts.filter((s) => s.attributes?.noscript).map((s) => s.attributes?.noscript).join("");
407
689
  if (!noscriptContent) {
408
690
  return null;
409
691
  }
410
692
  return /* @__PURE__ */ jsxRuntime.jsx("noscript", { dangerouslySetInnerHTML: { __html: noscriptContent } });
411
693
  }
694
+ function getApiConfig() {
695
+ const apiUrl = process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.uptrademedia.com";
696
+ return { apiUrl };
697
+ }
698
+ var getLocationSection = react.cache(async (projectId, path, section) => {
699
+ const { apiUrl } = getApiConfig();
700
+ try {
701
+ const response = await fetch(`${apiUrl}/api/public/seo/location-content`, {
702
+ method: "POST",
703
+ headers: { "Content-Type": "application/json" },
704
+ body: JSON.stringify({
705
+ project_id: projectId,
706
+ path,
707
+ section
708
+ }),
709
+ next: { revalidate: 3600 }
710
+ // Cache for 1 hour
711
+ });
712
+ if (!response.ok) {
713
+ console.error(`LocationPageContent: Failed to fetch section "${section}" for path "${path}"`);
714
+ return null;
715
+ }
716
+ const data = await response.json();
717
+ return data;
718
+ } catch (error) {
719
+ console.error("LocationPageContent: API error:", error);
720
+ return null;
721
+ }
722
+ });
723
+ function HeroRenderer({ data, className }) {
724
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: className || "location-hero", children: [
725
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { children: data.title }),
726
+ data.subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "subtitle", children: data.subtitle }),
727
+ data.stats && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "stats-grid", children: data.stats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "stat", children: [
728
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "stat-value", children: stat.value }),
729
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "stat-label", children: stat.label })
730
+ ] }, i)) }),
731
+ data.cta_text && data.cta_href && /* @__PURE__ */ jsxRuntime.jsx("a", { href: data.cta_href, className: "cta-button", children: data.cta_text })
732
+ ] });
733
+ }
734
+ function TextRenderer({ data, className }) {
735
+ if (data.html) {
736
+ return /* @__PURE__ */ jsxRuntime.jsx(
737
+ "section",
738
+ {
739
+ className: className || "location-text",
740
+ dangerouslySetInnerHTML: { __html: data.html }
741
+ }
742
+ );
743
+ }
744
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: className || "location-text", children: [
745
+ data.heading && /* @__PURE__ */ jsxRuntime.jsx("h2", { children: data.heading }),
746
+ data.paragraphs.map((p, i) => /* @__PURE__ */ jsxRuntime.jsx("p", { children: p }, i))
747
+ ] });
748
+ }
749
+ function ServicesGridRenderer({ data, className }) {
750
+ 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: [
751
+ service.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "service-icon", children: service.icon }),
752
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: service.title }),
753
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: service.description })
754
+ ] }, i)) }) });
755
+ }
756
+ function DefaultRenderer({ data, className }) {
757
+ if (process.env.NODE_ENV === "development") {
758
+ return /* @__PURE__ */ jsxRuntime.jsx("section", { className, children: /* @__PURE__ */ jsxRuntime.jsx("pre", { style: { fontSize: "12px", background: "#f0f0f0", padding: "1rem" }, children: JSON.stringify(data, null, 2) }) });
759
+ }
760
+ if (typeof data.content === "string") {
761
+ return /* @__PURE__ */ jsxRuntime.jsx(
762
+ "section",
763
+ {
764
+ className,
765
+ dangerouslySetInnerHTML: { __html: data.content }
766
+ }
767
+ );
768
+ }
769
+ return null;
770
+ }
771
+ async function LocationPageContent({
772
+ projectId,
773
+ path,
774
+ section,
775
+ fallback = null,
776
+ className,
777
+ render
778
+ }) {
779
+ const data = await getLocationSection(projectId, path, section);
780
+ if (!data) {
781
+ return fallback;
782
+ }
783
+ if (render) {
784
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render(data) });
785
+ }
786
+ switch (data.type) {
787
+ case "hero":
788
+ return /* @__PURE__ */ jsxRuntime.jsx(HeroRenderer, { data: data.content, className });
789
+ case "text":
790
+ case "intro":
791
+ case "about":
792
+ case "about_location":
793
+ return /* @__PURE__ */ jsxRuntime.jsx(TextRenderer, { data: data.content, className });
794
+ case "services_grid":
795
+ case "services":
796
+ return /* @__PURE__ */ jsxRuntime.jsx(ServicesGridRenderer, { data: data.content, className });
797
+ default:
798
+ return /* @__PURE__ */ jsxRuntime.jsx(DefaultRenderer, { data, className });
799
+ }
800
+ }
412
801
 
413
802
  Object.defineProperty(exports, "SitemapSync", {
414
803
  enumerable: true,
@@ -416,20 +805,21 @@ Object.defineProperty(exports, "SitemapSync", {
416
805
  });
417
806
  Object.defineProperty(exports, "generateSitemap", {
418
807
  enumerable: true,
419
- get: function () { return chunkSBVEYCSV_js.generateSitemap; }
808
+ get: function () { return chunkQQB4FO4Q_js.generateSitemap; }
420
809
  });
421
810
  Object.defineProperty(exports, "getRedirect", {
422
811
  enumerable: true,
423
- get: function () { return chunkSBVEYCSV_js.getRedirect; }
812
+ get: function () { return chunkQQB4FO4Q_js.getRedirect; }
424
813
  });
425
814
  Object.defineProperty(exports, "getRobotsDirective", {
426
815
  enumerable: true,
427
- get: function () { return chunkSBVEYCSV_js.getRobotsDirective; }
816
+ get: function () { return chunkQQB4FO4Q_js.getRobotsDirective; }
428
817
  });
429
818
  Object.defineProperty(exports, "isIndexable", {
430
819
  enumerable: true,
431
- get: function () { return chunkSBVEYCSV_js.isIndexable; }
820
+ get: function () { return chunkQQB4FO4Q_js.isIndexable; }
432
821
  });
822
+ exports.LocationPageContent = LocationPageContent;
433
823
  exports.ManagedContent = ManagedContent;
434
824
  exports.ManagedFAQ = ManagedFAQ;
435
825
  exports.ManagedInternalLinks = ManagedInternalLinks;
@@ -439,9 +829,27 @@ exports.ManagedScripts = ManagedScripts;
439
829
  exports.createBreadcrumbSchema = createBreadcrumbSchema;
440
830
  exports.createSchema = createSchema;
441
831
  exports.default = ManagedSchema;
832
+ exports.getABTest = getABTest2;
442
833
  exports.getABVariant = getABVariant;
834
+ exports.getContentBlock = getContentBlock2;
835
+ exports.getEntities = getEntities2;
836
+ exports.getEntityEnhancedSchema = getEntityEnhancedSchema2;
837
+ exports.getFAQData = getFAQData2;
838
+ exports.getInternalLinks = getInternalLinks2;
839
+ exports.getLocationSection = getLocationSection;
443
840
  exports.getManagedContentData = getManagedContentData;
444
841
  exports.getManagedMetadata = getManagedMetadata;
445
842
  exports.getManagedMetadataWithAB = getManagedMetadataWithAB;
843
+ exports.getManagedScripts = getManagedScripts2;
844
+ exports.getPrimaryEntity = getPrimaryEntity;
845
+ exports.getRedirectData = getRedirectData;
846
+ exports.getRobotsData = getRobotsData;
847
+ exports.getSEOPageData = getSEOPageData2;
848
+ exports.getSchemaMarkups = getSchemaMarkups2;
849
+ exports.getSitemapEntries = getSitemapEntries;
850
+ exports.getVisibilityScore = getVisibilityScore;
851
+ exports.getVisibilitySummary = getVisibilitySummary;
852
+ exports.recordABImpression = recordABImpression2;
853
+ exports.registerSitemap = registerSitemap;
446
854
  //# sourceMappingURL=index.js.map
447
855
  //# sourceMappingURL=index.js.map