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