@rankcli/agent-runtime 0.0.1
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/README.md +242 -0
- package/dist/analyzer-2CSWIQGD.mjs +6 -0
- package/dist/chunk-YNZYHEYM.mjs +774 -0
- package/dist/index.d.mts +4012 -0
- package/dist/index.d.ts +4012 -0
- package/dist/index.js +29672 -0
- package/dist/index.mjs +28602 -0
- package/package.json +53 -0
- package/scripts/build-deno.ts +134 -0
- package/src/audit/ai/analyzer.ts +347 -0
- package/src/audit/ai/index.ts +29 -0
- package/src/audit/ai/prompts/content-analysis.ts +271 -0
- package/src/audit/ai/types.ts +179 -0
- package/src/audit/checks/additional-checks.ts +439 -0
- package/src/audit/checks/ai-citation-worthiness.ts +399 -0
- package/src/audit/checks/ai-content-structure.ts +325 -0
- package/src/audit/checks/ai-readiness.ts +339 -0
- package/src/audit/checks/anchor-text.ts +179 -0
- package/src/audit/checks/answer-conciseness.ts +322 -0
- package/src/audit/checks/asset-minification.ts +270 -0
- package/src/audit/checks/bing-optimization.ts +206 -0
- package/src/audit/checks/brand-mention-optimization.ts +349 -0
- package/src/audit/checks/caching-headers.ts +305 -0
- package/src/audit/checks/canonical-advanced.ts +150 -0
- package/src/audit/checks/canonical-domain.ts +196 -0
- package/src/audit/checks/citation-quality.ts +358 -0
- package/src/audit/checks/client-rendering.ts +542 -0
- package/src/audit/checks/color-contrast.ts +342 -0
- package/src/audit/checks/content-freshness.ts +170 -0
- package/src/audit/checks/content-science.ts +589 -0
- package/src/audit/checks/conversion-elements.ts +526 -0
- package/src/audit/checks/crawlability.ts +220 -0
- package/src/audit/checks/directory-listing.ts +172 -0
- package/src/audit/checks/dom-analysis.ts +191 -0
- package/src/audit/checks/dom-size.ts +246 -0
- package/src/audit/checks/duplicate-content.ts +194 -0
- package/src/audit/checks/eeat-signals.ts +990 -0
- package/src/audit/checks/entity-seo.ts +396 -0
- package/src/audit/checks/featured-snippet.ts +473 -0
- package/src/audit/checks/freshness-signals.ts +443 -0
- package/src/audit/checks/funnel-intent.ts +463 -0
- package/src/audit/checks/hreflang.ts +174 -0
- package/src/audit/checks/html-compliance.ts +302 -0
- package/src/audit/checks/image-dimensions.ts +167 -0
- package/src/audit/checks/images.ts +160 -0
- package/src/audit/checks/indexnow.ts +275 -0
- package/src/audit/checks/interactive-tools.ts +475 -0
- package/src/audit/checks/internal-link-graph.ts +436 -0
- package/src/audit/checks/keyword-analysis.ts +239 -0
- package/src/audit/checks/keyword-cannibalization.ts +385 -0
- package/src/audit/checks/keyword-placement.ts +471 -0
- package/src/audit/checks/links.ts +203 -0
- package/src/audit/checks/llms-txt.ts +224 -0
- package/src/audit/checks/local-seo.ts +296 -0
- package/src/audit/checks/mobile.ts +167 -0
- package/src/audit/checks/modern-images.ts +226 -0
- package/src/audit/checks/navboost-signals.ts +395 -0
- package/src/audit/checks/on-page.ts +209 -0
- package/src/audit/checks/page-resources.ts +285 -0
- package/src/audit/checks/pagination.ts +180 -0
- package/src/audit/checks/performance.ts +153 -0
- package/src/audit/checks/platform-presence.ts +580 -0
- package/src/audit/checks/redirect-analysis.ts +153 -0
- package/src/audit/checks/redirect-chain.ts +389 -0
- package/src/audit/checks/resource-hints.ts +420 -0
- package/src/audit/checks/responsive-css.ts +247 -0
- package/src/audit/checks/responsive-images.ts +396 -0
- package/src/audit/checks/review-ecosystem.ts +415 -0
- package/src/audit/checks/robots-validation.ts +373 -0
- package/src/audit/checks/security-headers.ts +172 -0
- package/src/audit/checks/security.ts +144 -0
- package/src/audit/checks/serp-preview.ts +251 -0
- package/src/audit/checks/site-maturity.ts +444 -0
- package/src/audit/checks/social-meta.test.ts +275 -0
- package/src/audit/checks/social-meta.ts +134 -0
- package/src/audit/checks/soft-404.ts +151 -0
- package/src/audit/checks/structured-data.ts +238 -0
- package/src/audit/checks/tech-detection.ts +496 -0
- package/src/audit/checks/topical-clusters.ts +435 -0
- package/src/audit/checks/tracker-bloat.ts +462 -0
- package/src/audit/checks/tracking-verification.test.ts +371 -0
- package/src/audit/checks/tracking-verification.ts +636 -0
- package/src/audit/checks/url-safety.ts +682 -0
- package/src/audit/deno-entry.ts +66 -0
- package/src/audit/discovery/index.ts +15 -0
- package/src/audit/discovery/link-crawler.ts +232 -0
- package/src/audit/discovery/repo-routes.ts +347 -0
- package/src/audit/engine.ts +620 -0
- package/src/audit/fixes/index.ts +209 -0
- package/src/audit/fixes/social-meta-fixes.test.ts +329 -0
- package/src/audit/fixes/social-meta-fixes.ts +463 -0
- package/src/audit/index.ts +74 -0
- package/src/audit/runner.test.ts +299 -0
- package/src/audit/runner.ts +130 -0
- package/src/audit/types.ts +1953 -0
- package/src/content/featured-snippet.ts +367 -0
- package/src/content/generator.test.ts +534 -0
- package/src/content/generator.ts +501 -0
- package/src/content/headline.ts +317 -0
- package/src/content/index.ts +62 -0
- package/src/content/intent.ts +258 -0
- package/src/content/keyword-density.ts +349 -0
- package/src/content/readability.ts +262 -0
- package/src/executor.ts +336 -0
- package/src/fixer.ts +416 -0
- package/src/frameworks/detector.test.ts +248 -0
- package/src/frameworks/detector.ts +371 -0
- package/src/frameworks/index.ts +68 -0
- package/src/frameworks/recipes/angular.yaml +171 -0
- package/src/frameworks/recipes/astro.yaml +206 -0
- package/src/frameworks/recipes/django.yaml +180 -0
- package/src/frameworks/recipes/laravel.yaml +137 -0
- package/src/frameworks/recipes/nextjs.yaml +268 -0
- package/src/frameworks/recipes/nuxt.yaml +175 -0
- package/src/frameworks/recipes/rails.yaml +188 -0
- package/src/frameworks/recipes/react.yaml +202 -0
- package/src/frameworks/recipes/sveltekit.yaml +154 -0
- package/src/frameworks/recipes/vue.yaml +137 -0
- package/src/frameworks/recipes/wordpress.yaml +209 -0
- package/src/frameworks/suggestion-engine.ts +320 -0
- package/src/geo/geo-content.test.ts +305 -0
- package/src/geo/geo-content.ts +266 -0
- package/src/geo/geo-history.test.ts +473 -0
- package/src/geo/geo-history.ts +433 -0
- package/src/geo/geo-tracker.test.ts +359 -0
- package/src/geo/geo-tracker.ts +411 -0
- package/src/geo/index.ts +10 -0
- package/src/git/commit-helper.test.ts +261 -0
- package/src/git/commit-helper.ts +329 -0
- package/src/git/index.ts +12 -0
- package/src/git/pr-helper.test.ts +284 -0
- package/src/git/pr-helper.ts +307 -0
- package/src/index.ts +66 -0
- package/src/keywords/ai-keyword-engine.ts +1062 -0
- package/src/keywords/ai-summarizer.ts +387 -0
- package/src/keywords/ci-mode.ts +555 -0
- package/src/keywords/engine.ts +359 -0
- package/src/keywords/index.ts +151 -0
- package/src/keywords/llm-judge.ts +357 -0
- package/src/keywords/nlp-analysis.ts +706 -0
- package/src/keywords/prioritizer.ts +295 -0
- package/src/keywords/site-crawler.ts +342 -0
- package/src/keywords/sources/autocomplete.ts +139 -0
- package/src/keywords/sources/competitive-search.ts +450 -0
- package/src/keywords/sources/competitor-analysis.ts +374 -0
- package/src/keywords/sources/dataforseo.ts +206 -0
- package/src/keywords/sources/free-sources.ts +294 -0
- package/src/keywords/sources/gsc.ts +123 -0
- package/src/keywords/topic-grouping.ts +327 -0
- package/src/keywords/types.ts +144 -0
- package/src/keywords/wizard.ts +457 -0
- package/src/loader.ts +40 -0
- package/src/reports/index.ts +7 -0
- package/src/reports/report-generator.test.ts +293 -0
- package/src/reports/report-generator.ts +713 -0
- package/src/scheduler/alerts.test.ts +458 -0
- package/src/scheduler/alerts.ts +328 -0
- package/src/scheduler/index.ts +8 -0
- package/src/scheduler/scheduled-audit.test.ts +377 -0
- package/src/scheduler/scheduled-audit.ts +149 -0
- package/src/test/integration-test.ts +325 -0
- package/src/tools/analyzer.ts +373 -0
- package/src/tools/crawl.ts +293 -0
- package/src/tools/files.ts +301 -0
- package/src/tools/h1-fixer.ts +249 -0
- package/src/tools/index.ts +67 -0
- package/src/tracking/github-action.ts +326 -0
- package/src/tracking/google-analytics.ts +265 -0
- package/src/tracking/index.ts +45 -0
- package/src/tracking/report-generator.ts +386 -0
- package/src/tracking/search-console.ts +335 -0
- package/src/types.ts +134 -0
- package/src/utils/http.ts +302 -0
- package/src/wasm-adapter.ts +297 -0
- package/src/wasm-entry.ts +14 -0
- package/tsconfig.json +17 -0
- package/tsup.wasm.config.ts +26 -0
- package/vitest.config.ts +15 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,4012 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import { exec } from 'child_process';
|
|
3
|
+
|
|
4
|
+
interface AgentDefinition {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
model: string;
|
|
8
|
+
temperature: number;
|
|
9
|
+
max_tokens: number;
|
|
10
|
+
tools: AgentTool[];
|
|
11
|
+
system: string;
|
|
12
|
+
prompt: string;
|
|
13
|
+
}
|
|
14
|
+
interface AgentTool {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
}
|
|
18
|
+
interface SEOIssue {
|
|
19
|
+
severity: 'critical' | 'warning' | 'info';
|
|
20
|
+
category: 'meta' | 'schema' | 'content' | 'technical' | 'performance' | 'social' | 'accessibility';
|
|
21
|
+
code: string;
|
|
22
|
+
message: string;
|
|
23
|
+
impact: string;
|
|
24
|
+
element?: string;
|
|
25
|
+
fix?: {
|
|
26
|
+
file: string;
|
|
27
|
+
before: string | null;
|
|
28
|
+
after: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
interface SEOAnalysisResult {
|
|
32
|
+
url: string;
|
|
33
|
+
score: number;
|
|
34
|
+
core_web_vitals?: {
|
|
35
|
+
lcp?: {
|
|
36
|
+
value: string;
|
|
37
|
+
status: 'good' | 'needs-improvement' | 'poor';
|
|
38
|
+
};
|
|
39
|
+
fid?: {
|
|
40
|
+
value: string;
|
|
41
|
+
status: 'good' | 'needs-improvement' | 'poor';
|
|
42
|
+
};
|
|
43
|
+
cls?: {
|
|
44
|
+
value: string;
|
|
45
|
+
status: 'good' | 'needs-improvement' | 'poor';
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
issues: SEOIssue[];
|
|
49
|
+
recommendations: SEORecommendation[];
|
|
50
|
+
}
|
|
51
|
+
interface SEORecommendation {
|
|
52
|
+
priority: 'high' | 'medium' | 'low';
|
|
53
|
+
category: string;
|
|
54
|
+
message: string;
|
|
55
|
+
impact: string;
|
|
56
|
+
}
|
|
57
|
+
interface CrawlResult {
|
|
58
|
+
url: string;
|
|
59
|
+
html: string;
|
|
60
|
+
statusCode: number;
|
|
61
|
+
headers: Record<string, string>;
|
|
62
|
+
loadTime: number;
|
|
63
|
+
}
|
|
64
|
+
interface MetaData {
|
|
65
|
+
title?: string;
|
|
66
|
+
description?: string;
|
|
67
|
+
canonical?: string;
|
|
68
|
+
robots?: string;
|
|
69
|
+
viewport?: string;
|
|
70
|
+
charset?: string;
|
|
71
|
+
openGraph: {
|
|
72
|
+
title?: string;
|
|
73
|
+
description?: string;
|
|
74
|
+
image?: string;
|
|
75
|
+
url?: string;
|
|
76
|
+
type?: string;
|
|
77
|
+
siteName?: string;
|
|
78
|
+
};
|
|
79
|
+
twitter: {
|
|
80
|
+
card?: string;
|
|
81
|
+
title?: string;
|
|
82
|
+
description?: string;
|
|
83
|
+
image?: string;
|
|
84
|
+
site?: string;
|
|
85
|
+
};
|
|
86
|
+
other: Record<string, string>;
|
|
87
|
+
}
|
|
88
|
+
interface HeadingStructure {
|
|
89
|
+
tag: string;
|
|
90
|
+
text: string;
|
|
91
|
+
level: number;
|
|
92
|
+
}
|
|
93
|
+
interface ImageInfo$1 {
|
|
94
|
+
src: string;
|
|
95
|
+
alt: string | null;
|
|
96
|
+
width?: string;
|
|
97
|
+
height?: string;
|
|
98
|
+
loading?: string;
|
|
99
|
+
}
|
|
100
|
+
interface LinkInfo {
|
|
101
|
+
href: string;
|
|
102
|
+
text: string;
|
|
103
|
+
isInternal: boolean;
|
|
104
|
+
isNofollow: boolean;
|
|
105
|
+
}
|
|
106
|
+
interface SchemaData {
|
|
107
|
+
type: string;
|
|
108
|
+
data: Record<string, unknown>;
|
|
109
|
+
}
|
|
110
|
+
interface FrameworkInfo$1 {
|
|
111
|
+
name: string;
|
|
112
|
+
version?: string;
|
|
113
|
+
router?: 'app' | 'pages' | 'file-based' | 'custom';
|
|
114
|
+
metaPattern: 'metadata-export' | 'head-component' | 'frontmatter' | 'meta-function' | 'html-head';
|
|
115
|
+
}
|
|
116
|
+
interface Fix {
|
|
117
|
+
issue: {
|
|
118
|
+
code: string;
|
|
119
|
+
message: string;
|
|
120
|
+
severity: string;
|
|
121
|
+
};
|
|
122
|
+
file: string;
|
|
123
|
+
before: string | null;
|
|
124
|
+
after: string;
|
|
125
|
+
explanation: string;
|
|
126
|
+
}
|
|
127
|
+
interface ToolResult {
|
|
128
|
+
success: boolean;
|
|
129
|
+
data?: unknown;
|
|
130
|
+
error?: string;
|
|
131
|
+
}
|
|
132
|
+
type ToolFunction = (params: Record<string, unknown>) => Promise<ToolResult>;
|
|
133
|
+
|
|
134
|
+
type IssueSeverity = 'error' | 'warning' | 'notice';
|
|
135
|
+
type IssueCategory = 'crawlability' | 'indexability' | 'on-page' | 'content' | 'links' | 'images' | 'structured-data' | 'performance' | 'security' | 'mobile' | 'international' | 'ai-readiness' | 'social' | 'local-seo' | 'accessibility' | 'framework';
|
|
136
|
+
interface AuditIssue {
|
|
137
|
+
code: string;
|
|
138
|
+
severity: IssueSeverity;
|
|
139
|
+
category: IssueCategory;
|
|
140
|
+
title: string;
|
|
141
|
+
description: string;
|
|
142
|
+
impact: string;
|
|
143
|
+
howToFix: string;
|
|
144
|
+
affectedUrls?: string[];
|
|
145
|
+
details?: Record<string, unknown>;
|
|
146
|
+
}
|
|
147
|
+
interface PageData {
|
|
148
|
+
url: string;
|
|
149
|
+
statusCode: number;
|
|
150
|
+
redirectChain?: string[];
|
|
151
|
+
html: string;
|
|
152
|
+
loadTime: number;
|
|
153
|
+
size: number;
|
|
154
|
+
headers: Record<string, string>;
|
|
155
|
+
}
|
|
156
|
+
interface CrawlStats {
|
|
157
|
+
totalUrls: number;
|
|
158
|
+
crawledUrls: number;
|
|
159
|
+
errorUrls: number;
|
|
160
|
+
redirectUrls: number;
|
|
161
|
+
blockedUrls: number;
|
|
162
|
+
}
|
|
163
|
+
interface HealthScore {
|
|
164
|
+
overall: number;
|
|
165
|
+
crawlability: number;
|
|
166
|
+
indexability: number;
|
|
167
|
+
onPage: number;
|
|
168
|
+
content: number;
|
|
169
|
+
links: number;
|
|
170
|
+
performance: number;
|
|
171
|
+
security: number;
|
|
172
|
+
aiReadiness: number;
|
|
173
|
+
social: number;
|
|
174
|
+
localSeo: number;
|
|
175
|
+
accessibility: number;
|
|
176
|
+
}
|
|
177
|
+
interface AuditReport {
|
|
178
|
+
url: string;
|
|
179
|
+
domain: string;
|
|
180
|
+
timestamp: string;
|
|
181
|
+
crawlStats: CrawlStats;
|
|
182
|
+
healthScore: HealthScore;
|
|
183
|
+
issues: AuditIssue[];
|
|
184
|
+
pages: PageAudit[];
|
|
185
|
+
summary: {
|
|
186
|
+
errors: number;
|
|
187
|
+
warnings: number;
|
|
188
|
+
notices: number;
|
|
189
|
+
passed: number;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
interface PageAudit {
|
|
193
|
+
url: string;
|
|
194
|
+
statusCode: number;
|
|
195
|
+
title?: string;
|
|
196
|
+
description?: string;
|
|
197
|
+
canonical?: string;
|
|
198
|
+
h1?: string[];
|
|
199
|
+
wordCount: number;
|
|
200
|
+
loadTime: number;
|
|
201
|
+
issues: string[];
|
|
202
|
+
}
|
|
203
|
+
interface IssueDefinition {
|
|
204
|
+
code: string;
|
|
205
|
+
severity: IssueSeverity;
|
|
206
|
+
category: IssueCategory;
|
|
207
|
+
title: string;
|
|
208
|
+
description: string;
|
|
209
|
+
impact: string;
|
|
210
|
+
howToFix: string;
|
|
211
|
+
}
|
|
212
|
+
declare const ISSUE_DEFINITIONS: Record<string, IssueDefinition>;
|
|
213
|
+
|
|
214
|
+
interface AuditOptions {
|
|
215
|
+
url: string;
|
|
216
|
+
checkBrokenLinks?: boolean;
|
|
217
|
+
checkHreflangUrls?: boolean;
|
|
218
|
+
checkCanonicalChain?: boolean;
|
|
219
|
+
maxPages?: number;
|
|
220
|
+
cruxApiKey?: string;
|
|
221
|
+
/**
|
|
222
|
+
* Maximum number of checks to run. Used for tier enforcement:
|
|
223
|
+
* - 50: Free unregistered users (core checks only)
|
|
224
|
+
* - 100: Free registered users (core + some premium checks)
|
|
225
|
+
* - 280+: Paid users (all checks)
|
|
226
|
+
*/
|
|
227
|
+
checksLimit?: number;
|
|
228
|
+
}
|
|
229
|
+
declare function runFullAudit(options: AuditOptions): Promise<AuditReport>;
|
|
230
|
+
declare function formatReport(report: AuditReport): string;
|
|
231
|
+
|
|
232
|
+
interface RobotsTxtResult {
|
|
233
|
+
exists: boolean;
|
|
234
|
+
content?: string;
|
|
235
|
+
blocksAll: boolean;
|
|
236
|
+
hasSitemap: boolean;
|
|
237
|
+
sitemapUrls: string[];
|
|
238
|
+
}
|
|
239
|
+
declare function checkRobotsTxt(baseUrl: string): Promise<{
|
|
240
|
+
issues: AuditIssue[];
|
|
241
|
+
data: RobotsTxtResult;
|
|
242
|
+
}>;
|
|
243
|
+
declare function checkRedirects(url: string): Promise<{
|
|
244
|
+
issues: AuditIssue[];
|
|
245
|
+
chain: string[];
|
|
246
|
+
finalUrl: string;
|
|
247
|
+
}>;
|
|
248
|
+
declare function runCrawlabilityChecks(baseUrl: string): Promise<AuditIssue[]>;
|
|
249
|
+
|
|
250
|
+
interface OnPageData {
|
|
251
|
+
title?: string;
|
|
252
|
+
titleLength: number;
|
|
253
|
+
description?: string;
|
|
254
|
+
descriptionLength: number;
|
|
255
|
+
canonical?: string;
|
|
256
|
+
h1s: string[];
|
|
257
|
+
headings: {
|
|
258
|
+
level: number;
|
|
259
|
+
text: string;
|
|
260
|
+
}[];
|
|
261
|
+
wordCount: number;
|
|
262
|
+
textToHtmlRatio: number;
|
|
263
|
+
hasNoindex: boolean;
|
|
264
|
+
metaRobots?: string;
|
|
265
|
+
}
|
|
266
|
+
declare function analyzeOnPage(html: string, url: string): {
|
|
267
|
+
issues: AuditIssue[];
|
|
268
|
+
data: OnPageData;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
interface LinkData {
|
|
272
|
+
internal: {
|
|
273
|
+
href: string;
|
|
274
|
+
text: string;
|
|
275
|
+
nofollow: boolean;
|
|
276
|
+
}[];
|
|
277
|
+
external: {
|
|
278
|
+
href: string;
|
|
279
|
+
text: string;
|
|
280
|
+
nofollow: boolean;
|
|
281
|
+
}[];
|
|
282
|
+
totalLinks: number;
|
|
283
|
+
brokenInternal: string[];
|
|
284
|
+
brokenExternal: string[];
|
|
285
|
+
ratio: {
|
|
286
|
+
internal: number;
|
|
287
|
+
external: number;
|
|
288
|
+
internalToExternalRatio: number | null;
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
declare function analyzeLinks(html: string, baseUrl: string, checkBroken?: boolean): Promise<{
|
|
292
|
+
issues: AuditIssue[];
|
|
293
|
+
data: LinkData;
|
|
294
|
+
}>;
|
|
295
|
+
|
|
296
|
+
interface ImageData {
|
|
297
|
+
total: number;
|
|
298
|
+
missingAlt: {
|
|
299
|
+
src: string;
|
|
300
|
+
}[];
|
|
301
|
+
emptyAlt: {
|
|
302
|
+
src: string;
|
|
303
|
+
}[];
|
|
304
|
+
missingDimensions: {
|
|
305
|
+
src: string;
|
|
306
|
+
}[];
|
|
307
|
+
largImages: {
|
|
308
|
+
src: string;
|
|
309
|
+
size?: number;
|
|
310
|
+
}[];
|
|
311
|
+
brokenImages: {
|
|
312
|
+
src: string;
|
|
313
|
+
}[];
|
|
314
|
+
lazyLoaded: number;
|
|
315
|
+
withDimensions: number;
|
|
316
|
+
}
|
|
317
|
+
declare function analyzeImages(html: string, baseUrl: string, checkBroken?: boolean): Promise<{
|
|
318
|
+
issues: AuditIssue[];
|
|
319
|
+
data: ImageData;
|
|
320
|
+
}>;
|
|
321
|
+
|
|
322
|
+
interface PerformanceData {
|
|
323
|
+
loadTime: number;
|
|
324
|
+
ttfb: number;
|
|
325
|
+
htmlSize: number;
|
|
326
|
+
compressed: boolean;
|
|
327
|
+
cacheControl?: string;
|
|
328
|
+
contentEncoding?: string;
|
|
329
|
+
}
|
|
330
|
+
declare function analyzePerformance(url: string): Promise<{
|
|
331
|
+
issues: AuditIssue[];
|
|
332
|
+
data: PerformanceData;
|
|
333
|
+
}>;
|
|
334
|
+
declare function fetchCoreWebVitals(url: string, apiKey?: string): Promise<{
|
|
335
|
+
lcp?: {
|
|
336
|
+
value: number;
|
|
337
|
+
rating: 'good' | 'needs-improvement' | 'poor';
|
|
338
|
+
};
|
|
339
|
+
fid?: {
|
|
340
|
+
value: number;
|
|
341
|
+
rating: 'good' | 'needs-improvement' | 'poor';
|
|
342
|
+
};
|
|
343
|
+
cls?: {
|
|
344
|
+
value: number;
|
|
345
|
+
rating: 'good' | 'needs-improvement' | 'poor';
|
|
346
|
+
};
|
|
347
|
+
inp?: {
|
|
348
|
+
value: number;
|
|
349
|
+
rating: 'good' | 'needs-improvement' | 'poor';
|
|
350
|
+
};
|
|
351
|
+
} | null>;
|
|
352
|
+
|
|
353
|
+
interface SecurityData {
|
|
354
|
+
isHttps: boolean;
|
|
355
|
+
hasMixedContent: boolean;
|
|
356
|
+
mixedContentUrls: string[];
|
|
357
|
+
hasHsts: boolean;
|
|
358
|
+
hstsMaxAge?: number;
|
|
359
|
+
certificateExpiry?: Date;
|
|
360
|
+
certificateIssuer?: string;
|
|
361
|
+
}
|
|
362
|
+
declare function analyzeSecurity(html: string, url: string, headers: Record<string, string>): Promise<{
|
|
363
|
+
issues: AuditIssue[];
|
|
364
|
+
data: SecurityData;
|
|
365
|
+
}>;
|
|
366
|
+
declare function checkCertificate(url: string): Promise<{
|
|
367
|
+
valid: boolean;
|
|
368
|
+
expiresAt?: Date;
|
|
369
|
+
issuer?: string;
|
|
370
|
+
daysUntilExpiry?: number;
|
|
371
|
+
issues: AuditIssue[];
|
|
372
|
+
}>;
|
|
373
|
+
|
|
374
|
+
interface SchemaItem {
|
|
375
|
+
type: string;
|
|
376
|
+
data: Record<string, unknown>;
|
|
377
|
+
errors: string[];
|
|
378
|
+
warnings: string[];
|
|
379
|
+
}
|
|
380
|
+
interface StructuredDataData {
|
|
381
|
+
schemas: SchemaItem[];
|
|
382
|
+
hasSchema: boolean;
|
|
383
|
+
schemaTypes: string[];
|
|
384
|
+
}
|
|
385
|
+
declare function analyzeStructuredData(html: string, url: string): {
|
|
386
|
+
issues: AuditIssue[];
|
|
387
|
+
data: StructuredDataData;
|
|
388
|
+
};
|
|
389
|
+
declare function suggestSchemaTypes(html: string, url: string): string[];
|
|
390
|
+
|
|
391
|
+
interface MobileData {
|
|
392
|
+
hasViewport: boolean;
|
|
393
|
+
viewportContent?: string;
|
|
394
|
+
isResponsive: boolean;
|
|
395
|
+
tapTargetIssues: number;
|
|
396
|
+
fontSizeIssues: number;
|
|
397
|
+
}
|
|
398
|
+
declare function analyzeMobile(html: string, url: string): {
|
|
399
|
+
issues: AuditIssue[];
|
|
400
|
+
data: MobileData;
|
|
401
|
+
};
|
|
402
|
+
declare function checkMobileResources(html: string, url: string): AuditIssue[];
|
|
403
|
+
|
|
404
|
+
interface HreflangData {
|
|
405
|
+
hasHreflang: boolean;
|
|
406
|
+
entries: HreflangEntry[];
|
|
407
|
+
hasSelfReference: boolean;
|
|
408
|
+
hasXDefault: boolean;
|
|
409
|
+
}
|
|
410
|
+
interface HreflangEntry {
|
|
411
|
+
lang: string;
|
|
412
|
+
href: string;
|
|
413
|
+
isValid: boolean;
|
|
414
|
+
isSelfReference: boolean;
|
|
415
|
+
statusCode?: number;
|
|
416
|
+
}
|
|
417
|
+
declare function analyzeHreflang(html: string, url: string, options?: {
|
|
418
|
+
validateUrls?: boolean;
|
|
419
|
+
}): Promise<{
|
|
420
|
+
issues: AuditIssue[];
|
|
421
|
+
data: HreflangData;
|
|
422
|
+
}>;
|
|
423
|
+
|
|
424
|
+
interface SocialMetaData {
|
|
425
|
+
openGraph: {
|
|
426
|
+
title?: string;
|
|
427
|
+
description?: string;
|
|
428
|
+
image?: string;
|
|
429
|
+
url?: string;
|
|
430
|
+
type?: string;
|
|
431
|
+
siteName?: string;
|
|
432
|
+
};
|
|
433
|
+
twitter: {
|
|
434
|
+
card?: string;
|
|
435
|
+
title?: string;
|
|
436
|
+
description?: string;
|
|
437
|
+
image?: string;
|
|
438
|
+
site?: string;
|
|
439
|
+
creator?: string;
|
|
440
|
+
};
|
|
441
|
+
hasFavicon: boolean;
|
|
442
|
+
langAttribute?: string;
|
|
443
|
+
}
|
|
444
|
+
declare function analyzeSocialMeta(html: string, url: string): {
|
|
445
|
+
issues: AuditIssue[];
|
|
446
|
+
data: SocialMetaData;
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
interface Soft404Data {
|
|
450
|
+
isSoft404: boolean;
|
|
451
|
+
confidence: number;
|
|
452
|
+
signals: string[];
|
|
453
|
+
}
|
|
454
|
+
declare function detectSoft404(html: string, url: string, statusCode?: number): {
|
|
455
|
+
issues: AuditIssue[];
|
|
456
|
+
data: Soft404Data;
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
interface AnchorTextData {
|
|
460
|
+
totalLinks: number;
|
|
461
|
+
internalLinks: number;
|
|
462
|
+
externalLinks: number;
|
|
463
|
+
emptyAnchors: number;
|
|
464
|
+
genericAnchors: number;
|
|
465
|
+
anchorDistribution: Record<string, number>;
|
|
466
|
+
topAnchors: {
|
|
467
|
+
text: string;
|
|
468
|
+
count: number;
|
|
469
|
+
}[];
|
|
470
|
+
}
|
|
471
|
+
declare function analyzeAnchorText(html: string, url: string): {
|
|
472
|
+
issues: AuditIssue[];
|
|
473
|
+
data: AnchorTextData;
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
interface CanonicalData {
|
|
477
|
+
canonical?: string;
|
|
478
|
+
isSelfReferencing: boolean;
|
|
479
|
+
isCrossDomain: boolean;
|
|
480
|
+
canonicalChain?: string[];
|
|
481
|
+
finalCanonical?: string;
|
|
482
|
+
}
|
|
483
|
+
declare function analyzeCanonicalAdvanced(html: string, url: string, options?: {
|
|
484
|
+
checkChain?: boolean;
|
|
485
|
+
sitemapUrls?: string[];
|
|
486
|
+
}): Promise<{
|
|
487
|
+
issues: AuditIssue[];
|
|
488
|
+
data: CanonicalData;
|
|
489
|
+
}>;
|
|
490
|
+
|
|
491
|
+
interface ContentHashData {
|
|
492
|
+
url: string;
|
|
493
|
+
contentHash: string;
|
|
494
|
+
titleHash: string;
|
|
495
|
+
title?: string;
|
|
496
|
+
wordCount: number;
|
|
497
|
+
textSample: string;
|
|
498
|
+
}
|
|
499
|
+
interface DuplicateDetectionResult {
|
|
500
|
+
duplicates: Array<{
|
|
501
|
+
url1: string;
|
|
502
|
+
url2: string;
|
|
503
|
+
similarity: number;
|
|
504
|
+
type: 'exact' | 'near-duplicate';
|
|
505
|
+
}>;
|
|
506
|
+
potentialCannibalization: Array<{
|
|
507
|
+
pages: string[];
|
|
508
|
+
keyword: string;
|
|
509
|
+
similarity: number;
|
|
510
|
+
}>;
|
|
511
|
+
}
|
|
512
|
+
declare function extractContentHash(html: string, url: string): ContentHashData;
|
|
513
|
+
declare function detectDuplicates(pages: ContentHashData[]): DuplicateDetectionResult;
|
|
514
|
+
declare function generateDuplicateIssues(result: DuplicateDetectionResult, currentUrl: string): AuditIssue[];
|
|
515
|
+
|
|
516
|
+
interface PaginationData {
|
|
517
|
+
hasPagination: boolean;
|
|
518
|
+
hasHtmlPaginationLinks: boolean;
|
|
519
|
+
hasInfiniteScroll: boolean;
|
|
520
|
+
hasLoadMoreButton: boolean;
|
|
521
|
+
paginationLinks: string[];
|
|
522
|
+
relNextPrev: {
|
|
523
|
+
hasNext: boolean;
|
|
524
|
+
hasPrev: boolean;
|
|
525
|
+
nextUrl?: string;
|
|
526
|
+
prevUrl?: string;
|
|
527
|
+
};
|
|
528
|
+
currentPage?: number;
|
|
529
|
+
totalPages?: number;
|
|
530
|
+
}
|
|
531
|
+
declare function analyzePagination(html: string, url: string, canonical?: string): {
|
|
532
|
+
issues: AuditIssue[];
|
|
533
|
+
data: PaginationData;
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
interface RedirectData {
|
|
537
|
+
hasRedirect: boolean;
|
|
538
|
+
redirectChain: RedirectHop$1[];
|
|
539
|
+
isLoop: boolean;
|
|
540
|
+
finalUrl?: string;
|
|
541
|
+
totalHops: number;
|
|
542
|
+
}
|
|
543
|
+
interface RedirectHop$1 {
|
|
544
|
+
url: string;
|
|
545
|
+
statusCode: number;
|
|
546
|
+
location?: string;
|
|
547
|
+
}
|
|
548
|
+
declare function analyzeRedirects(url: string, maxHops?: number): Promise<{
|
|
549
|
+
issues: AuditIssue[];
|
|
550
|
+
data: RedirectData;
|
|
551
|
+
}>;
|
|
552
|
+
declare function checkInternalRedirects(internalLinks: string[], batchSize?: number): Promise<{
|
|
553
|
+
redirectLinks: Array<{
|
|
554
|
+
source: string;
|
|
555
|
+
target: string;
|
|
556
|
+
statusCode: number;
|
|
557
|
+
}>;
|
|
558
|
+
}>;
|
|
559
|
+
|
|
560
|
+
interface LlmsTxtResult {
|
|
561
|
+
exists: boolean;
|
|
562
|
+
content?: string;
|
|
563
|
+
valid: boolean;
|
|
564
|
+
errors: string[];
|
|
565
|
+
}
|
|
566
|
+
interface AIBotBlockingResult {
|
|
567
|
+
robotsExists: boolean;
|
|
568
|
+
blockedBots: string[];
|
|
569
|
+
allowedBots: string[];
|
|
570
|
+
allBlocked: boolean;
|
|
571
|
+
}
|
|
572
|
+
interface AIReadinessData {
|
|
573
|
+
llmsTxt: LlmsTxtResult;
|
|
574
|
+
botBlocking: AIBotBlockingResult;
|
|
575
|
+
jsRenderingRatio: number;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Check for llms.txt file
|
|
579
|
+
* See: https://llmstxt.org/
|
|
580
|
+
*/
|
|
581
|
+
declare function checkLlmsTxt(baseUrl: string): Promise<{
|
|
582
|
+
issues: AuditIssue[];
|
|
583
|
+
data: LlmsTxtResult;
|
|
584
|
+
}>;
|
|
585
|
+
/**
|
|
586
|
+
* Check robots.txt for AI bot blocking
|
|
587
|
+
*/
|
|
588
|
+
declare function checkAIBotBlocking(baseUrl: string): Promise<{
|
|
589
|
+
issues: AuditIssue[];
|
|
590
|
+
data: AIBotBlockingResult;
|
|
591
|
+
}>;
|
|
592
|
+
/**
|
|
593
|
+
* Check JavaScript rendering ratio
|
|
594
|
+
* Compares static HTML content size vs rendered content
|
|
595
|
+
*/
|
|
596
|
+
declare function checkJSRenderingRatio(html: string, url: string): {
|
|
597
|
+
issues: AuditIssue[];
|
|
598
|
+
data: {
|
|
599
|
+
ratio: number;
|
|
600
|
+
staticWordCount: number;
|
|
601
|
+
};
|
|
602
|
+
};
|
|
603
|
+
/**
|
|
604
|
+
* Run all AI readiness checks
|
|
605
|
+
*/
|
|
606
|
+
declare function runAIReadinessChecks(baseUrl: string, html: string): Promise<{
|
|
607
|
+
issues: AuditIssue[];
|
|
608
|
+
data: AIReadinessData;
|
|
609
|
+
}>;
|
|
610
|
+
|
|
611
|
+
interface SERPPreviewData {
|
|
612
|
+
title: {
|
|
613
|
+
text: string;
|
|
614
|
+
charLength: number;
|
|
615
|
+
pixelWidth: number;
|
|
616
|
+
truncated: boolean;
|
|
617
|
+
displayText: string;
|
|
618
|
+
};
|
|
619
|
+
description: {
|
|
620
|
+
text: string;
|
|
621
|
+
charLength: number;
|
|
622
|
+
pixelWidthDesktop: number;
|
|
623
|
+
pixelWidthMobile: number;
|
|
624
|
+
truncatedDesktop: boolean;
|
|
625
|
+
truncatedMobile: boolean;
|
|
626
|
+
displayTextDesktop: string;
|
|
627
|
+
displayTextMobile: string;
|
|
628
|
+
};
|
|
629
|
+
url: {
|
|
630
|
+
display: string;
|
|
631
|
+
breadcrumbs: string[];
|
|
632
|
+
};
|
|
633
|
+
preview: {
|
|
634
|
+
desktop: string;
|
|
635
|
+
mobile: string;
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Analyze SERP preview and generate pixel-based issues
|
|
640
|
+
*/
|
|
641
|
+
declare function analyzeSERPPreview(html: string, url: string): {
|
|
642
|
+
issues: AuditIssue[];
|
|
643
|
+
data: SERPPreviewData;
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
interface LocalSEOData {
|
|
647
|
+
hasLocalBusinessSchema: boolean;
|
|
648
|
+
hasOrganizationSchema: boolean;
|
|
649
|
+
detectedPhones: string[];
|
|
650
|
+
detectedAddresses: string[];
|
|
651
|
+
schemaData: {
|
|
652
|
+
name?: string;
|
|
653
|
+
address?: string;
|
|
654
|
+
phone?: string;
|
|
655
|
+
hours?: string[];
|
|
656
|
+
geo?: {
|
|
657
|
+
lat: number;
|
|
658
|
+
lng: number;
|
|
659
|
+
};
|
|
660
|
+
} | null;
|
|
661
|
+
socialProfiles: string[];
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Analyze local SEO elements
|
|
665
|
+
*/
|
|
666
|
+
declare function analyzeLocalSEO(html: string, url: string): {
|
|
667
|
+
issues: AuditIssue[];
|
|
668
|
+
data: LocalSEOData;
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
interface SecurityHeadersData {
|
|
672
|
+
https: boolean;
|
|
673
|
+
headers: {
|
|
674
|
+
hsts: string | null;
|
|
675
|
+
csp: string | null;
|
|
676
|
+
xFrameOptions: string | null;
|
|
677
|
+
xContentTypeOptions: string | null;
|
|
678
|
+
referrerPolicy: string | null;
|
|
679
|
+
permissionsPolicy: string | null;
|
|
680
|
+
};
|
|
681
|
+
hstsMaxAge: number | null;
|
|
682
|
+
hstsIncludesSubdomains: boolean;
|
|
683
|
+
hstsPreload: boolean;
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Analyze security headers
|
|
687
|
+
*/
|
|
688
|
+
declare function analyzeSecurityHeaders(url: string): Promise<{
|
|
689
|
+
issues: AuditIssue[];
|
|
690
|
+
data: SecurityHeadersData;
|
|
691
|
+
}>;
|
|
692
|
+
|
|
693
|
+
interface ContentFreshnessData {
|
|
694
|
+
lastModified: Date | null;
|
|
695
|
+
articleModifiedTime: Date | null;
|
|
696
|
+
articlePublishedTime: Date | null;
|
|
697
|
+
ogUpdatedTime: Date | null;
|
|
698
|
+
ageInDays: number | null;
|
|
699
|
+
isStale: boolean;
|
|
700
|
+
source: 'last-modified' | 'og-updated-time' | 'article-modified-time' | 'none';
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Analyze content freshness
|
|
704
|
+
*/
|
|
705
|
+
declare function analyzeContentFreshness(url: string, html: string): Promise<{
|
|
706
|
+
issues: AuditIssue[];
|
|
707
|
+
data: ContentFreshnessData;
|
|
708
|
+
}>;
|
|
709
|
+
|
|
710
|
+
interface DOMAnalysisData {
|
|
711
|
+
nodeCount: number;
|
|
712
|
+
maxDepth: number;
|
|
713
|
+
renderBlockingResources: {
|
|
714
|
+
css: string[];
|
|
715
|
+
js: string[];
|
|
716
|
+
};
|
|
717
|
+
totalRenderBlockingSize: number;
|
|
718
|
+
criticalPathLength: number;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Analyze DOM structure and render-blocking resources
|
|
722
|
+
*/
|
|
723
|
+
declare function analyzeDOMStructure(html: string, url: string): {
|
|
724
|
+
issues: AuditIssue[];
|
|
725
|
+
data: DOMAnalysisData;
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
interface ImageInfo {
|
|
729
|
+
src: string;
|
|
730
|
+
alt: string | null;
|
|
731
|
+
width: number | null;
|
|
732
|
+
height: number | null;
|
|
733
|
+
loading: string | null;
|
|
734
|
+
format: string;
|
|
735
|
+
isModernFormat: boolean;
|
|
736
|
+
hasDimensions: boolean;
|
|
737
|
+
isLazyLoaded: boolean;
|
|
738
|
+
}
|
|
739
|
+
interface ModernImagesData {
|
|
740
|
+
totalImages: number;
|
|
741
|
+
modernFormatCount: number;
|
|
742
|
+
legacyFormatCount: number;
|
|
743
|
+
modernFormatPercentage: number;
|
|
744
|
+
images: ImageInfo[];
|
|
745
|
+
hasSourceSet: boolean;
|
|
746
|
+
hasPictureElements: boolean;
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Analyze image formats and optimization
|
|
750
|
+
*/
|
|
751
|
+
declare function analyzeModernImages(html: string, url: string): {
|
|
752
|
+
issues: AuditIssue[];
|
|
753
|
+
data: ModernImagesData;
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
interface TechnologyInfo {
|
|
757
|
+
name: string;
|
|
758
|
+
version?: string;
|
|
759
|
+
category: 'cms' | 'framework' | 'library' | 'server' | 'analytics' | 'cdn' | 'other';
|
|
760
|
+
confidence: 'high' | 'medium' | 'low';
|
|
761
|
+
}
|
|
762
|
+
interface TechDetectionData {
|
|
763
|
+
technologies: TechnologyInfo[];
|
|
764
|
+
cms: string | null;
|
|
765
|
+
framework: string | null;
|
|
766
|
+
jsLibraries: string[];
|
|
767
|
+
analytics: string[];
|
|
768
|
+
cdn: string | null;
|
|
769
|
+
serverHeaders: Record<string, string>;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Detect technologies from HTML and headers
|
|
773
|
+
*/
|
|
774
|
+
declare function detectTechnologies(html: string, url: string, headers?: Record<string, string>): {
|
|
775
|
+
issues: AuditIssue[];
|
|
776
|
+
data: TechDetectionData;
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
interface KeywordInfo {
|
|
780
|
+
word: string;
|
|
781
|
+
count: number;
|
|
782
|
+
density: number;
|
|
783
|
+
inTitle: boolean;
|
|
784
|
+
inH1: boolean;
|
|
785
|
+
inH2: boolean;
|
|
786
|
+
inMetaDesc: boolean;
|
|
787
|
+
}
|
|
788
|
+
interface KeywordPhraseInfo {
|
|
789
|
+
phrase: string;
|
|
790
|
+
count: number;
|
|
791
|
+
wordCount: number;
|
|
792
|
+
}
|
|
793
|
+
interface KeywordAnalysisData {
|
|
794
|
+
totalWords: number;
|
|
795
|
+
uniqueWords: number;
|
|
796
|
+
topKeywords: KeywordInfo[];
|
|
797
|
+
topPhrases: {
|
|
798
|
+
twoWord: KeywordPhraseInfo[];
|
|
799
|
+
threeWord: KeywordPhraseInfo[];
|
|
800
|
+
fourWord: KeywordPhraseInfo[];
|
|
801
|
+
};
|
|
802
|
+
keywordDistribution: {
|
|
803
|
+
title: string[];
|
|
804
|
+
h1: string[];
|
|
805
|
+
h2: string[];
|
|
806
|
+
metaDesc: string[];
|
|
807
|
+
};
|
|
808
|
+
potentialStuffing: string[];
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Analyze keyword density and distribution
|
|
812
|
+
*/
|
|
813
|
+
declare function analyzeKeywords(html: string, url: string): {
|
|
814
|
+
issues: AuditIssue[];
|
|
815
|
+
data: KeywordAnalysisData;
|
|
816
|
+
};
|
|
817
|
+
|
|
818
|
+
interface AdsTxtData {
|
|
819
|
+
exists: boolean;
|
|
820
|
+
valid: boolean;
|
|
821
|
+
entries: number;
|
|
822
|
+
errors: string[];
|
|
823
|
+
}
|
|
824
|
+
interface DMARCData {
|
|
825
|
+
exists: boolean;
|
|
826
|
+
policy: string | null;
|
|
827
|
+
record: string | null;
|
|
828
|
+
}
|
|
829
|
+
interface SPFData {
|
|
830
|
+
exists: boolean;
|
|
831
|
+
record: string | null;
|
|
832
|
+
}
|
|
833
|
+
interface AMPData {
|
|
834
|
+
hasAmpLink: boolean;
|
|
835
|
+
ampUrl: string | null;
|
|
836
|
+
ampValid: boolean | null;
|
|
837
|
+
}
|
|
838
|
+
interface AdditionalChecksData {
|
|
839
|
+
adsTxt: AdsTxtData;
|
|
840
|
+
dmarc: DMARCData;
|
|
841
|
+
spf: SPFData;
|
|
842
|
+
amp: AMPData;
|
|
843
|
+
plaintextEmails: string[];
|
|
844
|
+
hasAppleTouchIcon: boolean;
|
|
845
|
+
faviconFormat: string | null;
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Check for ads.txt file
|
|
849
|
+
*/
|
|
850
|
+
declare function checkAdsTxt(baseUrl: string): Promise<{
|
|
851
|
+
issues: AuditIssue[];
|
|
852
|
+
data: AdsTxtData;
|
|
853
|
+
}>;
|
|
854
|
+
/**
|
|
855
|
+
* Check DMARC DNS record
|
|
856
|
+
*/
|
|
857
|
+
declare function checkDMARC(domain: string): Promise<{
|
|
858
|
+
issues: AuditIssue[];
|
|
859
|
+
data: DMARCData;
|
|
860
|
+
}>;
|
|
861
|
+
/**
|
|
862
|
+
* Check SPF DNS record
|
|
863
|
+
*/
|
|
864
|
+
declare function checkSPF(domain: string): Promise<{
|
|
865
|
+
issues: AuditIssue[];
|
|
866
|
+
data: SPFData;
|
|
867
|
+
}>;
|
|
868
|
+
/**
|
|
869
|
+
* Check for AMP version
|
|
870
|
+
*/
|
|
871
|
+
declare function checkAMP(html: string, url: string): {
|
|
872
|
+
issues: AuditIssue[];
|
|
873
|
+
data: AMPData;
|
|
874
|
+
};
|
|
875
|
+
/**
|
|
876
|
+
* Check for plaintext email addresses
|
|
877
|
+
*/
|
|
878
|
+
declare function checkPlaintextEmails(html: string, url: string): {
|
|
879
|
+
issues: AuditIssue[];
|
|
880
|
+
emails: string[];
|
|
881
|
+
};
|
|
882
|
+
/**
|
|
883
|
+
* Check for Apple Touch Icon
|
|
884
|
+
*/
|
|
885
|
+
declare function checkAppleTouchIcon(html: string, url: string): {
|
|
886
|
+
issues: AuditIssue[];
|
|
887
|
+
exists: boolean;
|
|
888
|
+
};
|
|
889
|
+
/**
|
|
890
|
+
* Run all additional checks
|
|
891
|
+
*/
|
|
892
|
+
declare function runAdditionalChecks(url: string, html: string): Promise<{
|
|
893
|
+
issues: AuditIssue[];
|
|
894
|
+
data: AdditionalChecksData;
|
|
895
|
+
}>;
|
|
896
|
+
|
|
897
|
+
interface TrackerInfo {
|
|
898
|
+
name: string;
|
|
899
|
+
type: 'analytics' | 'advertising' | 'social' | 'marketing' | 'heatmap' | 'chat' | 'other';
|
|
900
|
+
domain: string;
|
|
901
|
+
impact: 'high' | 'medium' | 'low';
|
|
902
|
+
}
|
|
903
|
+
interface DetectedTracker extends TrackerInfo {
|
|
904
|
+
scriptUrl?: string;
|
|
905
|
+
loadMethod: 'sync' | 'async' | 'defer' | 'inline';
|
|
906
|
+
}
|
|
907
|
+
interface TrackerAnalysis {
|
|
908
|
+
trackers: DetectedTracker[];
|
|
909
|
+
totalCount: number;
|
|
910
|
+
byType: Record<string, number>;
|
|
911
|
+
byImpact: Record<string, number>;
|
|
912
|
+
estimatedImpactScore: number;
|
|
913
|
+
recommendations: string[];
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Main function: Analyze page for tracker bloat
|
|
917
|
+
*/
|
|
918
|
+
declare function analyzeTrackerBloat(html: string, url: string): {
|
|
919
|
+
issues: AuditIssue[];
|
|
920
|
+
data: TrackerAnalysis;
|
|
921
|
+
};
|
|
922
|
+
|
|
923
|
+
interface RenderingAnalysis {
|
|
924
|
+
renderingMethod: 'ssr' | 'ssg' | 'csr' | 'hybrid' | 'unknown';
|
|
925
|
+
confidence: 'high' | 'medium' | 'low';
|
|
926
|
+
signals: RenderingSignal[];
|
|
927
|
+
frameworkDetected: string | null;
|
|
928
|
+
hasContentInHTML: boolean;
|
|
929
|
+
hasHydrationMarkers: boolean;
|
|
930
|
+
hasClientOnlyIndicators: boolean;
|
|
931
|
+
mainContentCharCount: number;
|
|
932
|
+
recommendations: string[];
|
|
933
|
+
metaManagement: string | null;
|
|
934
|
+
hasDynamicMetaTags: boolean;
|
|
935
|
+
aiAccessibility: {
|
|
936
|
+
htmlContentRatio: number;
|
|
937
|
+
hasSemanticStructure: boolean;
|
|
938
|
+
keyContentInHTML: boolean;
|
|
939
|
+
aiReadableScore: number;
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
interface RenderingSignal {
|
|
943
|
+
indicator: string;
|
|
944
|
+
suggests: 'ssr' | 'ssg' | 'csr';
|
|
945
|
+
weight: number;
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Main function: Analyze page rendering method for SEO
|
|
949
|
+
*/
|
|
950
|
+
declare function analyzeClientRendering(html: string, url: string): {
|
|
951
|
+
issues: AuditIssue[];
|
|
952
|
+
data: RenderingAnalysis;
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
interface RedirectHop {
|
|
956
|
+
url: string;
|
|
957
|
+
statusCode: number;
|
|
958
|
+
statusText: string;
|
|
959
|
+
redirectTo: string | null;
|
|
960
|
+
responseTime: number;
|
|
961
|
+
}
|
|
962
|
+
interface RedirectChainResult {
|
|
963
|
+
originalUrl: string;
|
|
964
|
+
finalUrl: string;
|
|
965
|
+
hops: RedirectHop[];
|
|
966
|
+
chainLength: number;
|
|
967
|
+
totalTime: number;
|
|
968
|
+
hasHttpsUpgrade: boolean;
|
|
969
|
+
hasWwwNormalization: boolean;
|
|
970
|
+
hasTrailingSlashIssue: boolean;
|
|
971
|
+
isInternalLoop: boolean;
|
|
972
|
+
issues: string[];
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* Main function: Analyze redirects for SEO issues
|
|
976
|
+
*/
|
|
977
|
+
declare function analyzeRedirectChain(url: string): Promise<{
|
|
978
|
+
issues: AuditIssue[];
|
|
979
|
+
data: RedirectChainResult;
|
|
980
|
+
}>;
|
|
981
|
+
|
|
982
|
+
interface ImageAnalysis {
|
|
983
|
+
src: string;
|
|
984
|
+
alt: string | null;
|
|
985
|
+
width: string | null;
|
|
986
|
+
height: string | null;
|
|
987
|
+
loading: 'lazy' | 'eager' | null;
|
|
988
|
+
decoding: 'async' | 'sync' | 'auto' | null;
|
|
989
|
+
srcset: string | null;
|
|
990
|
+
sizes: string | null;
|
|
991
|
+
isAboveFold: boolean;
|
|
992
|
+
hasExplicitDimensions: boolean;
|
|
993
|
+
hasResponsiveSrcset: boolean;
|
|
994
|
+
usesModernFormat: boolean;
|
|
995
|
+
issues: string[];
|
|
996
|
+
}
|
|
997
|
+
interface ResponsiveImageData {
|
|
998
|
+
totalImages: number;
|
|
999
|
+
imagesWithoutDimensions: number;
|
|
1000
|
+
imagesWithoutLazyLoad: number;
|
|
1001
|
+
imagesWithoutSrcset: number;
|
|
1002
|
+
imagesWithoutAlt: number;
|
|
1003
|
+
modernFormatCount: number;
|
|
1004
|
+
legacyFormatCount: number;
|
|
1005
|
+
images: ImageAnalysis[];
|
|
1006
|
+
recommendations: string[];
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Main function: Analyze responsive image best practices
|
|
1010
|
+
*/
|
|
1011
|
+
declare function analyzeResponsiveImages(html: string, url: string): {
|
|
1012
|
+
issues: AuditIssue[];
|
|
1013
|
+
data: ResponsiveImageData;
|
|
1014
|
+
};
|
|
1015
|
+
|
|
1016
|
+
interface AboveFoldAnalysis {
|
|
1017
|
+
hasHeadline: boolean;
|
|
1018
|
+
headlineText: string | null;
|
|
1019
|
+
hasCTA: boolean;
|
|
1020
|
+
ctaCount: number;
|
|
1021
|
+
ctaTexts: string[];
|
|
1022
|
+
hasForm: boolean;
|
|
1023
|
+
formType: 'contact' | 'signup' | 'search' | 'calculator' | 'other' | null;
|
|
1024
|
+
hasSocialProof: boolean;
|
|
1025
|
+
socialProofTypes: string[];
|
|
1026
|
+
hasHeroImage: boolean;
|
|
1027
|
+
hasVideo: boolean;
|
|
1028
|
+
estimatedAboveFoldScore: number;
|
|
1029
|
+
}
|
|
1030
|
+
interface SocialProofAnalysis {
|
|
1031
|
+
hasTestimonials: boolean;
|
|
1032
|
+
testimonialCount: number;
|
|
1033
|
+
hasReviews: boolean;
|
|
1034
|
+
reviewCount: number;
|
|
1035
|
+
hasRatings: boolean;
|
|
1036
|
+
averageRating: number | null;
|
|
1037
|
+
hasClientLogos: boolean;
|
|
1038
|
+
clientLogoCount: number;
|
|
1039
|
+
hasCaseStudies: boolean;
|
|
1040
|
+
hasAwards: boolean;
|
|
1041
|
+
hasCertifications: boolean;
|
|
1042
|
+
hasTrustBadges: boolean;
|
|
1043
|
+
hasStatistics: boolean;
|
|
1044
|
+
statisticsFound: string[];
|
|
1045
|
+
socialProofScore: number;
|
|
1046
|
+
}
|
|
1047
|
+
interface EngagementTriggers {
|
|
1048
|
+
hasCalculator: boolean;
|
|
1049
|
+
calculatorTypes: string[];
|
|
1050
|
+
hasQuiz: boolean;
|
|
1051
|
+
hasInteractiveElement: boolean;
|
|
1052
|
+
interactiveTypes: string[];
|
|
1053
|
+
hasEmbeddedVideo: boolean;
|
|
1054
|
+
videoCount: number;
|
|
1055
|
+
hasExpandableContent: boolean;
|
|
1056
|
+
hasTabsOrAccordion: boolean;
|
|
1057
|
+
hasChatWidget: boolean;
|
|
1058
|
+
engagementScore: number;
|
|
1059
|
+
}
|
|
1060
|
+
interface ConversionElementsData {
|
|
1061
|
+
aboveFold: AboveFoldAnalysis;
|
|
1062
|
+
socialProof: SocialProofAnalysis;
|
|
1063
|
+
engagementTriggers: EngagementTriggers;
|
|
1064
|
+
pageType: 'commercial' | 'informational' | 'mixed' | 'unknown';
|
|
1065
|
+
recommendations: string[];
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Main function: Analyze conversion elements
|
|
1069
|
+
*/
|
|
1070
|
+
declare function analyzeConversionElements(html: string, url: string): {
|
|
1071
|
+
issues: AuditIssue[];
|
|
1072
|
+
data: ConversionElementsData;
|
|
1073
|
+
};
|
|
1074
|
+
|
|
1075
|
+
interface KeywordPlacementData {
|
|
1076
|
+
detectedKeywords: string[];
|
|
1077
|
+
urlAnalysis: {
|
|
1078
|
+
containsKeyword: boolean;
|
|
1079
|
+
keywordInUrl: string | null;
|
|
1080
|
+
urlSlug: string;
|
|
1081
|
+
isCleanUrl: boolean;
|
|
1082
|
+
hasDynamicParams: boolean;
|
|
1083
|
+
};
|
|
1084
|
+
titleAnalysis: {
|
|
1085
|
+
hasExactMatch: boolean;
|
|
1086
|
+
hasPartialMatch: boolean;
|
|
1087
|
+
titleMatchScore: number;
|
|
1088
|
+
position: 'start' | 'middle' | 'end' | 'none';
|
|
1089
|
+
};
|
|
1090
|
+
h1Analysis: {
|
|
1091
|
+
hasExactMatch: boolean;
|
|
1092
|
+
hasPartialMatch: boolean;
|
|
1093
|
+
h1Text: string | null;
|
|
1094
|
+
};
|
|
1095
|
+
firstParagraphAnalysis: {
|
|
1096
|
+
hasKeyword: boolean;
|
|
1097
|
+
keywordPosition: number | null;
|
|
1098
|
+
firstParagraphPreview: string;
|
|
1099
|
+
isWithinFirst100Words: boolean;
|
|
1100
|
+
};
|
|
1101
|
+
metaDescriptionAnalysis: {
|
|
1102
|
+
hasKeyword: boolean;
|
|
1103
|
+
position: 'start' | 'middle' | 'end' | 'none';
|
|
1104
|
+
};
|
|
1105
|
+
overallPlacementScore: number;
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Main function: Analyze keyword placement
|
|
1109
|
+
*/
|
|
1110
|
+
declare function analyzeKeywordPlacement(html: string, url: string): {
|
|
1111
|
+
issues: AuditIssue[];
|
|
1112
|
+
data: KeywordPlacementData;
|
|
1113
|
+
};
|
|
1114
|
+
|
|
1115
|
+
interface InternalLink {
|
|
1116
|
+
href: string;
|
|
1117
|
+
anchorText: string;
|
|
1118
|
+
context: 'navigation' | 'content' | 'footer' | 'sidebar';
|
|
1119
|
+
isDoFollow: boolean;
|
|
1120
|
+
destination: 'internal' | 'external' | 'anchor';
|
|
1121
|
+
}
|
|
1122
|
+
interface TopicalClusterData {
|
|
1123
|
+
currentUrl: string;
|
|
1124
|
+
internalLinks: InternalLink[];
|
|
1125
|
+
externalLinks: InternalLink[];
|
|
1126
|
+
anchorLinks: InternalLink[];
|
|
1127
|
+
linkMetrics: {
|
|
1128
|
+
totalLinks: number;
|
|
1129
|
+
internalLinkCount: number;
|
|
1130
|
+
externalLinkCount: number;
|
|
1131
|
+
contentLinks: number;
|
|
1132
|
+
uniqueInternalDestinations: number;
|
|
1133
|
+
avgAnchorTextLength: number;
|
|
1134
|
+
hasExactMatchAnchors: boolean;
|
|
1135
|
+
};
|
|
1136
|
+
clusterSignals: {
|
|
1137
|
+
hasHubStructure: boolean;
|
|
1138
|
+
hasSpokeLinks: boolean;
|
|
1139
|
+
hasBreadcrumbs: boolean;
|
|
1140
|
+
hasRelatedPosts: boolean;
|
|
1141
|
+
hasCategoryLinks: boolean;
|
|
1142
|
+
internalToExternalRatio: number;
|
|
1143
|
+
};
|
|
1144
|
+
orphanPageRisk: 'low' | 'medium' | 'high';
|
|
1145
|
+
recommendations: string[];
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
1148
|
+
* Main function: Analyze topical cluster structure
|
|
1149
|
+
*/
|
|
1150
|
+
declare function analyzeTopicalClusters(html: string, url: string): {
|
|
1151
|
+
issues: AuditIssue[];
|
|
1152
|
+
data: TopicalClusterData;
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1155
|
+
interface PlatformLink {
|
|
1156
|
+
platform: string;
|
|
1157
|
+
url: string;
|
|
1158
|
+
type: 'profile' | 'content' | 'mention' | 'embed';
|
|
1159
|
+
location: 'header' | 'footer' | 'content' | 'sidebar' | 'schema';
|
|
1160
|
+
}
|
|
1161
|
+
interface PlatformPresenceData {
|
|
1162
|
+
detectedPlatforms: string[];
|
|
1163
|
+
platformLinks: PlatformLink[];
|
|
1164
|
+
socialProfiles: {
|
|
1165
|
+
platform: string;
|
|
1166
|
+
url: string;
|
|
1167
|
+
hasSchemaMarkup: boolean;
|
|
1168
|
+
}[];
|
|
1169
|
+
embeddedContent: {
|
|
1170
|
+
platform: string;
|
|
1171
|
+
count: number;
|
|
1172
|
+
}[];
|
|
1173
|
+
metrics: {
|
|
1174
|
+
totalPlatforms: number;
|
|
1175
|
+
hasYouTube: boolean;
|
|
1176
|
+
hasTikTok: boolean;
|
|
1177
|
+
hasTwitter: boolean;
|
|
1178
|
+
hasLinkedIn: boolean;
|
|
1179
|
+
hasReddit: boolean;
|
|
1180
|
+
hasFacebook: boolean;
|
|
1181
|
+
hasInstagram: boolean;
|
|
1182
|
+
hasPinterest: boolean;
|
|
1183
|
+
hasPodcast: boolean;
|
|
1184
|
+
hasGitHub: boolean;
|
|
1185
|
+
};
|
|
1186
|
+
schemaPresence: {
|
|
1187
|
+
hasSameAs: boolean;
|
|
1188
|
+
sameAsUrls: string[];
|
|
1189
|
+
hasOrganizationSchema: boolean;
|
|
1190
|
+
hasPersonSchema: boolean;
|
|
1191
|
+
};
|
|
1192
|
+
crossPlatformScore: number;
|
|
1193
|
+
recommendations: string[];
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Main function: Analyze platform presence
|
|
1197
|
+
*/
|
|
1198
|
+
declare function analyzePlatformPresence(html: string, url: string): {
|
|
1199
|
+
issues: AuditIssue[];
|
|
1200
|
+
data: PlatformPresenceData;
|
|
1201
|
+
};
|
|
1202
|
+
|
|
1203
|
+
interface InteractiveElement {
|
|
1204
|
+
type: 'calculator' | 'quiz' | 'form' | 'widget' | 'embed' | 'tool' | 'interactive';
|
|
1205
|
+
description: string;
|
|
1206
|
+
location: string;
|
|
1207
|
+
hasUserInput: boolean;
|
|
1208
|
+
}
|
|
1209
|
+
interface InteractiveToolsData {
|
|
1210
|
+
hasInteractiveTools: boolean;
|
|
1211
|
+
tools: InteractiveElement[];
|
|
1212
|
+
dwellTimeSignals: {
|
|
1213
|
+
hasCalculator: boolean;
|
|
1214
|
+
hasQuiz: boolean;
|
|
1215
|
+
hasInteractiveWidget: boolean;
|
|
1216
|
+
hasVideoEmbed: boolean;
|
|
1217
|
+
hasCodePlayground: boolean;
|
|
1218
|
+
hasConfigurator: boolean;
|
|
1219
|
+
hasChatWidget: boolean;
|
|
1220
|
+
};
|
|
1221
|
+
toolCount: number;
|
|
1222
|
+
dwellTimeScore: number;
|
|
1223
|
+
recommendations: string[];
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Main function: Analyze interactive tools on the page
|
|
1227
|
+
*/
|
|
1228
|
+
declare function analyzeInteractiveTools(html: string, url: string): {
|
|
1229
|
+
issues: AuditIssue[];
|
|
1230
|
+
data: InteractiveToolsData;
|
|
1231
|
+
};
|
|
1232
|
+
|
|
1233
|
+
type FunnelStage = 'tofu' | 'mofu' | 'bofu' | 'mixed';
|
|
1234
|
+
interface FunnelIntentData {
|
|
1235
|
+
detectedStage: FunnelStage;
|
|
1236
|
+
confidence: number;
|
|
1237
|
+
signals: {
|
|
1238
|
+
tofu: string[];
|
|
1239
|
+
mofu: string[];
|
|
1240
|
+
bofu: string[];
|
|
1241
|
+
};
|
|
1242
|
+
metrics: {
|
|
1243
|
+
informationalScore: number;
|
|
1244
|
+
considerationScore: number;
|
|
1245
|
+
conversionScore: number;
|
|
1246
|
+
};
|
|
1247
|
+
pageType: string;
|
|
1248
|
+
aiOverviewRisk: 'high' | 'medium' | 'low';
|
|
1249
|
+
recommendations: string[];
|
|
1250
|
+
}
|
|
1251
|
+
/**
|
|
1252
|
+
* Main function: Analyze search funnel intent
|
|
1253
|
+
*/
|
|
1254
|
+
declare function analyzeFunnelIntent(html: string, url: string): {
|
|
1255
|
+
issues: AuditIssue[];
|
|
1256
|
+
data: FunnelIntentData;
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
interface NavBoostSignalsData {
|
|
1260
|
+
clickOptimization: {
|
|
1261
|
+
hasClearTitle: boolean;
|
|
1262
|
+
hasCompellingMetaDesc: boolean;
|
|
1263
|
+
titleTruncated: boolean;
|
|
1264
|
+
metaDescTruncated: boolean;
|
|
1265
|
+
estimatedCTRPotential: 'high' | 'medium' | 'low';
|
|
1266
|
+
};
|
|
1267
|
+
engagementSignals: {
|
|
1268
|
+
hasTableOfContents: boolean;
|
|
1269
|
+
hasJumpLinks: boolean;
|
|
1270
|
+
estimatedScrollDepth: 'deep' | 'medium' | 'shallow';
|
|
1271
|
+
hasProgressIndicator: boolean;
|
|
1272
|
+
hasStickyNavigation: boolean;
|
|
1273
|
+
contentSections: number;
|
|
1274
|
+
};
|
|
1275
|
+
bounceRiskFactors: {
|
|
1276
|
+
hasAboveFoldContent: boolean;
|
|
1277
|
+
hasSlowLoadingIndicators: boolean;
|
|
1278
|
+
hasPopupRisk: boolean;
|
|
1279
|
+
hasIntrusiveAds: boolean;
|
|
1280
|
+
contentMatchesTitle: boolean;
|
|
1281
|
+
hasImmediateValue: boolean;
|
|
1282
|
+
};
|
|
1283
|
+
dwellTimeFactors: {
|
|
1284
|
+
estimatedReadTime: number;
|
|
1285
|
+
hasVideo: boolean;
|
|
1286
|
+
hasInteractiveElements: boolean;
|
|
1287
|
+
contentDepth: 'comprehensive' | 'moderate' | 'thin';
|
|
1288
|
+
hasRelatedContent: boolean;
|
|
1289
|
+
};
|
|
1290
|
+
overallNavBoostScore: number;
|
|
1291
|
+
recommendations: string[];
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Main function: Analyze NavBoost optimization signals
|
|
1295
|
+
*/
|
|
1296
|
+
declare function analyzeNavBoostSignals(html: string, url: string): {
|
|
1297
|
+
issues: AuditIssue[];
|
|
1298
|
+
data: NavBoostSignalsData;
|
|
1299
|
+
};
|
|
1300
|
+
|
|
1301
|
+
interface EntitySEOData {
|
|
1302
|
+
entitySignals: {
|
|
1303
|
+
hasOrganizationSchema: boolean;
|
|
1304
|
+
hasPersonSchema: boolean;
|
|
1305
|
+
hasProductSchema: boolean;
|
|
1306
|
+
hasSameAsReferences: boolean;
|
|
1307
|
+
sameAsUrls: string[];
|
|
1308
|
+
hasMainEntityOfPage: boolean;
|
|
1309
|
+
hasAboutReference: boolean;
|
|
1310
|
+
};
|
|
1311
|
+
entityClarity: {
|
|
1312
|
+
primaryEntityType: string | null;
|
|
1313
|
+
entityNameConsistency: boolean;
|
|
1314
|
+
hasEntityDefinition: boolean;
|
|
1315
|
+
hasWikipediaStyleIntro: boolean;
|
|
1316
|
+
entityMentionCount: number;
|
|
1317
|
+
};
|
|
1318
|
+
topicalCoverage: {
|
|
1319
|
+
hasRelatedEntities: boolean;
|
|
1320
|
+
relatedEntityCount: number;
|
|
1321
|
+
hasEntityRelationships: boolean;
|
|
1322
|
+
topicalDepthScore: number;
|
|
1323
|
+
};
|
|
1324
|
+
knowledgePanelSignals: {
|
|
1325
|
+
hasCompanyInfo: boolean;
|
|
1326
|
+
hasFounderInfo: boolean;
|
|
1327
|
+
hasHeadquarters: boolean;
|
|
1328
|
+
hasIndustryMention: boolean;
|
|
1329
|
+
hasDateFounded: boolean;
|
|
1330
|
+
};
|
|
1331
|
+
entitySEOScore: number;
|
|
1332
|
+
recommendations: string[];
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Main function: Analyze Entity SEO optimization
|
|
1336
|
+
*/
|
|
1337
|
+
declare function analyzeEntitySEO(html: string, url: string): {
|
|
1338
|
+
issues: AuditIssue[];
|
|
1339
|
+
data: EntitySEOData;
|
|
1340
|
+
};
|
|
1341
|
+
|
|
1342
|
+
interface FreshnessSignalsData {
|
|
1343
|
+
dateSignals: {
|
|
1344
|
+
hasDatePublished: boolean;
|
|
1345
|
+
hasDateModified: boolean;
|
|
1346
|
+
hasSchemaDatePublished: boolean;
|
|
1347
|
+
hasSchemaDateModified: boolean;
|
|
1348
|
+
visibleDateOnPage: string | null;
|
|
1349
|
+
schemaDatePublished: string | null;
|
|
1350
|
+
schemaDateModified: string | null;
|
|
1351
|
+
daysSincePublished: number | null;
|
|
1352
|
+
daysSinceModified: number | null;
|
|
1353
|
+
};
|
|
1354
|
+
freshnessIndicators: {
|
|
1355
|
+
hasCurrentYearMention: boolean;
|
|
1356
|
+
hasRecentDateReferences: boolean;
|
|
1357
|
+
hasUpdateNotice: boolean;
|
|
1358
|
+
hasChangeLog: boolean;
|
|
1359
|
+
hasVersionNumber: boolean;
|
|
1360
|
+
contentFreshnessSignal: 'fresh' | 'dated' | 'evergreen' | 'unknown';
|
|
1361
|
+
};
|
|
1362
|
+
qdfRelevance: {
|
|
1363
|
+
isLikelyQDFTopic: boolean;
|
|
1364
|
+
qdfIndicators: string[];
|
|
1365
|
+
updateFrequencyRecommendation: string;
|
|
1366
|
+
};
|
|
1367
|
+
aiCitationOptimization: {
|
|
1368
|
+
hasLastUpdatedMeta: boolean;
|
|
1369
|
+
hasClearDateFormat: boolean;
|
|
1370
|
+
freshnessSchemaComplete: boolean;
|
|
1371
|
+
aiCitationReadiness: 'high' | 'medium' | 'low';
|
|
1372
|
+
};
|
|
1373
|
+
freshnessScore: number;
|
|
1374
|
+
recommendations: string[];
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Main function: Analyze freshness signals
|
|
1378
|
+
*/
|
|
1379
|
+
declare function analyzeFreshnessSignals(html: string, url: string): {
|
|
1380
|
+
issues: AuditIssue[];
|
|
1381
|
+
data: FreshnessSignalsData;
|
|
1382
|
+
};
|
|
1383
|
+
|
|
1384
|
+
/**
|
|
1385
|
+
* URL Safety Check (Local Hash Database)
|
|
1386
|
+
*
|
|
1387
|
+
* Implements a Google Safe Browsing-style architecture:
|
|
1388
|
+
* 1. Maintains a local database of hash prefixes
|
|
1389
|
+
* 2. All URL checks happen locally against the hash database
|
|
1390
|
+
* 3. Database can be updated from open threat feeds (URLhaus, etc.)
|
|
1391
|
+
* 4. No external API calls during audit - fully offline capable
|
|
1392
|
+
*
|
|
1393
|
+
* Hash Database Format:
|
|
1394
|
+
* - URLs are canonicalized and hashed with FNV-1a
|
|
1395
|
+
* - 8-character hex prefixes are stored for space efficiency
|
|
1396
|
+
* - Prefixes are stored in a Set for O(1) lookup
|
|
1397
|
+
*
|
|
1398
|
+
* Data Sources for updates:
|
|
1399
|
+
* - URLhaus (abuse.ch) - https://urlhaus.abuse.ch/downloads/csv/
|
|
1400
|
+
* - PhishTank - https://data.phishtank.com/
|
|
1401
|
+
* - OpenPhish - https://openphish.com/
|
|
1402
|
+
*/
|
|
1403
|
+
|
|
1404
|
+
interface UrlSafetyData {
|
|
1405
|
+
checkedUrls: number;
|
|
1406
|
+
matchedUrls: UrlMatch[];
|
|
1407
|
+
databaseInfo: {
|
|
1408
|
+
prefixCount: number;
|
|
1409
|
+
lastUpdated?: string;
|
|
1410
|
+
sources: string[];
|
|
1411
|
+
};
|
|
1412
|
+
patternMatches: PatternMatch[];
|
|
1413
|
+
}
|
|
1414
|
+
interface UrlMatch {
|
|
1415
|
+
url: string;
|
|
1416
|
+
hashPrefix: string;
|
|
1417
|
+
matchType: 'exact' | 'domain' | 'pattern';
|
|
1418
|
+
threatType?: string;
|
|
1419
|
+
}
|
|
1420
|
+
interface PatternMatch {
|
|
1421
|
+
url: string;
|
|
1422
|
+
reasons: string[];
|
|
1423
|
+
riskLevel: 'low' | 'medium' | 'high';
|
|
1424
|
+
}
|
|
1425
|
+
/**
|
|
1426
|
+
* Analyze URL safety using local hash database and pattern matching
|
|
1427
|
+
*
|
|
1428
|
+
* This function performs two types of checks:
|
|
1429
|
+
* 1. Hash-based lookup against the local threat database
|
|
1430
|
+
* 2. Pattern-based detection for suspicious URL characteristics
|
|
1431
|
+
*
|
|
1432
|
+
* No external API calls are made - all checks are local.
|
|
1433
|
+
*/
|
|
1434
|
+
declare function analyzeUrlSafety(url: string, externalLinks?: string[]): {
|
|
1435
|
+
issues: AuditIssue[];
|
|
1436
|
+
data: UrlSafetyData;
|
|
1437
|
+
};
|
|
1438
|
+
/**
|
|
1439
|
+
* Export the threat database for external updates
|
|
1440
|
+
*/
|
|
1441
|
+
declare const urlSafetyDatabase: {
|
|
1442
|
+
/**
|
|
1443
|
+
* Load URLs from URLhaus CSV format
|
|
1444
|
+
*/
|
|
1445
|
+
loadFromUrlhausCsv: (csv: string) => number;
|
|
1446
|
+
/**
|
|
1447
|
+
* Add URLs to the blocklist
|
|
1448
|
+
*/
|
|
1449
|
+
addUrls: (urls: string[]) => number;
|
|
1450
|
+
/**
|
|
1451
|
+
* Add domains to the blocklist
|
|
1452
|
+
*/
|
|
1453
|
+
addDomains: (domains: string[]) => number;
|
|
1454
|
+
/**
|
|
1455
|
+
* Bulk load hash prefixes (for Supabase integration)
|
|
1456
|
+
* Call this with data from: SELECT hash_prefix, hash_type FROM threat_hashes WHERE is_active = TRUE
|
|
1457
|
+
*/
|
|
1458
|
+
loadHashPrefixes: (hashes: Array<{
|
|
1459
|
+
hash_prefix: string;
|
|
1460
|
+
hash_type: "url" | "domain";
|
|
1461
|
+
}>) => number;
|
|
1462
|
+
/**
|
|
1463
|
+
* Clear all hashes (useful before reloading from fresh data)
|
|
1464
|
+
*/
|
|
1465
|
+
clear: () => void;
|
|
1466
|
+
/**
|
|
1467
|
+
* Check if database has been populated with threat data
|
|
1468
|
+
*/
|
|
1469
|
+
isPopulated: () => boolean;
|
|
1470
|
+
/**
|
|
1471
|
+
* Get database statistics
|
|
1472
|
+
*/
|
|
1473
|
+
getStats: () => {
|
|
1474
|
+
prefixCount: number;
|
|
1475
|
+
lastUpdated: string;
|
|
1476
|
+
sources: string[];
|
|
1477
|
+
};
|
|
1478
|
+
};
|
|
1479
|
+
|
|
1480
|
+
/**
|
|
1481
|
+
* Link Crawler Module
|
|
1482
|
+
*
|
|
1483
|
+
* Discovers pages from a website by following internal links from the homepage.
|
|
1484
|
+
* Prioritizes important pages like /pricing, /about, /features, etc.
|
|
1485
|
+
*/
|
|
1486
|
+
interface DiscoveredPage {
|
|
1487
|
+
url: string;
|
|
1488
|
+
source: 'homepage' | 'sitemap' | 'internal-link';
|
|
1489
|
+
priority: number;
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Discover pages from HTML content
|
|
1493
|
+
*
|
|
1494
|
+
* @param baseUrl - The base URL of the site
|
|
1495
|
+
* @param html - The HTML content of the homepage
|
|
1496
|
+
* @param maxPages - Maximum number of pages to return
|
|
1497
|
+
* @returns Array of discovered pages sorted by priority
|
|
1498
|
+
*/
|
|
1499
|
+
declare function discoverPagesFromLinks(baseUrl: string, html: string, maxPages?: number): DiscoveredPage[];
|
|
1500
|
+
/**
|
|
1501
|
+
* Parse sitemap XML to extract URLs
|
|
1502
|
+
*/
|
|
1503
|
+
declare function parseSitemap(xml: string, baseUrl: string): DiscoveredPage[];
|
|
1504
|
+
/**
|
|
1505
|
+
* Merge pages from multiple sources, deduplicating by URL
|
|
1506
|
+
*/
|
|
1507
|
+
declare function mergePages(...pageSets: DiscoveredPage[][]): DiscoveredPage[];
|
|
1508
|
+
|
|
1509
|
+
/**
|
|
1510
|
+
* Route Discovery Module
|
|
1511
|
+
*
|
|
1512
|
+
* Discovers routes from repository files based on framework-specific patterns.
|
|
1513
|
+
* Supports: Next.js (App/Pages), Astro, React Router, Vue Router, SvelteKit
|
|
1514
|
+
*/
|
|
1515
|
+
interface RouteInfo {
|
|
1516
|
+
path: string;
|
|
1517
|
+
type: 'static' | 'dynamic';
|
|
1518
|
+
sourceFile: string;
|
|
1519
|
+
}
|
|
1520
|
+
type Framework$2 = 'nextjs' | 'astro' | 'react' | 'react-vite' | 'vue' | 'sveltekit' | 'unknown';
|
|
1521
|
+
/**
|
|
1522
|
+
* Discover routes based on framework
|
|
1523
|
+
*/
|
|
1524
|
+
declare function discoverRoutesFromRepo(files: string[], framework: Framework$2, fetchFile: (path: string) => Promise<string | null>): Promise<RouteInfo[]>;
|
|
1525
|
+
/**
|
|
1526
|
+
* Convert static routes to full URLs
|
|
1527
|
+
*/
|
|
1528
|
+
declare function routesToUrls(routes: RouteInfo[], baseUrl: string, maxUrls?: number): string[];
|
|
1529
|
+
|
|
1530
|
+
/**
|
|
1531
|
+
* Social Meta Tag Fix Generator
|
|
1532
|
+
*
|
|
1533
|
+
* Generates code fixes for missing Twitter Cards, Open Graph tags, and other social meta.
|
|
1534
|
+
* Supports multiple frameworks: HTML, React, Next.js, Astro, Remix, SvelteKit.
|
|
1535
|
+
*/
|
|
1536
|
+
|
|
1537
|
+
interface SocialMetaFix {
|
|
1538
|
+
issueCode: string;
|
|
1539
|
+
filePath: string;
|
|
1540
|
+
framework: string;
|
|
1541
|
+
before?: string;
|
|
1542
|
+
after: string;
|
|
1543
|
+
explanation: string;
|
|
1544
|
+
}
|
|
1545
|
+
interface SocialMetaConfig {
|
|
1546
|
+
title: string;
|
|
1547
|
+
description: string;
|
|
1548
|
+
image: string;
|
|
1549
|
+
url: string;
|
|
1550
|
+
siteName?: string;
|
|
1551
|
+
twitterSite?: string;
|
|
1552
|
+
twitterCreator?: string;
|
|
1553
|
+
type?: 'website' | 'article' | 'product';
|
|
1554
|
+
locale?: string;
|
|
1555
|
+
}
|
|
1556
|
+
type Framework$1 = 'html' | 'react' | 'nextjs-app' | 'nextjs-pages' | 'astro' | 'remix' | 'sveltekit' | 'vite-react';
|
|
1557
|
+
/**
|
|
1558
|
+
* Generates complete social meta tags for HTML
|
|
1559
|
+
*/
|
|
1560
|
+
declare function generateHTMLSocialMeta(config: SocialMetaConfig): string;
|
|
1561
|
+
/**
|
|
1562
|
+
* Generates React Helmet / react-helmet-async component
|
|
1563
|
+
*/
|
|
1564
|
+
declare function generateReactHelmetSocialMeta(config: SocialMetaConfig): string;
|
|
1565
|
+
/**
|
|
1566
|
+
* Generates Next.js App Router metadata export
|
|
1567
|
+
*/
|
|
1568
|
+
declare function generateNextAppMetadata(config: SocialMetaConfig): string;
|
|
1569
|
+
/**
|
|
1570
|
+
* Generates Next.js Pages Router Head component
|
|
1571
|
+
*/
|
|
1572
|
+
declare function generateNextPagesHead(config: SocialMetaConfig): string;
|
|
1573
|
+
/**
|
|
1574
|
+
* Generates Astro frontmatter and BaseHead usage
|
|
1575
|
+
*/
|
|
1576
|
+
declare function generateAstroMeta(config: SocialMetaConfig): string;
|
|
1577
|
+
/**
|
|
1578
|
+
* Generates Remix meta function
|
|
1579
|
+
*/
|
|
1580
|
+
declare function generateRemixMeta(config: SocialMetaConfig): string;
|
|
1581
|
+
/**
|
|
1582
|
+
* Generates SvelteKit +page.ts and svelte:head usage
|
|
1583
|
+
*/
|
|
1584
|
+
declare function generateSvelteKitMeta(config: SocialMetaConfig): string;
|
|
1585
|
+
/**
|
|
1586
|
+
* Generates fix for a specific missing social meta tag
|
|
1587
|
+
*/
|
|
1588
|
+
declare function generateSocialMetaFix(issueCode: string, framework: Framework$1, existingData: SocialMetaData, pageData: {
|
|
1589
|
+
title?: string;
|
|
1590
|
+
description?: string;
|
|
1591
|
+
url: string;
|
|
1592
|
+
}): SocialMetaFix;
|
|
1593
|
+
/**
|
|
1594
|
+
* Generates complete social meta setup for a project
|
|
1595
|
+
*/
|
|
1596
|
+
declare function generateCompleteSocialMetaSetup(framework: Framework$1, config: SocialMetaConfig): {
|
|
1597
|
+
filePath: string;
|
|
1598
|
+
content: string;
|
|
1599
|
+
explanation: string;
|
|
1600
|
+
};
|
|
1601
|
+
/**
|
|
1602
|
+
* OG Image recommendations based on platform requirements
|
|
1603
|
+
*/
|
|
1604
|
+
declare const OG_IMAGE_SPECS: {
|
|
1605
|
+
recommended: {
|
|
1606
|
+
width: number;
|
|
1607
|
+
height: number;
|
|
1608
|
+
aspectRatio: string;
|
|
1609
|
+
format: string[];
|
|
1610
|
+
maxSize: string;
|
|
1611
|
+
};
|
|
1612
|
+
twitter: {
|
|
1613
|
+
summary: {
|
|
1614
|
+
width: number;
|
|
1615
|
+
height: number;
|
|
1616
|
+
};
|
|
1617
|
+
summary_large_image: {
|
|
1618
|
+
width: number;
|
|
1619
|
+
height: number;
|
|
1620
|
+
};
|
|
1621
|
+
};
|
|
1622
|
+
facebook: {
|
|
1623
|
+
minimum: {
|
|
1624
|
+
width: number;
|
|
1625
|
+
height: number;
|
|
1626
|
+
};
|
|
1627
|
+
recommended: {
|
|
1628
|
+
width: number;
|
|
1629
|
+
height: number;
|
|
1630
|
+
};
|
|
1631
|
+
};
|
|
1632
|
+
linkedin: {
|
|
1633
|
+
recommended: {
|
|
1634
|
+
width: number;
|
|
1635
|
+
height: number;
|
|
1636
|
+
};
|
|
1637
|
+
};
|
|
1638
|
+
};
|
|
1639
|
+
|
|
1640
|
+
/**
|
|
1641
|
+
* Fix generators for SEO issues
|
|
1642
|
+
*
|
|
1643
|
+
* These modules generate framework-specific code to fix SEO issues
|
|
1644
|
+
* detected during audits.
|
|
1645
|
+
*/
|
|
1646
|
+
|
|
1647
|
+
interface FixFile {
|
|
1648
|
+
path: string;
|
|
1649
|
+
content: string;
|
|
1650
|
+
}
|
|
1651
|
+
interface FixResult {
|
|
1652
|
+
category: string;
|
|
1653
|
+
issues: string[];
|
|
1654
|
+
files: FixFile[];
|
|
1655
|
+
}
|
|
1656
|
+
/**
|
|
1657
|
+
* Generates all fixes for issues found in an audit report
|
|
1658
|
+
*/
|
|
1659
|
+
declare function generateAllFixes(report: AuditReport): FixResult[];
|
|
1660
|
+
|
|
1661
|
+
/**
|
|
1662
|
+
* Audit Runner
|
|
1663
|
+
*
|
|
1664
|
+
* High-level API for running SEO audits with automatic fix generation
|
|
1665
|
+
* and PR creation. Orchestrates the audit engine, fix generators, and
|
|
1666
|
+
* git helpers.
|
|
1667
|
+
*/
|
|
1668
|
+
|
|
1669
|
+
interface AuditRunnerOptions extends Partial<AuditOptions> {
|
|
1670
|
+
url: string;
|
|
1671
|
+
generateFixes?: boolean;
|
|
1672
|
+
previousScore?: number;
|
|
1673
|
+
}
|
|
1674
|
+
interface AuditRunnerResult {
|
|
1675
|
+
report: AuditReport;
|
|
1676
|
+
fixes: FixResult[];
|
|
1677
|
+
score: number;
|
|
1678
|
+
previousScore?: number;
|
|
1679
|
+
}
|
|
1680
|
+
interface CreateAuditPROptions {
|
|
1681
|
+
baseBranch: string;
|
|
1682
|
+
headBranch: string;
|
|
1683
|
+
dryRun?: boolean;
|
|
1684
|
+
reviewers?: string[];
|
|
1685
|
+
assignees?: string[];
|
|
1686
|
+
draft?: boolean;
|
|
1687
|
+
}
|
|
1688
|
+
interface AuditPRResult {
|
|
1689
|
+
success: boolean;
|
|
1690
|
+
prUrl?: string;
|
|
1691
|
+
prNumber?: number;
|
|
1692
|
+
error?: string;
|
|
1693
|
+
dryRun?: boolean;
|
|
1694
|
+
}
|
|
1695
|
+
/**
|
|
1696
|
+
* Runs a full SEO audit and generates fixes for identified issues
|
|
1697
|
+
*/
|
|
1698
|
+
declare function runAuditWithFixes(options: AuditRunnerOptions): Promise<AuditRunnerResult>;
|
|
1699
|
+
/**
|
|
1700
|
+
* Creates a pull request with audit fixes
|
|
1701
|
+
*/
|
|
1702
|
+
declare function createAuditPR(result: AuditRunnerResult, options: CreateAuditPROptions): Promise<AuditPRResult>;
|
|
1703
|
+
|
|
1704
|
+
interface SiteProfile {
|
|
1705
|
+
domain: string;
|
|
1706
|
+
domainAge: 'new' | 'established' | 'authority';
|
|
1707
|
+
backlinkCount: 'none' | 'few' | 'some' | 'many';
|
|
1708
|
+
businessGoal: 'signups' | 'purchases' | 'leads' | 'awareness';
|
|
1709
|
+
contentCapacity: 'low' | 'medium' | 'high';
|
|
1710
|
+
targetGeo: string;
|
|
1711
|
+
}
|
|
1712
|
+
interface KeywordData {
|
|
1713
|
+
keyword: string;
|
|
1714
|
+
searchVolume: number;
|
|
1715
|
+
keywordDifficulty: number;
|
|
1716
|
+
cpc?: number;
|
|
1717
|
+
trafficPotential?: number;
|
|
1718
|
+
intent?: 'informational' | 'commercial' | 'transactional' | 'navigational';
|
|
1719
|
+
trend?: 'up' | 'down' | 'stable';
|
|
1720
|
+
source: 'gsc' | 'dataforseo' | 'autocomplete' | 'manual' | 'competitor';
|
|
1721
|
+
}
|
|
1722
|
+
interface KeywordOpportunity$1 extends KeywordData {
|
|
1723
|
+
priorityScore: number;
|
|
1724
|
+
category: 'quick-win' | 'medium-term' | 'long-term';
|
|
1725
|
+
suggestedAction: KeywordAction;
|
|
1726
|
+
currentRanking?: number;
|
|
1727
|
+
impressions?: number;
|
|
1728
|
+
clicks?: number;
|
|
1729
|
+
ctr?: number;
|
|
1730
|
+
}
|
|
1731
|
+
interface KeywordAction {
|
|
1732
|
+
type: 'add-to-title' | 'add-to-h1' | 'add-to-meta' | 'create-content' | 'optimize-existing';
|
|
1733
|
+
description: string;
|
|
1734
|
+
targetElement?: string;
|
|
1735
|
+
currentValue?: string;
|
|
1736
|
+
suggestedValue?: string;
|
|
1737
|
+
file?: string;
|
|
1738
|
+
line?: number;
|
|
1739
|
+
}
|
|
1740
|
+
interface KeywordResearchResult {
|
|
1741
|
+
siteProfile: SiteProfile;
|
|
1742
|
+
keywords: KeywordOpportunity$1[];
|
|
1743
|
+
quickWins: KeywordOpportunity$1[];
|
|
1744
|
+
mediumTerm: KeywordOpportunity$1[];
|
|
1745
|
+
longTerm: KeywordOpportunity$1[];
|
|
1746
|
+
recommendations: string[];
|
|
1747
|
+
maxKdThreshold: number;
|
|
1748
|
+
}
|
|
1749
|
+
interface GSCQueryData {
|
|
1750
|
+
query: string;
|
|
1751
|
+
clicks: number;
|
|
1752
|
+
impressions: number;
|
|
1753
|
+
ctr: number;
|
|
1754
|
+
position: number;
|
|
1755
|
+
}
|
|
1756
|
+
declare const SITE_PROFILE_QUESTIONS: readonly [{
|
|
1757
|
+
readonly id: "domainAge";
|
|
1758
|
+
readonly question: "How old is your domain?";
|
|
1759
|
+
readonly options: readonly [{
|
|
1760
|
+
readonly value: "new";
|
|
1761
|
+
readonly label: "New (< 6 months)";
|
|
1762
|
+
readonly description: "Just started, building from scratch";
|
|
1763
|
+
}, {
|
|
1764
|
+
readonly value: "established";
|
|
1765
|
+
readonly label: "Established (6 months - 2 years)";
|
|
1766
|
+
readonly description: "Has some history and content";
|
|
1767
|
+
}, {
|
|
1768
|
+
readonly value: "authority";
|
|
1769
|
+
readonly label: "Authority (2+ years)";
|
|
1770
|
+
readonly description: "Well-established with backlinks";
|
|
1771
|
+
}];
|
|
1772
|
+
readonly impact: "Determines the maximum keyword difficulty you should target";
|
|
1773
|
+
}, {
|
|
1774
|
+
readonly id: "backlinkCount";
|
|
1775
|
+
readonly question: "How many backlinks does your site have?";
|
|
1776
|
+
readonly options: readonly [{
|
|
1777
|
+
readonly value: "none";
|
|
1778
|
+
readonly label: "None or very few (0-10)";
|
|
1779
|
+
readonly description: "Just starting link building";
|
|
1780
|
+
}, {
|
|
1781
|
+
readonly value: "few";
|
|
1782
|
+
readonly label: "Some (10-50)";
|
|
1783
|
+
readonly description: "A few quality backlinks";
|
|
1784
|
+
}, {
|
|
1785
|
+
readonly value: "some";
|
|
1786
|
+
readonly label: "Moderate (50-200)";
|
|
1787
|
+
readonly description: "Decent backlink profile";
|
|
1788
|
+
}, {
|
|
1789
|
+
readonly value: "many";
|
|
1790
|
+
readonly label: "Many (200+)";
|
|
1791
|
+
readonly description: "Strong backlink profile";
|
|
1792
|
+
}];
|
|
1793
|
+
readonly impact: "Affects your ability to rank for competitive keywords";
|
|
1794
|
+
}, {
|
|
1795
|
+
readonly id: "businessGoal";
|
|
1796
|
+
readonly question: "What is your primary business goal?";
|
|
1797
|
+
readonly options: readonly [{
|
|
1798
|
+
readonly value: "signups";
|
|
1799
|
+
readonly label: "Get signups/registrations";
|
|
1800
|
+
readonly description: "SaaS, apps, newsletters";
|
|
1801
|
+
}, {
|
|
1802
|
+
readonly value: "purchases";
|
|
1803
|
+
readonly label: "Generate purchases";
|
|
1804
|
+
readonly description: "E-commerce, products";
|
|
1805
|
+
}, {
|
|
1806
|
+
readonly value: "leads";
|
|
1807
|
+
readonly label: "Capture leads";
|
|
1808
|
+
readonly description: "B2B, services, consulting";
|
|
1809
|
+
}, {
|
|
1810
|
+
readonly value: "awareness";
|
|
1811
|
+
readonly label: "Build brand awareness";
|
|
1812
|
+
readonly description: "Content, community, thought leadership";
|
|
1813
|
+
}];
|
|
1814
|
+
readonly impact: "Weights commercial vs informational keywords";
|
|
1815
|
+
}, {
|
|
1816
|
+
readonly id: "contentCapacity";
|
|
1817
|
+
readonly question: "How much content can you produce monthly?";
|
|
1818
|
+
readonly options: readonly [{
|
|
1819
|
+
readonly value: "low";
|
|
1820
|
+
readonly label: "1-2 pages/month";
|
|
1821
|
+
readonly description: "Limited time or resources";
|
|
1822
|
+
}, {
|
|
1823
|
+
readonly value: "medium";
|
|
1824
|
+
readonly label: "3-5 pages/month";
|
|
1825
|
+
readonly description: "Moderate content output";
|
|
1826
|
+
}, {
|
|
1827
|
+
readonly value: "high";
|
|
1828
|
+
readonly label: "5+ pages/month";
|
|
1829
|
+
readonly description: "Dedicated content team";
|
|
1830
|
+
}];
|
|
1831
|
+
readonly impact: "Determines how many keywords to suggest";
|
|
1832
|
+
}, {
|
|
1833
|
+
readonly id: "targetGeo";
|
|
1834
|
+
readonly question: "Where are your target customers?";
|
|
1835
|
+
readonly options: readonly [{
|
|
1836
|
+
readonly value: "us";
|
|
1837
|
+
readonly label: "United States";
|
|
1838
|
+
readonly description: "Primary US audience";
|
|
1839
|
+
}, {
|
|
1840
|
+
readonly value: "uk";
|
|
1841
|
+
readonly label: "United Kingdom";
|
|
1842
|
+
readonly description: "Primary UK audience";
|
|
1843
|
+
}, {
|
|
1844
|
+
readonly value: "global";
|
|
1845
|
+
readonly label: "Global";
|
|
1846
|
+
readonly description: "Worldwide audience";
|
|
1847
|
+
}, {
|
|
1848
|
+
readonly value: "other";
|
|
1849
|
+
readonly label: "Other";
|
|
1850
|
+
readonly description: "Specific country or region";
|
|
1851
|
+
}];
|
|
1852
|
+
readonly impact: "Determines which search volume data to use";
|
|
1853
|
+
}];
|
|
1854
|
+
declare function getMaxKdThreshold(profile: SiteProfile): number;
|
|
1855
|
+
declare const PRIORITY_WEIGHTS: {
|
|
1856
|
+
businessValue: number;
|
|
1857
|
+
difficulty: number;
|
|
1858
|
+
trafficPotential: number;
|
|
1859
|
+
};
|
|
1860
|
+
|
|
1861
|
+
interface DataForSEOCredentials {
|
|
1862
|
+
login: string;
|
|
1863
|
+
password: string;
|
|
1864
|
+
}
|
|
1865
|
+
declare function getKeywordData(keywords: string[], credentials: DataForSEOCredentials, location?: number): Promise<KeywordData[]>;
|
|
1866
|
+
declare function getKeywordSuggestions(seedKeyword: string, credentials: DataForSEOCredentials, location?: number, limit?: number): Promise<KeywordData[]>;
|
|
1867
|
+
declare function getRelatedKeywords(seedKeyword: string, credentials: DataForSEOCredentials, location?: number, limit?: number): Promise<KeywordData[]>;
|
|
1868
|
+
declare const LOCATION_CODES: {
|
|
1869
|
+
US: number;
|
|
1870
|
+
UK: number;
|
|
1871
|
+
CA: number;
|
|
1872
|
+
AU: number;
|
|
1873
|
+
DE: number;
|
|
1874
|
+
FR: number;
|
|
1875
|
+
ES: number;
|
|
1876
|
+
IT: number;
|
|
1877
|
+
BR: number;
|
|
1878
|
+
IN: number;
|
|
1879
|
+
JP: number;
|
|
1880
|
+
};
|
|
1881
|
+
declare function checkBalance(credentials: DataForSEOCredentials): Promise<number>;
|
|
1882
|
+
|
|
1883
|
+
interface KeywordResearchOptions {
|
|
1884
|
+
seedKeywords: string[];
|
|
1885
|
+
siteProfile: SiteProfile;
|
|
1886
|
+
url?: string;
|
|
1887
|
+
dataForSEOCredentials?: DataForSEOCredentials;
|
|
1888
|
+
maxKeywords?: number;
|
|
1889
|
+
}
|
|
1890
|
+
interface PageMeta {
|
|
1891
|
+
title?: string;
|
|
1892
|
+
description?: string;
|
|
1893
|
+
h1?: string;
|
|
1894
|
+
url: string;
|
|
1895
|
+
}
|
|
1896
|
+
declare function runKeywordResearch(options: KeywordResearchOptions): Promise<KeywordResearchResult>;
|
|
1897
|
+
declare function formatKeywordReport(result: KeywordResearchResult): string;
|
|
1898
|
+
declare function extractSeedKeywords(url: string): Promise<string[]>;
|
|
1899
|
+
|
|
1900
|
+
/**
|
|
1901
|
+
* Site Crawler for Keyword Research
|
|
1902
|
+
*
|
|
1903
|
+
* Crawls an entire site to collect text content for AI analysis.
|
|
1904
|
+
* Used to understand what the site does and generate relevant keywords.
|
|
1905
|
+
*/
|
|
1906
|
+
interface CrawledPage {
|
|
1907
|
+
url: string;
|
|
1908
|
+
title: string;
|
|
1909
|
+
description: string;
|
|
1910
|
+
h1: string;
|
|
1911
|
+
h2s: string[];
|
|
1912
|
+
mainContent: string;
|
|
1913
|
+
wordCount: number;
|
|
1914
|
+
internalLinks: string[];
|
|
1915
|
+
isProductPage: boolean;
|
|
1916
|
+
isPricingPage: boolean;
|
|
1917
|
+
isBlogPost: boolean;
|
|
1918
|
+
isFeaturePage: boolean;
|
|
1919
|
+
}
|
|
1920
|
+
interface SiteCrawlResult {
|
|
1921
|
+
domain: string;
|
|
1922
|
+
pages: CrawledPage[];
|
|
1923
|
+
aggregatedContent: string;
|
|
1924
|
+
totalWordCount: number;
|
|
1925
|
+
uniqueHeadings: string[];
|
|
1926
|
+
detectedPageTypes: {
|
|
1927
|
+
product: number;
|
|
1928
|
+
pricing: number;
|
|
1929
|
+
blog: number;
|
|
1930
|
+
feature: number;
|
|
1931
|
+
other: number;
|
|
1932
|
+
};
|
|
1933
|
+
crawlStats: {
|
|
1934
|
+
attempted: number;
|
|
1935
|
+
succeeded: number;
|
|
1936
|
+
failed: number;
|
|
1937
|
+
duration: number;
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
/**
|
|
1941
|
+
* Crawl an entire site to collect text content
|
|
1942
|
+
*/
|
|
1943
|
+
declare function crawlSite(startUrl: string, options?: {
|
|
1944
|
+
maxPages?: number;
|
|
1945
|
+
maxDepth?: number;
|
|
1946
|
+
timeout?: number;
|
|
1947
|
+
}): Promise<SiteCrawlResult>;
|
|
1948
|
+
/**
|
|
1949
|
+
* Extract key phrases from crawled content
|
|
1950
|
+
*/
|
|
1951
|
+
declare function extractKeyPhrases(crawlResult: SiteCrawlResult): string[];
|
|
1952
|
+
|
|
1953
|
+
/**
|
|
1954
|
+
* AI-Powered Site Summarizer
|
|
1955
|
+
*
|
|
1956
|
+
* Uses OpenAI to understand what a site does from crawled content.
|
|
1957
|
+
* Extracts: product, audience, features, industry, positioning.
|
|
1958
|
+
*/
|
|
1959
|
+
|
|
1960
|
+
interface SiteSummary {
|
|
1961
|
+
/** Primary product/service name */
|
|
1962
|
+
productName: string;
|
|
1963
|
+
/** What the product does (1-2 sentences) */
|
|
1964
|
+
productDescription: string;
|
|
1965
|
+
/** Target audience description */
|
|
1966
|
+
targetAudience: string;
|
|
1967
|
+
/** Key features/benefits (3-7 items) */
|
|
1968
|
+
keyFeatures: string[];
|
|
1969
|
+
/** Industry/category */
|
|
1970
|
+
industry: string;
|
|
1971
|
+
/** Business model */
|
|
1972
|
+
businessModel: 'saas' | 'ecommerce' | 'marketplace' | 'agency' | 'media' | 'other';
|
|
1973
|
+
/** Unique value proposition */
|
|
1974
|
+
valueProposition: string;
|
|
1975
|
+
/** Niche focus (if specific segment) */
|
|
1976
|
+
nicheFocus?: string;
|
|
1977
|
+
/** Pricing tier detected */
|
|
1978
|
+
pricingTier?: 'free' | 'freemium' | 'paid' | 'enterprise' | 'unknown';
|
|
1979
|
+
/** Geographic focus */
|
|
1980
|
+
geographicFocus?: string;
|
|
1981
|
+
/** Primary use cases */
|
|
1982
|
+
useCases: string[];
|
|
1983
|
+
/** Problems solved */
|
|
1984
|
+
problemsSolved: string[];
|
|
1985
|
+
/** Seed keyword suggestions */
|
|
1986
|
+
suggestedSeedKeywords: string[];
|
|
1987
|
+
/** Confidence score (0-1) */
|
|
1988
|
+
confidence: number;
|
|
1989
|
+
/** What we're uncertain about */
|
|
1990
|
+
uncertainties: string[];
|
|
1991
|
+
}
|
|
1992
|
+
interface SummarizerOptions {
|
|
1993
|
+
openaiApiKey: string;
|
|
1994
|
+
model?: string;
|
|
1995
|
+
maxTokens?: number;
|
|
1996
|
+
}
|
|
1997
|
+
/**
|
|
1998
|
+
* Summarize a site using AI
|
|
1999
|
+
*/
|
|
2000
|
+
declare function summarizeSite(crawlResult: SiteCrawlResult, options: SummarizerOptions): Promise<SiteSummary>;
|
|
2001
|
+
/**
|
|
2002
|
+
* Create a basic summary without AI (fallback)
|
|
2003
|
+
*/
|
|
2004
|
+
declare function createFallbackSummary(crawlResult: SiteCrawlResult): SiteSummary;
|
|
2005
|
+
/**
|
|
2006
|
+
* Enhance summary with competitive context
|
|
2007
|
+
*/
|
|
2008
|
+
declare function enhanceSummaryWithCompetitors(summary: SiteSummary, competitors: string[], options: SummarizerOptions): Promise<SiteSummary & {
|
|
2009
|
+
competitivePositioning: string;
|
|
2010
|
+
}>;
|
|
2011
|
+
/**
|
|
2012
|
+
* Generate questions to reduce uncertainty
|
|
2013
|
+
*/
|
|
2014
|
+
declare function generateUncertaintyQuestions(summary: SiteSummary): Array<{
|
|
2015
|
+
id: string;
|
|
2016
|
+
question: string;
|
|
2017
|
+
category: string;
|
|
2018
|
+
impact: number;
|
|
2019
|
+
options?: string[];
|
|
2020
|
+
}>;
|
|
2021
|
+
|
|
2022
|
+
/**
|
|
2023
|
+
* Advanced NLP Analysis for Keyword Research
|
|
2024
|
+
*
|
|
2025
|
+
* Uses data science techniques:
|
|
2026
|
+
* - TF-IDF for keyword extraction
|
|
2027
|
+
* - N-gram analysis for phrase detection
|
|
2028
|
+
* - BM25 scoring for relevance
|
|
2029
|
+
* - Keyword clustering using cosine similarity
|
|
2030
|
+
* - Embedding-based semantic grouping (OpenAI)
|
|
2031
|
+
* - Topic modeling (LDA-inspired)
|
|
2032
|
+
*/
|
|
2033
|
+
|
|
2034
|
+
interface TFIDFResult {
|
|
2035
|
+
term: string;
|
|
2036
|
+
tf: number;
|
|
2037
|
+
idf: number;
|
|
2038
|
+
tfidf: number;
|
|
2039
|
+
documentFrequency: number;
|
|
2040
|
+
}
|
|
2041
|
+
interface NGram {
|
|
2042
|
+
phrase: string;
|
|
2043
|
+
frequency: number;
|
|
2044
|
+
words: number;
|
|
2045
|
+
}
|
|
2046
|
+
interface KeywordCluster {
|
|
2047
|
+
id: number;
|
|
2048
|
+
name: string;
|
|
2049
|
+
keywords: string[];
|
|
2050
|
+
centroid?: number[];
|
|
2051
|
+
coherenceScore: number;
|
|
2052
|
+
}
|
|
2053
|
+
interface TopicModel {
|
|
2054
|
+
topics: Array<{
|
|
2055
|
+
id: number;
|
|
2056
|
+
name: string;
|
|
2057
|
+
keywords: string[];
|
|
2058
|
+
weight: number;
|
|
2059
|
+
}>;
|
|
2060
|
+
documentTopicDistribution: Array<{
|
|
2061
|
+
documentId: number;
|
|
2062
|
+
topicWeights: number[];
|
|
2063
|
+
}>;
|
|
2064
|
+
}
|
|
2065
|
+
interface NLPAnalysisResult {
|
|
2066
|
+
tfidfKeywords: TFIDFResult[];
|
|
2067
|
+
ngrams: {
|
|
2068
|
+
unigrams: NGram[];
|
|
2069
|
+
bigrams: NGram[];
|
|
2070
|
+
trigrams: NGram[];
|
|
2071
|
+
};
|
|
2072
|
+
clusters: KeywordCluster[];
|
|
2073
|
+
topics: TopicModel;
|
|
2074
|
+
entityPhrases: string[];
|
|
2075
|
+
semanticGroups: Array<{
|
|
2076
|
+
theme: string;
|
|
2077
|
+
keywords: string[];
|
|
2078
|
+
}>;
|
|
2079
|
+
}
|
|
2080
|
+
/**
|
|
2081
|
+
* Tokenize text into words
|
|
2082
|
+
*/
|
|
2083
|
+
declare function tokenize(text: string): string[];
|
|
2084
|
+
/**
|
|
2085
|
+
* Calculate TF-IDF for a corpus
|
|
2086
|
+
*/
|
|
2087
|
+
declare function calculateTFIDF$1(documents: string[]): TFIDFResult[];
|
|
2088
|
+
/**
|
|
2089
|
+
* Extract N-grams from text
|
|
2090
|
+
*/
|
|
2091
|
+
declare function extractNgrams(text: string, n: number, minFrequency?: number): NGram[];
|
|
2092
|
+
/**
|
|
2093
|
+
* BM25 scoring for keyword relevance
|
|
2094
|
+
* BM25 is a bag-of-words retrieval function that ranks documents by relevance
|
|
2095
|
+
*/
|
|
2096
|
+
declare function calculateBM25(documents: string[], query: string, k1?: number, b?: number): Array<{
|
|
2097
|
+
docIndex: number;
|
|
2098
|
+
score: number;
|
|
2099
|
+
}>;
|
|
2100
|
+
/**
|
|
2101
|
+
* Cluster keywords using embeddings
|
|
2102
|
+
*/
|
|
2103
|
+
declare function clusterKeywordsByEmbedding(keywords: string[], openai: OpenAI, numClusters?: number): Promise<KeywordCluster[]>;
|
|
2104
|
+
/**
|
|
2105
|
+
* Extract entity-like phrases (capitalized sequences, proper nouns)
|
|
2106
|
+
*/
|
|
2107
|
+
declare function extractEntityPhrases(text: string): string[];
|
|
2108
|
+
/**
|
|
2109
|
+
* Simplified LDA-inspired topic modeling
|
|
2110
|
+
* Groups keywords by co-occurrence patterns
|
|
2111
|
+
*/
|
|
2112
|
+
declare function extractTopics(documents: string[], numTopics?: number): TopicModel;
|
|
2113
|
+
/**
|
|
2114
|
+
* Run full NLP analysis on content
|
|
2115
|
+
*/
|
|
2116
|
+
declare function runNLPAnalysis(content: string | string[], options?: {
|
|
2117
|
+
openaiApiKey?: string;
|
|
2118
|
+
numClusters?: number;
|
|
2119
|
+
numTopics?: number;
|
|
2120
|
+
}): Promise<NLPAnalysisResult>;
|
|
2121
|
+
|
|
2122
|
+
/**
|
|
2123
|
+
* AI-Powered Keyword Research Engine
|
|
2124
|
+
*
|
|
2125
|
+
* Tiered access:
|
|
2126
|
+
* - FREE: Basic keyword extraction + score teaser
|
|
2127
|
+
* - PAID: Full NLP, clustering, embeddings, competitive analysis
|
|
2128
|
+
*
|
|
2129
|
+
* Based on Bhanu's "Engineering as Marketing" strategy:
|
|
2130
|
+
* 1. Find low KD keywords (< 10)
|
|
2131
|
+
* 2. High volume (1000+)
|
|
2132
|
+
* 3. Relevant to product
|
|
2133
|
+
* 4. Easy to build free tools for
|
|
2134
|
+
*/
|
|
2135
|
+
|
|
2136
|
+
type PlanTier = 'free' | 'solo' | 'pro' | 'agency';
|
|
2137
|
+
interface AIKeywordResearchOptions {
|
|
2138
|
+
url: string;
|
|
2139
|
+
tier: PlanTier;
|
|
2140
|
+
openaiApiKey?: string;
|
|
2141
|
+
maxPages?: number;
|
|
2142
|
+
userContext?: {
|
|
2143
|
+
productDescription?: string;
|
|
2144
|
+
targetAudience?: string;
|
|
2145
|
+
competitors?: string[];
|
|
2146
|
+
mainProblem?: string;
|
|
2147
|
+
differentiator?: string;
|
|
2148
|
+
};
|
|
2149
|
+
wizardResponses?: Array<{
|
|
2150
|
+
id: string;
|
|
2151
|
+
answer: string;
|
|
2152
|
+
}>;
|
|
2153
|
+
ciMode?: boolean;
|
|
2154
|
+
/** API keys for competitive search (optional but recommended) */
|
|
2155
|
+
competitiveSearchKeys?: {
|
|
2156
|
+
braveApiKey?: string;
|
|
2157
|
+
serperApiKey?: string;
|
|
2158
|
+
githubToken?: string;
|
|
2159
|
+
};
|
|
2160
|
+
/** Enable enhanced tool ideas with LLM judge (default: true for paid tiers) */
|
|
2161
|
+
enableEnhancedToolIdeas?: boolean;
|
|
2162
|
+
}
|
|
2163
|
+
interface FreeKeywordResult {
|
|
2164
|
+
tier: 'free';
|
|
2165
|
+
/** Basic keyword suggestions (limited) */
|
|
2166
|
+
keywords: Array<{
|
|
2167
|
+
keyword: string;
|
|
2168
|
+
estimatedVolume: 'low' | 'medium' | 'high';
|
|
2169
|
+
estimatedDifficulty: 'low' | 'medium' | 'high';
|
|
2170
|
+
relevance: number;
|
|
2171
|
+
}>;
|
|
2172
|
+
/** Overall keyword opportunity score (teaser) */
|
|
2173
|
+
opportunityScore: number;
|
|
2174
|
+
/** Teaser message */
|
|
2175
|
+
teaserMessage: string;
|
|
2176
|
+
/** What they'd get with upgrade */
|
|
2177
|
+
upgradeFeatures: string[];
|
|
2178
|
+
/** Basic site understanding */
|
|
2179
|
+
siteCategory: string;
|
|
2180
|
+
/** Detected keywords count */
|
|
2181
|
+
totalKeywordsFound: number;
|
|
2182
|
+
}
|
|
2183
|
+
interface PaidKeywordResult {
|
|
2184
|
+
tier: PlanTier;
|
|
2185
|
+
/** Site summary from AI */
|
|
2186
|
+
siteSummary: SiteSummary;
|
|
2187
|
+
/** Full keyword opportunities */
|
|
2188
|
+
opportunities: KeywordOpportunity[];
|
|
2189
|
+
/** NLP analysis results */
|
|
2190
|
+
nlpAnalysis: NLPAnalysisResult;
|
|
2191
|
+
/** Keyword clusters */
|
|
2192
|
+
clusters: Array<{
|
|
2193
|
+
name: string;
|
|
2194
|
+
keywords: string[];
|
|
2195
|
+
totalVolume: number;
|
|
2196
|
+
avgDifficulty: number;
|
|
2197
|
+
}>;
|
|
2198
|
+
/** Recommended free tools to build */
|
|
2199
|
+
freeToolIdeas: FreeToolIdea[];
|
|
2200
|
+
/** Competitive positioning */
|
|
2201
|
+
competitiveInsights?: CompetitiveInsight[];
|
|
2202
|
+
/** Uncertainty assessment */
|
|
2203
|
+
uncertainty: UncertaintyAssessment;
|
|
2204
|
+
/** Prioritized recommendations */
|
|
2205
|
+
recommendations: KeywordRecommendation[];
|
|
2206
|
+
}
|
|
2207
|
+
interface KeywordOpportunity {
|
|
2208
|
+
keyword: string;
|
|
2209
|
+
volume: number;
|
|
2210
|
+
difficulty: number;
|
|
2211
|
+
relevance: number;
|
|
2212
|
+
opportunityScore: number;
|
|
2213
|
+
intent: 'informational' | 'commercial' | 'transactional' | 'navigational';
|
|
2214
|
+
suggestedContentType: 'free-tool' | 'landing-page' | 'blog-post' | 'comparison' | 'guide';
|
|
2215
|
+
suggestedCTA: string;
|
|
2216
|
+
rationale: string;
|
|
2217
|
+
cluster?: string;
|
|
2218
|
+
}
|
|
2219
|
+
interface FreeToolIdea {
|
|
2220
|
+
keyword: string;
|
|
2221
|
+
toolName: string;
|
|
2222
|
+
toolDescription: string;
|
|
2223
|
+
estimatedEffort: 'low' | 'medium' | 'high';
|
|
2224
|
+
ctaConnection: string;
|
|
2225
|
+
volume: number;
|
|
2226
|
+
difficulty: number;
|
|
2227
|
+
priority: number;
|
|
2228
|
+
/** Enhanced fields from LLM judge */
|
|
2229
|
+
inputFormat?: string;
|
|
2230
|
+
outputFormat?: string;
|
|
2231
|
+
productTieIn?: string;
|
|
2232
|
+
ctaText?: string;
|
|
2233
|
+
deepLinkPattern?: string;
|
|
2234
|
+
competitors?: {
|
|
2235
|
+
hasFreeAlternative: boolean;
|
|
2236
|
+
topCompetitor?: string;
|
|
2237
|
+
ourAdvantage: string;
|
|
2238
|
+
};
|
|
2239
|
+
implementationHints?: {
|
|
2240
|
+
suggestedLibraries: string[];
|
|
2241
|
+
estimatedComplexity: 'trivial' | 'simple' | 'moderate' | 'complex';
|
|
2242
|
+
canUseExistingOSS: boolean;
|
|
2243
|
+
ossLibrary?: string;
|
|
2244
|
+
};
|
|
2245
|
+
feasibilityScore?: {
|
|
2246
|
+
feasibility: number;
|
|
2247
|
+
specificity: number;
|
|
2248
|
+
productFit: number;
|
|
2249
|
+
marketOpportunity: number;
|
|
2250
|
+
overallScore: number;
|
|
2251
|
+
passes: boolean;
|
|
2252
|
+
reasoning: string;
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
interface CompetitiveInsight {
|
|
2256
|
+
competitor: string;
|
|
2257
|
+
theirFocus: 'broad' | 'niche';
|
|
2258
|
+
ourAdvantage?: string;
|
|
2259
|
+
keywordsTheyRankFor: string[];
|
|
2260
|
+
keywordsWeCanTarget: string[];
|
|
2261
|
+
}
|
|
2262
|
+
interface UncertaintyAssessment {
|
|
2263
|
+
overallConfidence: number;
|
|
2264
|
+
siteUnderstanding: number;
|
|
2265
|
+
audienceClarity: number;
|
|
2266
|
+
competitiveClarity: number;
|
|
2267
|
+
canAutomate: boolean;
|
|
2268
|
+
questionsToAsk: Array<{
|
|
2269
|
+
id: string;
|
|
2270
|
+
question: string;
|
|
2271
|
+
impact: number;
|
|
2272
|
+
options?: string[];
|
|
2273
|
+
}>;
|
|
2274
|
+
explanation: string;
|
|
2275
|
+
}
|
|
2276
|
+
interface KeywordRecommendation {
|
|
2277
|
+
priority: number;
|
|
2278
|
+
keyword: string;
|
|
2279
|
+
action: 'build-tool' | 'create-page' | 'write-content' | 'skip' | 'needs-input';
|
|
2280
|
+
effort: 'low' | 'medium' | 'high';
|
|
2281
|
+
impact: 'low' | 'medium' | 'high';
|
|
2282
|
+
rationale: string;
|
|
2283
|
+
}
|
|
2284
|
+
/**
|
|
2285
|
+
* Run keyword research based on tier
|
|
2286
|
+
*/
|
|
2287
|
+
declare function runAIKeywordResearch(options: AIKeywordResearchOptions): Promise<FreeKeywordResult | PaidKeywordResult>;
|
|
2288
|
+
|
|
2289
|
+
/**
|
|
2290
|
+
* Keyword Research Wizard
|
|
2291
|
+
*
|
|
2292
|
+
* Interactive wizard to reduce uncertainty in keyword research.
|
|
2293
|
+
* Works with CLI (inquirer-style) and Web (JSON responses).
|
|
2294
|
+
*/
|
|
2295
|
+
|
|
2296
|
+
interface WizardQuestion {
|
|
2297
|
+
id: string;
|
|
2298
|
+
question: string;
|
|
2299
|
+
description?: string;
|
|
2300
|
+
type: 'select' | 'multi-select' | 'text' | 'confirm';
|
|
2301
|
+
options?: Array<{
|
|
2302
|
+
value: string;
|
|
2303
|
+
label: string;
|
|
2304
|
+
description?: string;
|
|
2305
|
+
}>;
|
|
2306
|
+
required: boolean;
|
|
2307
|
+
impactOnConfidence: number;
|
|
2308
|
+
category: 'product' | 'audience' | 'competition' | 'goals' | 'constraints';
|
|
2309
|
+
}
|
|
2310
|
+
interface WizardResponse {
|
|
2311
|
+
questionId: string;
|
|
2312
|
+
answer: string | string[];
|
|
2313
|
+
confidence: 'certain' | 'somewhat' | 'unsure';
|
|
2314
|
+
}
|
|
2315
|
+
interface WizardSession {
|
|
2316
|
+
sessionId: string;
|
|
2317
|
+
url: string;
|
|
2318
|
+
siteSummary: SiteSummary;
|
|
2319
|
+
questions: WizardQuestion[];
|
|
2320
|
+
responses: WizardResponse[];
|
|
2321
|
+
currentQuestionIndex: number;
|
|
2322
|
+
isComplete: boolean;
|
|
2323
|
+
finalConfidence: number;
|
|
2324
|
+
}
|
|
2325
|
+
interface WizardResult {
|
|
2326
|
+
session: WizardSession;
|
|
2327
|
+
canProceed: boolean;
|
|
2328
|
+
message: string;
|
|
2329
|
+
nextSteps: string[];
|
|
2330
|
+
}
|
|
2331
|
+
/**
|
|
2332
|
+
* Start a new wizard session
|
|
2333
|
+
*/
|
|
2334
|
+
declare function startWizardSession(url: string, options?: {
|
|
2335
|
+
openaiApiKey?: string;
|
|
2336
|
+
existingResponses?: WizardResponse[];
|
|
2337
|
+
}): Promise<WizardSession>;
|
|
2338
|
+
/**
|
|
2339
|
+
* Generate wizard questions based on site summary uncertainty
|
|
2340
|
+
*/
|
|
2341
|
+
declare function generateWizardQuestions(summary: SiteSummary): WizardQuestion[];
|
|
2342
|
+
/**
|
|
2343
|
+
* Process a wizard response and update session
|
|
2344
|
+
*/
|
|
2345
|
+
declare function processWizardResponse(session: WizardSession, response: WizardResponse): WizardSession;
|
|
2346
|
+
/**
|
|
2347
|
+
* Get the next question in the wizard
|
|
2348
|
+
*/
|
|
2349
|
+
declare function getNextQuestion(session: WizardSession): WizardQuestion | null;
|
|
2350
|
+
/**
|
|
2351
|
+
* Complete the wizard and get result
|
|
2352
|
+
*/
|
|
2353
|
+
declare function completeWizard(session: WizardSession): WizardResult;
|
|
2354
|
+
/**
|
|
2355
|
+
* Convert wizard responses to keyword research context
|
|
2356
|
+
*/
|
|
2357
|
+
declare function wizardResponsesToContext(session: WizardSession): {
|
|
2358
|
+
productDescription?: string;
|
|
2359
|
+
targetAudience?: string;
|
|
2360
|
+
competitors?: string[];
|
|
2361
|
+
mainProblem?: string;
|
|
2362
|
+
differentiator?: string;
|
|
2363
|
+
businessGoal?: string;
|
|
2364
|
+
contentCapacity?: string;
|
|
2365
|
+
domainAuthority?: string;
|
|
2366
|
+
};
|
|
2367
|
+
/**
|
|
2368
|
+
* Format wizard session for CLI output
|
|
2369
|
+
*/
|
|
2370
|
+
declare function formatWizardProgress(session: WizardSession): string;
|
|
2371
|
+
|
|
2372
|
+
/**
|
|
2373
|
+
* CI Mode for Keyword Research
|
|
2374
|
+
*
|
|
2375
|
+
* Handles automated keyword research in CI/CD pipelines.
|
|
2376
|
+
* - If confidence is high enough, adds keywords to PR
|
|
2377
|
+
* - If uncertainty is high, skips and warns user
|
|
2378
|
+
* - Provides clear instructions for what to do next
|
|
2379
|
+
*/
|
|
2380
|
+
|
|
2381
|
+
interface CIKeywordOptions {
|
|
2382
|
+
url: string;
|
|
2383
|
+
tier: PlanTier;
|
|
2384
|
+
openaiApiKey?: string;
|
|
2385
|
+
/** Minimum confidence to proceed (default: 0.7) */
|
|
2386
|
+
minConfidence?: number;
|
|
2387
|
+
/** Maximum keywords to include in PR */
|
|
2388
|
+
maxKeywords?: number;
|
|
2389
|
+
/** Branch name for context */
|
|
2390
|
+
branchName?: string;
|
|
2391
|
+
/** PR number if applicable */
|
|
2392
|
+
prNumber?: number;
|
|
2393
|
+
/** Site ID for dashboard link */
|
|
2394
|
+
siteId?: string;
|
|
2395
|
+
}
|
|
2396
|
+
interface CIKeywordResult {
|
|
2397
|
+
/** Whether keywords can be added to the PR */
|
|
2398
|
+
canAddToPR: boolean;
|
|
2399
|
+
/** Keywords to add (if canAddToPR is true) */
|
|
2400
|
+
keywords: KeywordRecommendation[];
|
|
2401
|
+
/** Warning messages to display */
|
|
2402
|
+
warnings: string[];
|
|
2403
|
+
/** Error messages (if any) */
|
|
2404
|
+
errors: string[];
|
|
2405
|
+
/** Info messages */
|
|
2406
|
+
info: string[];
|
|
2407
|
+
/** Actions user needs to take */
|
|
2408
|
+
requiredActions: CIAction[];
|
|
2409
|
+
/** PR comment body */
|
|
2410
|
+
prCommentBody: string;
|
|
2411
|
+
/** Exit code (0 = success, 1 = needs action, 2 = error) */
|
|
2412
|
+
exitCode: 0 | 1 | 2;
|
|
2413
|
+
/** Detailed explanation */
|
|
2414
|
+
explanation: string;
|
|
2415
|
+
/** Raw result for debugging */
|
|
2416
|
+
rawResult?: PaidKeywordResult | FreeKeywordResult;
|
|
2417
|
+
}
|
|
2418
|
+
interface CIAction {
|
|
2419
|
+
title: string;
|
|
2420
|
+
description: string;
|
|
2421
|
+
command?: string;
|
|
2422
|
+
webUrl?: string;
|
|
2423
|
+
priority: 'high' | 'medium' | 'low';
|
|
2424
|
+
}
|
|
2425
|
+
/**
|
|
2426
|
+
* Run keyword research in CI mode
|
|
2427
|
+
*/
|
|
2428
|
+
declare function runCIKeywordResearch(options: CIKeywordOptions): Promise<CIKeywordResult>;
|
|
2429
|
+
/**
|
|
2430
|
+
* Format CI result for console output
|
|
2431
|
+
*/
|
|
2432
|
+
declare function formatCIResult(result: CIKeywordResult): string;
|
|
2433
|
+
|
|
2434
|
+
declare function prioritizeKeywords(keywords: KeywordData[], siteProfile: SiteProfile, existingMeta?: {
|
|
2435
|
+
title?: string;
|
|
2436
|
+
description?: string;
|
|
2437
|
+
h1?: string;
|
|
2438
|
+
}): KeywordResearchResult;
|
|
2439
|
+
|
|
2440
|
+
interface AutocompleteOptions {
|
|
2441
|
+
language?: string;
|
|
2442
|
+
country?: string;
|
|
2443
|
+
}
|
|
2444
|
+
declare function getAutocompleteSuggestions(seedKeyword: string, options?: AutocompleteOptions): Promise<KeywordData[]>;
|
|
2445
|
+
declare function getExpandedSuggestions(seedKeyword: string, options?: AutocompleteOptions): Promise<KeywordData[]>;
|
|
2446
|
+
declare function enrichKeywordsWithEstimates(keywords: KeywordData[]): KeywordData[];
|
|
2447
|
+
|
|
2448
|
+
interface GSCQueryOptions {
|
|
2449
|
+
siteUrl: string;
|
|
2450
|
+
startDate: string;
|
|
2451
|
+
endDate: string;
|
|
2452
|
+
dimensions?: string[];
|
|
2453
|
+
rowLimit?: number;
|
|
2454
|
+
startRow?: number;
|
|
2455
|
+
}
|
|
2456
|
+
declare function transformGSCData(gscData: GSCQueryData[]): KeywordData[];
|
|
2457
|
+
declare function findCTROpportunities(gscData: GSCQueryData[]): GSCQueryData[];
|
|
2458
|
+
declare function findAlmostPage1Keywords(gscData: GSCQueryData[]): GSCQueryData[];
|
|
2459
|
+
declare function findTopPerformers(gscData: GSCQueryData[]): GSCQueryData[];
|
|
2460
|
+
declare function buildGSCRequest(options: GSCQueryOptions): object;
|
|
2461
|
+
declare function getDateRange(days?: number): {
|
|
2462
|
+
startDate: string;
|
|
2463
|
+
endDate: string;
|
|
2464
|
+
};
|
|
2465
|
+
|
|
2466
|
+
interface CompetitorKeywordResult {
|
|
2467
|
+
coreKeywords: KeywordData[];
|
|
2468
|
+
missingKeywords: KeywordData[];
|
|
2469
|
+
uniqueKeywords: KeywordData[];
|
|
2470
|
+
keywordUniverse: KeywordData[];
|
|
2471
|
+
competitorOverlap: CompetitorOverlap[];
|
|
2472
|
+
}
|
|
2473
|
+
interface CompetitorOverlap {
|
|
2474
|
+
competitor: string;
|
|
2475
|
+
sharedKeywords: number;
|
|
2476
|
+
uniqueToThem: number;
|
|
2477
|
+
uniqueToYou: number;
|
|
2478
|
+
}
|
|
2479
|
+
/**
|
|
2480
|
+
* Scrape competitor rankings from Google SERP for seed keywords
|
|
2481
|
+
* This discovers what keywords competitors appear for
|
|
2482
|
+
*/
|
|
2483
|
+
declare function discoverCompetitorKeywords(yourDomain: string, seedKeywords: string[], competitors?: string[]): Promise<CompetitorKeywordResult>;
|
|
2484
|
+
/**
|
|
2485
|
+
* Format competitor analysis report
|
|
2486
|
+
*/
|
|
2487
|
+
declare function formatCompetitorReport(result: CompetitorKeywordResult): string;
|
|
2488
|
+
|
|
2489
|
+
interface KeywordTopic {
|
|
2490
|
+
topic: string;
|
|
2491
|
+
keywords: KeywordData[];
|
|
2492
|
+
totalVolume: number;
|
|
2493
|
+
avgDifficulty: number;
|
|
2494
|
+
contentType: 'hub' | 'pillar' | 'cluster';
|
|
2495
|
+
}
|
|
2496
|
+
interface TopicClusterResult {
|
|
2497
|
+
topics: KeywordTopic[];
|
|
2498
|
+
uncategorized: KeywordData[];
|
|
2499
|
+
contentStrategy: ContentRecommendation[];
|
|
2500
|
+
}
|
|
2501
|
+
interface ContentRecommendation {
|
|
2502
|
+
topic: string;
|
|
2503
|
+
pageType: 'pillar-page' | 'blog-post' | 'faq-page' | 'landing-page';
|
|
2504
|
+
targetKeywords: string[];
|
|
2505
|
+
potentialTraffic: number;
|
|
2506
|
+
difficulty: 'easy' | 'medium' | 'hard';
|
|
2507
|
+
}
|
|
2508
|
+
/**
|
|
2509
|
+
* Group keywords into topic clusters using multiple strategies:
|
|
2510
|
+
* 1. Shared root words
|
|
2511
|
+
* 2. Semantic similarity (common terms)
|
|
2512
|
+
* 3. Intent matching (questions, how-to, etc.)
|
|
2513
|
+
* 4. N-gram overlap
|
|
2514
|
+
*/
|
|
2515
|
+
declare function groupKeywordsByTopic(keywords: KeywordData[]): TopicClusterResult;
|
|
2516
|
+
/**
|
|
2517
|
+
* Format topic grouping report
|
|
2518
|
+
*/
|
|
2519
|
+
declare function formatTopicReport(result: TopicClusterResult): string;
|
|
2520
|
+
|
|
2521
|
+
/**
|
|
2522
|
+
* Competitive Search Module
|
|
2523
|
+
*
|
|
2524
|
+
* Uses free APIs to find existing tools, competitors, and market intelligence.
|
|
2525
|
+
* Priority order: Brave Search > Serper.dev > GitHub > npm/PyPI
|
|
2526
|
+
*/
|
|
2527
|
+
interface CompetitorTool {
|
|
2528
|
+
name: string;
|
|
2529
|
+
url: string;
|
|
2530
|
+
description: string;
|
|
2531
|
+
isPaid: boolean;
|
|
2532
|
+
pricing?: string;
|
|
2533
|
+
source: 'search' | 'github' | 'npm' | 'pypi' | 'hackernews';
|
|
2534
|
+
stars?: number;
|
|
2535
|
+
weeklyDownloads?: number;
|
|
2536
|
+
}
|
|
2537
|
+
interface CompetitiveSearchResult {
|
|
2538
|
+
query: string;
|
|
2539
|
+
existingTools: CompetitorTool[];
|
|
2540
|
+
openSourceOptions: CompetitorTool[];
|
|
2541
|
+
marketInsights: {
|
|
2542
|
+
hasFreeSolutions: boolean;
|
|
2543
|
+
hasPaidSolutions: boolean;
|
|
2544
|
+
dominantPlayer?: string;
|
|
2545
|
+
marketGap?: string;
|
|
2546
|
+
};
|
|
2547
|
+
searchSource: string;
|
|
2548
|
+
}
|
|
2549
|
+
interface CompetitiveSearchOptions {
|
|
2550
|
+
braveApiKey?: string;
|
|
2551
|
+
serperApiKey?: string;
|
|
2552
|
+
githubToken?: string;
|
|
2553
|
+
maxResults?: number;
|
|
2554
|
+
}
|
|
2555
|
+
/**
|
|
2556
|
+
* Search for existing tools and competitors
|
|
2557
|
+
*/
|
|
2558
|
+
declare function searchCompetitors(toolConcept: string, options?: CompetitiveSearchOptions): Promise<CompetitiveSearchResult>;
|
|
2559
|
+
/**
|
|
2560
|
+
* Search for specific format converters (e.g., "X to Mermaid converter")
|
|
2561
|
+
*/
|
|
2562
|
+
declare function searchFormatConverters(targetFormat: string, options?: CompetitiveSearchOptions): Promise<{
|
|
2563
|
+
sourceFormats: string[];
|
|
2564
|
+
existingConverters: CompetitorTool[];
|
|
2565
|
+
opportunities: string[];
|
|
2566
|
+
}>;
|
|
2567
|
+
/**
|
|
2568
|
+
* Search Hacker News for tool discussions
|
|
2569
|
+
*/
|
|
2570
|
+
declare function searchHackerNews(query: string, maxResults?: number): Promise<Array<{
|
|
2571
|
+
title: string;
|
|
2572
|
+
url: string;
|
|
2573
|
+
points: number;
|
|
2574
|
+
comments: number;
|
|
2575
|
+
}>>;
|
|
2576
|
+
|
|
2577
|
+
/**
|
|
2578
|
+
* LLM-as-Judge Module
|
|
2579
|
+
*
|
|
2580
|
+
* Uses AI to evaluate tool feasibility, specificity, and product fit.
|
|
2581
|
+
* Prevents vague or unbuildable tool suggestions.
|
|
2582
|
+
*/
|
|
2583
|
+
|
|
2584
|
+
interface ToolFeasibilityScore {
|
|
2585
|
+
/** Overall feasibility score 1-5 */
|
|
2586
|
+
feasibility: number;
|
|
2587
|
+
/** Specificity score 1-5 (how detailed/actionable is the idea?) */
|
|
2588
|
+
specificity: number;
|
|
2589
|
+
/** Product fit score 1-5 (how well does it tie into the main product?) */
|
|
2590
|
+
productFit: number;
|
|
2591
|
+
/** Market opportunity score 1-5 */
|
|
2592
|
+
marketOpportunity: number;
|
|
2593
|
+
/** Combined weighted score */
|
|
2594
|
+
overallScore: number;
|
|
2595
|
+
/** Pass/fail based on minimum threshold */
|
|
2596
|
+
passes: boolean;
|
|
2597
|
+
/** Explanation for the scores */
|
|
2598
|
+
reasoning: string;
|
|
2599
|
+
/** Issues that would prevent building */
|
|
2600
|
+
blockers: string[];
|
|
2601
|
+
/** Improvements to make the tool more specific */
|
|
2602
|
+
improvements: string[];
|
|
2603
|
+
}
|
|
2604
|
+
interface EnhancedToolIdea {
|
|
2605
|
+
keyword: string;
|
|
2606
|
+
toolName: string;
|
|
2607
|
+
description: string;
|
|
2608
|
+
/** Specific input format (e.g., "PlantUML text syntax") */
|
|
2609
|
+
inputFormat: string;
|
|
2610
|
+
/** Specific output format (e.g., "Mermaid diagram code") */
|
|
2611
|
+
outputFormat: string;
|
|
2612
|
+
/** How this tool connects back to the main product */
|
|
2613
|
+
productTieIn: string;
|
|
2614
|
+
/** Specific CTA text */
|
|
2615
|
+
ctaText: string;
|
|
2616
|
+
/** Deep link into product if possible */
|
|
2617
|
+
deepLinkPattern?: string;
|
|
2618
|
+
/** Competitor analysis */
|
|
2619
|
+
competitors: {
|
|
2620
|
+
hasFreeAlternative: boolean;
|
|
2621
|
+
topCompetitor?: string;
|
|
2622
|
+
ourAdvantage: string;
|
|
2623
|
+
};
|
|
2624
|
+
/** Technical implementation hints */
|
|
2625
|
+
implementationHints: {
|
|
2626
|
+
suggestedLibraries: string[];
|
|
2627
|
+
estimatedComplexity: 'trivial' | 'simple' | 'moderate' | 'complex';
|
|
2628
|
+
canUseExistingOSS: boolean;
|
|
2629
|
+
ossLibrary?: string;
|
|
2630
|
+
};
|
|
2631
|
+
/** Feasibility assessment */
|
|
2632
|
+
feasibilityScore: ToolFeasibilityScore;
|
|
2633
|
+
/** Search volume and difficulty from keyword data */
|
|
2634
|
+
volume: number;
|
|
2635
|
+
difficulty: number;
|
|
2636
|
+
priority: number;
|
|
2637
|
+
}
|
|
2638
|
+
interface LLMJudgeOptions {
|
|
2639
|
+
openaiApiKey: string;
|
|
2640
|
+
minFeasibilityScore?: number;
|
|
2641
|
+
minSpecificityScore?: number;
|
|
2642
|
+
minProductFitScore?: number;
|
|
2643
|
+
}
|
|
2644
|
+
/**
|
|
2645
|
+
* Evaluate a tool idea for feasibility, specificity, and product fit
|
|
2646
|
+
*/
|
|
2647
|
+
declare function evaluateToolFeasibility(toolIdea: {
|
|
2648
|
+
keyword: string;
|
|
2649
|
+
toolName: string;
|
|
2650
|
+
toolDescription: string;
|
|
2651
|
+
}, siteSummary: SiteSummary, competitiveData: CompetitiveSearchResult | null, options: LLMJudgeOptions): Promise<ToolFeasibilityScore>;
|
|
2652
|
+
/**
|
|
2653
|
+
* Enhance a tool idea with specific details using AI
|
|
2654
|
+
*/
|
|
2655
|
+
declare function enhanceToolIdea(toolIdea: {
|
|
2656
|
+
keyword: string;
|
|
2657
|
+
toolName: string;
|
|
2658
|
+
toolDescription: string;
|
|
2659
|
+
volume: number;
|
|
2660
|
+
difficulty: number;
|
|
2661
|
+
}, siteSummary: SiteSummary, competitiveData: CompetitiveSearchResult | null, options: LLMJudgeOptions): Promise<EnhancedToolIdea | null>;
|
|
2662
|
+
/**
|
|
2663
|
+
* Batch evaluate and enhance tool ideas
|
|
2664
|
+
*/
|
|
2665
|
+
declare function evaluateAndEnhanceToolIdeas(toolIdeas: Array<{
|
|
2666
|
+
keyword: string;
|
|
2667
|
+
toolName: string;
|
|
2668
|
+
toolDescription: string;
|
|
2669
|
+
volume: number;
|
|
2670
|
+
difficulty: number;
|
|
2671
|
+
}>, siteSummary: SiteSummary, getCompetitiveData: (keyword: string) => Promise<CompetitiveSearchResult | null>, options: LLMJudgeOptions): Promise<EnhancedToolIdea[]>;
|
|
2672
|
+
|
|
2673
|
+
interface ReadabilityResult {
|
|
2674
|
+
fleschReadingEase: number;
|
|
2675
|
+
fleschGrade: string;
|
|
2676
|
+
fleschKincaidGrade: number;
|
|
2677
|
+
avgSentenceLength: number;
|
|
2678
|
+
avgSyllablesPerWord: number;
|
|
2679
|
+
avgWordsPerParagraph: number;
|
|
2680
|
+
wordCount: number;
|
|
2681
|
+
sentenceCount: number;
|
|
2682
|
+
paragraphCount: number;
|
|
2683
|
+
syllableCount: number;
|
|
2684
|
+
passiveVoicePercentage: number;
|
|
2685
|
+
complexWordPercentage: number;
|
|
2686
|
+
recommendations: string[];
|
|
2687
|
+
score: number;
|
|
2688
|
+
}
|
|
2689
|
+
/**
|
|
2690
|
+
* Analyze content readability
|
|
2691
|
+
*/
|
|
2692
|
+
declare function analyzeReadability(text: string): ReadabilityResult;
|
|
2693
|
+
/**
|
|
2694
|
+
* Format readability report
|
|
2695
|
+
*/
|
|
2696
|
+
declare function formatReadabilityReport(result: ReadabilityResult): string;
|
|
2697
|
+
|
|
2698
|
+
type SearchIntent = 'informational' | 'navigational' | 'transactional' | 'commercial';
|
|
2699
|
+
interface IntentAnalysis {
|
|
2700
|
+
intent: SearchIntent;
|
|
2701
|
+
confidence: number;
|
|
2702
|
+
signals: string[];
|
|
2703
|
+
recommendedContentFormat: string;
|
|
2704
|
+
contentSuggestions: string[];
|
|
2705
|
+
}
|
|
2706
|
+
/**
|
|
2707
|
+
* Classify search intent for a keyword/query
|
|
2708
|
+
*/
|
|
2709
|
+
declare function classifyIntent(query: string): IntentAnalysis;
|
|
2710
|
+
/**
|
|
2711
|
+
* Batch classify multiple keywords
|
|
2712
|
+
*/
|
|
2713
|
+
declare function classifyIntents(keywords: string[]): Map<string, IntentAnalysis>;
|
|
2714
|
+
/**
|
|
2715
|
+
* Format intent analysis report
|
|
2716
|
+
*/
|
|
2717
|
+
declare function formatIntentReport(query: string, analysis: IntentAnalysis): string;
|
|
2718
|
+
|
|
2719
|
+
interface HeadlineAnalysis {
|
|
2720
|
+
headline: string;
|
|
2721
|
+
score: number;
|
|
2722
|
+
wordCount: number;
|
|
2723
|
+
charCount: number;
|
|
2724
|
+
breakdown: {
|
|
2725
|
+
length: number;
|
|
2726
|
+
powerWords: number;
|
|
2727
|
+
emotionalWords: number;
|
|
2728
|
+
numbers: number;
|
|
2729
|
+
readability: number;
|
|
2730
|
+
uniqueness: number;
|
|
2731
|
+
};
|
|
2732
|
+
issues: string[];
|
|
2733
|
+
suggestions: string[];
|
|
2734
|
+
type: 'how-to' | 'list' | 'question' | 'statement' | 'guide' | 'other';
|
|
2735
|
+
sentiment: 'positive' | 'negative' | 'neutral';
|
|
2736
|
+
}
|
|
2737
|
+
/**
|
|
2738
|
+
* Analyze headline effectiveness
|
|
2739
|
+
*/
|
|
2740
|
+
declare function analyzeHeadline(headline: string): HeadlineAnalysis;
|
|
2741
|
+
/**
|
|
2742
|
+
* Generate headline variations
|
|
2743
|
+
*/
|
|
2744
|
+
declare function generateHeadlineVariations(topic: string, keywords: string[]): string[];
|
|
2745
|
+
/**
|
|
2746
|
+
* Format headline analysis report
|
|
2747
|
+
*/
|
|
2748
|
+
declare function formatHeadlineReport(analysis: HeadlineAnalysis): string;
|
|
2749
|
+
|
|
2750
|
+
type SnippetType = 'paragraph' | 'list' | 'table' | 'video' | 'none';
|
|
2751
|
+
interface FeaturedSnippetAnalysis {
|
|
2752
|
+
snippetPotential: number;
|
|
2753
|
+
bestSnippetType: SnippetType;
|
|
2754
|
+
hasDirectAnswer: boolean;
|
|
2755
|
+
hasNumberedSteps: boolean;
|
|
2756
|
+
hasBulletList: boolean;
|
|
2757
|
+
hasTable: boolean;
|
|
2758
|
+
hasDefinition: boolean;
|
|
2759
|
+
recommendations: SnippetRecommendation[];
|
|
2760
|
+
suggestedParagraph?: string;
|
|
2761
|
+
suggestedListItems?: string[];
|
|
2762
|
+
}
|
|
2763
|
+
interface SnippetRecommendation {
|
|
2764
|
+
priority: 'high' | 'medium' | 'low';
|
|
2765
|
+
action: string;
|
|
2766
|
+
example?: string;
|
|
2767
|
+
}
|
|
2768
|
+
/**
|
|
2769
|
+
* Analyze content for featured snippet optimization
|
|
2770
|
+
*/
|
|
2771
|
+
declare function analyzeFeaturedSnippetPotential(query: string, content: string, headings: string[]): FeaturedSnippetAnalysis;
|
|
2772
|
+
/**
|
|
2773
|
+
* Format featured snippet analysis report
|
|
2774
|
+
*/
|
|
2775
|
+
declare function formatFeaturedSnippetReport(analysis: FeaturedSnippetAnalysis): string;
|
|
2776
|
+
|
|
2777
|
+
interface KeywordDensityAnalysis {
|
|
2778
|
+
primaryKeyword: string;
|
|
2779
|
+
density: number;
|
|
2780
|
+
occurrences: number;
|
|
2781
|
+
wordCount: number;
|
|
2782
|
+
inTitle: boolean;
|
|
2783
|
+
inH1: boolean;
|
|
2784
|
+
inFirstParagraph: boolean;
|
|
2785
|
+
inLastParagraph: boolean;
|
|
2786
|
+
inHeadings: number;
|
|
2787
|
+
isKeywordStuffing: boolean;
|
|
2788
|
+
isUnderOptimized: boolean;
|
|
2789
|
+
lsiKeywords: LSIKeyword[];
|
|
2790
|
+
recommendations: string[];
|
|
2791
|
+
}
|
|
2792
|
+
interface LSIKeyword {
|
|
2793
|
+
keyword: string;
|
|
2794
|
+
occurrences: number;
|
|
2795
|
+
relevance: 'high' | 'medium' | 'low';
|
|
2796
|
+
}
|
|
2797
|
+
interface ContentElements {
|
|
2798
|
+
title?: string;
|
|
2799
|
+
h1?: string;
|
|
2800
|
+
headings: string[];
|
|
2801
|
+
body: string;
|
|
2802
|
+
firstParagraph?: string;
|
|
2803
|
+
lastParagraph?: string;
|
|
2804
|
+
}
|
|
2805
|
+
/**
|
|
2806
|
+
* Analyze keyword density in content
|
|
2807
|
+
*/
|
|
2808
|
+
declare function analyzeKeywordDensity(primaryKeyword: string, content: ContentElements): KeywordDensityAnalysis;
|
|
2809
|
+
/**
|
|
2810
|
+
* Find LSI (Latent Semantic Indexing) keywords in content
|
|
2811
|
+
*/
|
|
2812
|
+
declare function findLSIKeywords(primaryKeyword: string, content: string): LSIKeyword[];
|
|
2813
|
+
/**
|
|
2814
|
+
* Calculate TF-IDF score for keywords in content
|
|
2815
|
+
*/
|
|
2816
|
+
declare function calculateTFIDF(content: string, documentCount?: number): Map<string, number>;
|
|
2817
|
+
/**
|
|
2818
|
+
* Format keyword density report
|
|
2819
|
+
*/
|
|
2820
|
+
declare function formatKeywordDensityReport(analysis: KeywordDensityAnalysis): string;
|
|
2821
|
+
|
|
2822
|
+
/**
|
|
2823
|
+
* Content Generator Module
|
|
2824
|
+
*
|
|
2825
|
+
* Generates SEO-optimized content including blog posts, changelogs,
|
|
2826
|
+
* and README files. Supports GEO (Generative Engine Optimization)
|
|
2827
|
+
* for AI-friendly content.
|
|
2828
|
+
*/
|
|
2829
|
+
interface BlogPostConfig {
|
|
2830
|
+
topic: string;
|
|
2831
|
+
keywords?: string[];
|
|
2832
|
+
tone?: 'technical' | 'educational' | 'casual' | 'professional';
|
|
2833
|
+
wordCount?: {
|
|
2834
|
+
min: number;
|
|
2835
|
+
max: number;
|
|
2836
|
+
};
|
|
2837
|
+
includeFAQ?: boolean;
|
|
2838
|
+
geoOptimize?: boolean;
|
|
2839
|
+
}
|
|
2840
|
+
interface ChangelogConfig {
|
|
2841
|
+
fromRef: string;
|
|
2842
|
+
toRef: string;
|
|
2843
|
+
groupByType?: boolean;
|
|
2844
|
+
seoKeywords?: string[];
|
|
2845
|
+
includeBreaking?: boolean;
|
|
2846
|
+
}
|
|
2847
|
+
interface ReadmeConfig {
|
|
2848
|
+
currentContent: string;
|
|
2849
|
+
projectName: string;
|
|
2850
|
+
keywords?: string[];
|
|
2851
|
+
preserveCustomSections?: boolean;
|
|
2852
|
+
}
|
|
2853
|
+
interface GeneratedContent {
|
|
2854
|
+
title: string;
|
|
2855
|
+
content: string;
|
|
2856
|
+
metaDescription: string;
|
|
2857
|
+
keywords: string[];
|
|
2858
|
+
readingTime?: string;
|
|
2859
|
+
wordCount?: number;
|
|
2860
|
+
hasFAQ?: boolean;
|
|
2861
|
+
error?: string;
|
|
2862
|
+
}
|
|
2863
|
+
interface ChangelogResult {
|
|
2864
|
+
content: string;
|
|
2865
|
+
version?: string;
|
|
2866
|
+
date?: string;
|
|
2867
|
+
sections: {
|
|
2868
|
+
features?: string[];
|
|
2869
|
+
fixes?: string[];
|
|
2870
|
+
breaking?: string[];
|
|
2871
|
+
docs?: string[];
|
|
2872
|
+
other?: string[];
|
|
2873
|
+
};
|
|
2874
|
+
metaDescription?: string;
|
|
2875
|
+
}
|
|
2876
|
+
interface ReadmeResult {
|
|
2877
|
+
content: string;
|
|
2878
|
+
metaDescription?: string;
|
|
2879
|
+
suggestions: string[];
|
|
2880
|
+
}
|
|
2881
|
+
interface SEOScore {
|
|
2882
|
+
overall: number;
|
|
2883
|
+
headingScore: number;
|
|
2884
|
+
keywordScore: number;
|
|
2885
|
+
lengthScore: number;
|
|
2886
|
+
linkScore: number;
|
|
2887
|
+
mediaScore: number;
|
|
2888
|
+
}
|
|
2889
|
+
interface ContentGeneratorOptions {
|
|
2890
|
+
llm?: LLMFunction;
|
|
2891
|
+
exec?: ExecFunction;
|
|
2892
|
+
}
|
|
2893
|
+
type LLMFunction = (prompt: string) => Promise<any>;
|
|
2894
|
+
type ExecFunction = (cmd: string) => Promise<{
|
|
2895
|
+
stdout: string;
|
|
2896
|
+
stderr?: string;
|
|
2897
|
+
}>;
|
|
2898
|
+
/**
|
|
2899
|
+
* Generate an SEO-optimized blog post
|
|
2900
|
+
*/
|
|
2901
|
+
declare function generateBlogPost(config: BlogPostConfig, options?: ContentGeneratorOptions): Promise<GeneratedContent>;
|
|
2902
|
+
/**
|
|
2903
|
+
* Generate a changelog from git commits
|
|
2904
|
+
*/
|
|
2905
|
+
declare function generateChangelog(config: ChangelogConfig, options?: ContentGeneratorOptions): Promise<ChangelogResult>;
|
|
2906
|
+
/**
|
|
2907
|
+
* Optimize a README file for SEO
|
|
2908
|
+
*/
|
|
2909
|
+
declare function optimizeReadme(config: ReadmeConfig, options?: ContentGeneratorOptions): Promise<ReadmeResult>;
|
|
2910
|
+
/**
|
|
2911
|
+
* Score content for SEO quality
|
|
2912
|
+
*/
|
|
2913
|
+
declare function scoreContentSEO(content: string, options?: {
|
|
2914
|
+
targetKeywords?: string[];
|
|
2915
|
+
}): SEOScore;
|
|
2916
|
+
|
|
2917
|
+
interface GA4Config {
|
|
2918
|
+
measurementId: string;
|
|
2919
|
+
}
|
|
2920
|
+
interface InjectionResult {
|
|
2921
|
+
success: boolean;
|
|
2922
|
+
file?: string;
|
|
2923
|
+
message: string;
|
|
2924
|
+
code?: string;
|
|
2925
|
+
}
|
|
2926
|
+
/**
|
|
2927
|
+
* Generate GA4 tracking script
|
|
2928
|
+
*/
|
|
2929
|
+
declare function generateGA4Script(config: GA4Config): string;
|
|
2930
|
+
/**
|
|
2931
|
+
* Generate GA4 for React/Next.js (component-based)
|
|
2932
|
+
*/
|
|
2933
|
+
declare function generateGA4ReactComponent(config: GA4Config): string;
|
|
2934
|
+
/**
|
|
2935
|
+
* Generate GA4 for Vite/vanilla (index.html injection)
|
|
2936
|
+
*/
|
|
2937
|
+
declare function generateGA4ViteScript(config: GA4Config): string;
|
|
2938
|
+
/**
|
|
2939
|
+
* Auto-detect framework and inject GA4
|
|
2940
|
+
*/
|
|
2941
|
+
declare function injectGA4(projectPath: string, config: GA4Config): Promise<InjectionResult>;
|
|
2942
|
+
/**
|
|
2943
|
+
* Generate environment variable template for GA4
|
|
2944
|
+
*/
|
|
2945
|
+
declare function generateGA4EnvTemplate(): string;
|
|
2946
|
+
|
|
2947
|
+
interface GSCConfig {
|
|
2948
|
+
verificationCode?: string;
|
|
2949
|
+
siteUrl: string;
|
|
2950
|
+
credentials?: GSCCredentials;
|
|
2951
|
+
}
|
|
2952
|
+
interface GSCCredentials {
|
|
2953
|
+
type: 'service_account' | 'oauth';
|
|
2954
|
+
clientEmail?: string;
|
|
2955
|
+
privateKey?: string;
|
|
2956
|
+
accessToken?: string;
|
|
2957
|
+
refreshToken?: string;
|
|
2958
|
+
}
|
|
2959
|
+
interface GSCQueryResult {
|
|
2960
|
+
query: string;
|
|
2961
|
+
clicks: number;
|
|
2962
|
+
impressions: number;
|
|
2963
|
+
ctr: number;
|
|
2964
|
+
position: number;
|
|
2965
|
+
page?: string;
|
|
2966
|
+
}
|
|
2967
|
+
interface GSCPerformanceData {
|
|
2968
|
+
startDate: string;
|
|
2969
|
+
endDate: string;
|
|
2970
|
+
queries: GSCQueryResult[];
|
|
2971
|
+
totalClicks: number;
|
|
2972
|
+
totalImpressions: number;
|
|
2973
|
+
avgCtr: number;
|
|
2974
|
+
avgPosition: number;
|
|
2975
|
+
}
|
|
2976
|
+
interface QuickWin {
|
|
2977
|
+
query: string;
|
|
2978
|
+
currentPosition: number;
|
|
2979
|
+
impressions: number;
|
|
2980
|
+
clicks: number;
|
|
2981
|
+
ctr: number;
|
|
2982
|
+
opportunity: 'page-1-close' | 'low-ctr' | 'high-impression';
|
|
2983
|
+
suggestedAction: string;
|
|
2984
|
+
potentialGain: number;
|
|
2985
|
+
}
|
|
2986
|
+
/**
|
|
2987
|
+
* Generate Search Console verification meta tag
|
|
2988
|
+
*/
|
|
2989
|
+
declare function generateGSCVerificationTag(verificationCode: string): string;
|
|
2990
|
+
/**
|
|
2991
|
+
* Inject GSC verification into project
|
|
2992
|
+
*/
|
|
2993
|
+
declare function injectGSCVerification(projectPath: string, verificationCode: string): Promise<{
|
|
2994
|
+
success: boolean;
|
|
2995
|
+
file?: string;
|
|
2996
|
+
message: string;
|
|
2997
|
+
}>;
|
|
2998
|
+
/**
|
|
2999
|
+
* Build GSC API request (for use with Google APIs client)
|
|
3000
|
+
* User needs to set up OAuth or service account credentials
|
|
3001
|
+
*/
|
|
3002
|
+
declare function buildGSCApiRequest(siteUrl: string, startDate: string, endDate: string, options?: {
|
|
3003
|
+
dimensions?: ('query' | 'page' | 'country' | 'device' | 'date')[];
|
|
3004
|
+
rowLimit?: number;
|
|
3005
|
+
startRow?: number;
|
|
3006
|
+
}): object;
|
|
3007
|
+
/**
|
|
3008
|
+
* Parse GSC API response into our format
|
|
3009
|
+
*/
|
|
3010
|
+
declare function parseGSCResponse(response: any): GSCPerformanceData;
|
|
3011
|
+
/**
|
|
3012
|
+
* Identify quick wins from GSC data
|
|
3013
|
+
*/
|
|
3014
|
+
declare function identifyQuickWins(data: GSCPerformanceData): QuickWin[];
|
|
3015
|
+
/**
|
|
3016
|
+
* Compare two periods to identify trends
|
|
3017
|
+
*/
|
|
3018
|
+
declare function comparePeriods(current: GSCPerformanceData, previous: GSCPerformanceData): {
|
|
3019
|
+
improved: GSCQueryResult[];
|
|
3020
|
+
declined: GSCQueryResult[];
|
|
3021
|
+
newKeywords: GSCQueryResult[];
|
|
3022
|
+
lostKeywords: GSCQueryResult[];
|
|
3023
|
+
summary: {
|
|
3024
|
+
clicksChange: number;
|
|
3025
|
+
impressionsChange: number;
|
|
3026
|
+
avgPositionChange: number;
|
|
3027
|
+
};
|
|
3028
|
+
};
|
|
3029
|
+
/**
|
|
3030
|
+
* Generate credentials setup instructions
|
|
3031
|
+
*/
|
|
3032
|
+
declare function getGSCSetupInstructions(): string;
|
|
3033
|
+
|
|
3034
|
+
interface WorkflowConfig {
|
|
3035
|
+
schedule: 'daily' | 'weekly' | 'monthly' | 'manual';
|
|
3036
|
+
siteUrl: string;
|
|
3037
|
+
features: {
|
|
3038
|
+
audit: boolean;
|
|
3039
|
+
tracking: boolean;
|
|
3040
|
+
autoFix: boolean;
|
|
3041
|
+
createIssues: boolean;
|
|
3042
|
+
createPRs: boolean;
|
|
3043
|
+
};
|
|
3044
|
+
apiKey?: string;
|
|
3045
|
+
}
|
|
3046
|
+
/**
|
|
3047
|
+
* Generate GitHub Action workflow YAML
|
|
3048
|
+
*/
|
|
3049
|
+
declare function generateWorkflow(config: WorkflowConfig): string;
|
|
3050
|
+
/**
|
|
3051
|
+
* Generate the secrets documentation
|
|
3052
|
+
*/
|
|
3053
|
+
declare function generateSecretsDoc(config: WorkflowConfig): string;
|
|
3054
|
+
/**
|
|
3055
|
+
* Generate complete setup package
|
|
3056
|
+
*/
|
|
3057
|
+
declare function generateGitHubActionSetup(config: WorkflowConfig): {
|
|
3058
|
+
workflowYaml: string;
|
|
3059
|
+
secretsDoc: string;
|
|
3060
|
+
readmeBadge: string;
|
|
3061
|
+
};
|
|
3062
|
+
/**
|
|
3063
|
+
* Write GitHub Action files to project
|
|
3064
|
+
*/
|
|
3065
|
+
declare function writeGitHubActionFiles(projectPath: string, config: WorkflowConfig): {
|
|
3066
|
+
files: string[];
|
|
3067
|
+
instructions: string;
|
|
3068
|
+
};
|
|
3069
|
+
|
|
3070
|
+
interface ReportData {
|
|
3071
|
+
siteUrl: string;
|
|
3072
|
+
generatedAt: string;
|
|
3073
|
+
audit?: AuditReport;
|
|
3074
|
+
tracking?: {
|
|
3075
|
+
current: GSCPerformanceData;
|
|
3076
|
+
previous?: GSCPerformanceData;
|
|
3077
|
+
quickWins: QuickWin[];
|
|
3078
|
+
};
|
|
3079
|
+
comparison?: {
|
|
3080
|
+
improved: any[];
|
|
3081
|
+
declined: any[];
|
|
3082
|
+
newKeywords: any[];
|
|
3083
|
+
lostKeywords: any[];
|
|
3084
|
+
summary: {
|
|
3085
|
+
clicksChange: number;
|
|
3086
|
+
impressionsChange: number;
|
|
3087
|
+
avgPositionChange: number;
|
|
3088
|
+
};
|
|
3089
|
+
};
|
|
3090
|
+
}
|
|
3091
|
+
/**
|
|
3092
|
+
* Generate comprehensive markdown report
|
|
3093
|
+
*/
|
|
3094
|
+
declare function generateMarkdownReport(data: ReportData): string;
|
|
3095
|
+
/**
|
|
3096
|
+
* Generate JSON report for API/dashboard
|
|
3097
|
+
*/
|
|
3098
|
+
declare function generateJsonReport(data: ReportData): object;
|
|
3099
|
+
|
|
3100
|
+
declare function loadAgent(agentPath: string): AgentDefinition;
|
|
3101
|
+
declare function loadAgentByName(name: string, agentsDir?: string): AgentDefinition;
|
|
3102
|
+
declare function interpolatePrompt(template: string, variables: Record<string, string>): string;
|
|
3103
|
+
|
|
3104
|
+
interface ExecuteOptions {
|
|
3105
|
+
variables?: Record<string, string>;
|
|
3106
|
+
onToolCall?: (name: string, params: Record<string, unknown>) => void;
|
|
3107
|
+
onToolResult?: (name: string, result: ToolResult) => void;
|
|
3108
|
+
cwd?: string;
|
|
3109
|
+
}
|
|
3110
|
+
interface ExecutionResult {
|
|
3111
|
+
success: boolean;
|
|
3112
|
+
data?: unknown;
|
|
3113
|
+
error?: string;
|
|
3114
|
+
toolCalls?: {
|
|
3115
|
+
name: string;
|
|
3116
|
+
params: unknown;
|
|
3117
|
+
result: ToolResult;
|
|
3118
|
+
}[];
|
|
3119
|
+
}
|
|
3120
|
+
declare function executeAgent(agent: AgentDefinition, options?: ExecuteOptions): Promise<ExecutionResult>;
|
|
3121
|
+
declare function runDirectAnalysis(url: string): Promise<SEOAnalysisResult>;
|
|
3122
|
+
|
|
3123
|
+
interface FixGeneratorOptions {
|
|
3124
|
+
cwd: string;
|
|
3125
|
+
url?: string;
|
|
3126
|
+
framework?: FrameworkInfo$1;
|
|
3127
|
+
}
|
|
3128
|
+
interface GeneratedFix extends Fix {
|
|
3129
|
+
applied?: boolean;
|
|
3130
|
+
skipped?: boolean;
|
|
3131
|
+
skipReason?: string;
|
|
3132
|
+
}
|
|
3133
|
+
declare function generateFixes(issues: SEOIssue[], options: FixGeneratorOptions): Promise<GeneratedFix[]>;
|
|
3134
|
+
declare function applyFixes(fixes: GeneratedFix[], options: {
|
|
3135
|
+
cwd: string;
|
|
3136
|
+
dryRun?: boolean;
|
|
3137
|
+
}): Promise<{
|
|
3138
|
+
applied: GeneratedFix[];
|
|
3139
|
+
skipped: GeneratedFix[];
|
|
3140
|
+
}>;
|
|
3141
|
+
|
|
3142
|
+
declare function crawlUrl(params: {
|
|
3143
|
+
url: string;
|
|
3144
|
+
}): Promise<ToolResult>;
|
|
3145
|
+
declare function extractMeta(params: {
|
|
3146
|
+
html: string;
|
|
3147
|
+
url: string;
|
|
3148
|
+
}): Promise<ToolResult>;
|
|
3149
|
+
declare function analyzeHeadings(params: {
|
|
3150
|
+
html: string;
|
|
3151
|
+
}): Promise<ToolResult>;
|
|
3152
|
+
declare function extractImages(params: {
|
|
3153
|
+
html: string;
|
|
3154
|
+
}): Promise<ToolResult>;
|
|
3155
|
+
declare function extractLinks(params: {
|
|
3156
|
+
html: string;
|
|
3157
|
+
baseUrl: string;
|
|
3158
|
+
}): Promise<ToolResult>;
|
|
3159
|
+
declare function extractSchema(params: {
|
|
3160
|
+
html: string;
|
|
3161
|
+
}): Promise<ToolResult>;
|
|
3162
|
+
declare function checkRobots(params: {
|
|
3163
|
+
url: string;
|
|
3164
|
+
}): Promise<ToolResult>;
|
|
3165
|
+
declare function checkSitemap(params: {
|
|
3166
|
+
url: string;
|
|
3167
|
+
}): Promise<ToolResult>;
|
|
3168
|
+
|
|
3169
|
+
declare function readFile(params: {
|
|
3170
|
+
path: string;
|
|
3171
|
+
cwd?: string;
|
|
3172
|
+
}): Promise<ToolResult>;
|
|
3173
|
+
declare function writeFile(params: {
|
|
3174
|
+
path: string;
|
|
3175
|
+
content: string;
|
|
3176
|
+
cwd?: string;
|
|
3177
|
+
}): Promise<ToolResult>;
|
|
3178
|
+
declare function listFiles(params: {
|
|
3179
|
+
path: string;
|
|
3180
|
+
cwd?: string;
|
|
3181
|
+
pattern?: string;
|
|
3182
|
+
recursive?: boolean;
|
|
3183
|
+
}): Promise<ToolResult>;
|
|
3184
|
+
declare function detectFramework$1(params: {
|
|
3185
|
+
cwd?: string;
|
|
3186
|
+
}): Promise<ToolResult>;
|
|
3187
|
+
declare function findHtmlEntry(params: {
|
|
3188
|
+
cwd?: string;
|
|
3189
|
+
}): Promise<ToolResult>;
|
|
3190
|
+
declare function findPageFiles(params: {
|
|
3191
|
+
cwd?: string;
|
|
3192
|
+
framework?: string;
|
|
3193
|
+
}): Promise<ToolResult>;
|
|
3194
|
+
|
|
3195
|
+
declare function analyzeUrl(params: {
|
|
3196
|
+
url: string;
|
|
3197
|
+
}): Promise<ToolResult>;
|
|
3198
|
+
|
|
3199
|
+
declare const tools: Record<string, ToolFunction>;
|
|
3200
|
+
|
|
3201
|
+
/**
|
|
3202
|
+
* Git Commit Helper
|
|
3203
|
+
*
|
|
3204
|
+
* Creates conventional commits for SEO fixes with proper co-authoring.
|
|
3205
|
+
* Supports GitHub Pages and various static site generators.
|
|
3206
|
+
*/
|
|
3207
|
+
interface CommitConfig {
|
|
3208
|
+
systemName?: string;
|
|
3209
|
+
systemEmail?: string;
|
|
3210
|
+
dryRun?: boolean;
|
|
3211
|
+
}
|
|
3212
|
+
interface ConventionalCommit {
|
|
3213
|
+
type: 'fix' | 'feat' | 'docs' | 'style' | 'refactor' | 'perf' | 'chore';
|
|
3214
|
+
scope?: string;
|
|
3215
|
+
description: string;
|
|
3216
|
+
body?: string;
|
|
3217
|
+
breaking?: boolean;
|
|
3218
|
+
issues?: string[];
|
|
3219
|
+
}
|
|
3220
|
+
interface SEOFixCommit {
|
|
3221
|
+
category: string;
|
|
3222
|
+
issues: string[];
|
|
3223
|
+
filesChanged: string[];
|
|
3224
|
+
description: string;
|
|
3225
|
+
}
|
|
3226
|
+
/**
|
|
3227
|
+
* Formats a conventional commit message
|
|
3228
|
+
*/
|
|
3229
|
+
declare function formatConventionalCommit(commit: ConventionalCommit): string;
|
|
3230
|
+
/**
|
|
3231
|
+
* Formats a commit message for SEO fixes
|
|
3232
|
+
*/
|
|
3233
|
+
declare function formatSEOCommitMessage(fix: SEOFixCommit, config?: CommitConfig): string;
|
|
3234
|
+
/**
|
|
3235
|
+
* Creates a git commit with the SEO fix
|
|
3236
|
+
*/
|
|
3237
|
+
declare function createSEOCommit(fix: SEOFixCommit, config?: CommitConfig): Promise<{
|
|
3238
|
+
success: boolean;
|
|
3239
|
+
hash?: string;
|
|
3240
|
+
error?: string;
|
|
3241
|
+
}>;
|
|
3242
|
+
/**
|
|
3243
|
+
* Creates multiple commits, one per category
|
|
3244
|
+
*/
|
|
3245
|
+
declare function createSEOCommits(fixes: SEOFixCommit[], config?: CommitConfig): Promise<{
|
|
3246
|
+
commits: Array<{
|
|
3247
|
+
fix: SEOFixCommit;
|
|
3248
|
+
result: Awaited<ReturnType<typeof createSEOCommit>>;
|
|
3249
|
+
}>;
|
|
3250
|
+
}>;
|
|
3251
|
+
/**
|
|
3252
|
+
* Checks if the current directory is a git repository
|
|
3253
|
+
*/
|
|
3254
|
+
declare function isGitRepo(dir?: string): boolean;
|
|
3255
|
+
/**
|
|
3256
|
+
* Initializes a git repository if not already initialized
|
|
3257
|
+
*/
|
|
3258
|
+
declare function ensureGitRepo(dir?: string): Promise<void>;
|
|
3259
|
+
/**
|
|
3260
|
+
* Gets the current git user config
|
|
3261
|
+
*/
|
|
3262
|
+
declare function getGitUser(): {
|
|
3263
|
+
name?: string;
|
|
3264
|
+
email?: string;
|
|
3265
|
+
};
|
|
3266
|
+
/**
|
|
3267
|
+
* Detects if this is a GitHub Pages repository
|
|
3268
|
+
*/
|
|
3269
|
+
declare function detectGitHubPages(dir: string): {
|
|
3270
|
+
isGitHubPages: boolean;
|
|
3271
|
+
type?: 'jekyll' | 'static' | 'docs' | 'custom';
|
|
3272
|
+
baseUrl?: string;
|
|
3273
|
+
};
|
|
3274
|
+
/**
|
|
3275
|
+
* Generates a summary of commits made
|
|
3276
|
+
*/
|
|
3277
|
+
declare function generateCommitSummary(commits: Array<{
|
|
3278
|
+
fix: SEOFixCommit;
|
|
3279
|
+
result: {
|
|
3280
|
+
success: boolean;
|
|
3281
|
+
hash?: string;
|
|
3282
|
+
error?: string;
|
|
3283
|
+
};
|
|
3284
|
+
}>): string;
|
|
3285
|
+
declare const COMMIT_TYPES: readonly [{
|
|
3286
|
+
readonly type: "fix";
|
|
3287
|
+
readonly description: "Bug fix (SEO issue correction)";
|
|
3288
|
+
}, {
|
|
3289
|
+
readonly type: "feat";
|
|
3290
|
+
readonly description: "New feature (schema, OG tags, etc.)";
|
|
3291
|
+
}, {
|
|
3292
|
+
readonly type: "docs";
|
|
3293
|
+
readonly description: "Documentation update";
|
|
3294
|
+
}, {
|
|
3295
|
+
readonly type: "style";
|
|
3296
|
+
readonly description: "Code style changes (formatting)";
|
|
3297
|
+
}, {
|
|
3298
|
+
readonly type: "refactor";
|
|
3299
|
+
readonly description: "Code restructuring";
|
|
3300
|
+
}, {
|
|
3301
|
+
readonly type: "perf";
|
|
3302
|
+
readonly description: "Performance improvement";
|
|
3303
|
+
}, {
|
|
3304
|
+
readonly type: "chore";
|
|
3305
|
+
readonly description: "Maintenance task";
|
|
3306
|
+
}];
|
|
3307
|
+
declare const SEO_SCOPES: readonly ["seo", "meta", "og", "schema", "images", "links", "content", "security", "mobile", "i18n", "perf"];
|
|
3308
|
+
|
|
3309
|
+
/**
|
|
3310
|
+
* PR Helper
|
|
3311
|
+
*
|
|
3312
|
+
* Creates pull requests for SEO fixes using GitHub CLI.
|
|
3313
|
+
* Generates formatted PR titles, bodies, and handles branch management.
|
|
3314
|
+
*/
|
|
3315
|
+
|
|
3316
|
+
declare const execAsync: typeof exec.__promisify__;
|
|
3317
|
+
interface SEOFixSummary {
|
|
3318
|
+
category: string;
|
|
3319
|
+
issues: string[];
|
|
3320
|
+
filesCount: number;
|
|
3321
|
+
}
|
|
3322
|
+
interface PRConfig {
|
|
3323
|
+
scoreBefore?: number;
|
|
3324
|
+
scoreAfter?: number;
|
|
3325
|
+
reviewers?: string[];
|
|
3326
|
+
assignees?: string[];
|
|
3327
|
+
draft?: boolean;
|
|
3328
|
+
}
|
|
3329
|
+
interface PRDescription {
|
|
3330
|
+
title: string;
|
|
3331
|
+
body: string;
|
|
3332
|
+
labels: string[];
|
|
3333
|
+
reviewers?: string[];
|
|
3334
|
+
assignees?: string[];
|
|
3335
|
+
}
|
|
3336
|
+
interface CreatePROptions {
|
|
3337
|
+
title: string;
|
|
3338
|
+
body: string;
|
|
3339
|
+
baseBranch: string;
|
|
3340
|
+
headBranch: string;
|
|
3341
|
+
createBranch?: boolean;
|
|
3342
|
+
labels?: string[];
|
|
3343
|
+
reviewers?: string[];
|
|
3344
|
+
assignees?: string[];
|
|
3345
|
+
draft?: boolean;
|
|
3346
|
+
dryRun?: boolean;
|
|
3347
|
+
}
|
|
3348
|
+
interface PRResult {
|
|
3349
|
+
success: boolean;
|
|
3350
|
+
url?: string;
|
|
3351
|
+
number?: number;
|
|
3352
|
+
error?: string;
|
|
3353
|
+
dryRun?: boolean;
|
|
3354
|
+
}
|
|
3355
|
+
interface ExecOptions {
|
|
3356
|
+
execAsync?: typeof execAsync;
|
|
3357
|
+
}
|
|
3358
|
+
/**
|
|
3359
|
+
* Formats a PR title based on the fixes
|
|
3360
|
+
*/
|
|
3361
|
+
declare function formatPRTitle(fixes: SEOFixSummary[]): string;
|
|
3362
|
+
/**
|
|
3363
|
+
* Formats the PR body with detailed information
|
|
3364
|
+
*/
|
|
3365
|
+
declare function formatPRBody(fixes: SEOFixSummary[], options?: {
|
|
3366
|
+
scoreBefore?: number;
|
|
3367
|
+
scoreAfter?: number;
|
|
3368
|
+
}): string;
|
|
3369
|
+
/**
|
|
3370
|
+
* Generates complete PR description including title, body, and labels
|
|
3371
|
+
*/
|
|
3372
|
+
declare function generatePRDescription(fixes: SEOFixSummary[], config?: PRConfig): PRDescription;
|
|
3373
|
+
/**
|
|
3374
|
+
* Creates a pull request using GitHub CLI
|
|
3375
|
+
*/
|
|
3376
|
+
declare function createPullRequest(options: CreatePROptions, deps?: ExecOptions): Promise<PRResult>;
|
|
3377
|
+
/**
|
|
3378
|
+
* Generates a branch name for SEO fixes
|
|
3379
|
+
*/
|
|
3380
|
+
declare function generateBranchName(prefix?: string): string;
|
|
3381
|
+
/**
|
|
3382
|
+
* Checks if gh CLI is available and authenticated
|
|
3383
|
+
*/
|
|
3384
|
+
declare function checkGitHubCLI(deps?: ExecOptions): Promise<{
|
|
3385
|
+
available: boolean;
|
|
3386
|
+
authenticated: boolean;
|
|
3387
|
+
error?: string;
|
|
3388
|
+
}>;
|
|
3389
|
+
|
|
3390
|
+
/**
|
|
3391
|
+
* Scheduled Audit Module
|
|
3392
|
+
*
|
|
3393
|
+
* Handles scheduled execution of SEO audits with optional auto-fix PR creation.
|
|
3394
|
+
* Can be used from Edge Functions, CLI cron jobs, or other scheduling mechanisms.
|
|
3395
|
+
*/
|
|
3396
|
+
type AuditSchedule = 'manual' | 'daily' | 'weekly' | 'on-demand';
|
|
3397
|
+
interface ScheduledAuditConfig {
|
|
3398
|
+
projectId: string;
|
|
3399
|
+
url: string;
|
|
3400
|
+
schedule: AuditSchedule;
|
|
3401
|
+
lastRunAt?: string;
|
|
3402
|
+
previousScore?: number;
|
|
3403
|
+
autoFix?: boolean;
|
|
3404
|
+
baseBranch?: string;
|
|
3405
|
+
generateFixes?: boolean;
|
|
3406
|
+
}
|
|
3407
|
+
interface ScheduledAuditResult {
|
|
3408
|
+
success: boolean;
|
|
3409
|
+
projectId: string;
|
|
3410
|
+
score?: number;
|
|
3411
|
+
scoreChange?: number;
|
|
3412
|
+
issuesFound?: number;
|
|
3413
|
+
fixesGenerated?: number;
|
|
3414
|
+
prCreated?: boolean;
|
|
3415
|
+
prUrl?: string;
|
|
3416
|
+
prNumber?: number;
|
|
3417
|
+
error?: string;
|
|
3418
|
+
completedAt: string;
|
|
3419
|
+
nextRunAt?: string | null;
|
|
3420
|
+
}
|
|
3421
|
+
/**
|
|
3422
|
+
* Determines if an audit should run based on schedule and last run time
|
|
3423
|
+
*/
|
|
3424
|
+
declare function shouldRunAudit(config: ScheduledAuditConfig): boolean;
|
|
3425
|
+
/**
|
|
3426
|
+
* Calculates the next scheduled run time
|
|
3427
|
+
*/
|
|
3428
|
+
declare function calculateNextRun(schedule: AuditSchedule): string | null;
|
|
3429
|
+
/**
|
|
3430
|
+
* Runs a scheduled audit with optional auto-fix PR creation
|
|
3431
|
+
*/
|
|
3432
|
+
declare function runScheduledAudit(config: ScheduledAuditConfig): Promise<ScheduledAuditResult>;
|
|
3433
|
+
|
|
3434
|
+
/**
|
|
3435
|
+
* Alerts Module
|
|
3436
|
+
*
|
|
3437
|
+
* Sends notifications via Slack, Discord, and email webhooks when SEO events occur.
|
|
3438
|
+
*/
|
|
3439
|
+
type AlertType = 'error' | 'score_drop' | 'weekly_report' | 'pr_created';
|
|
3440
|
+
type AlertChannel = 'slack' | 'discord' | 'email';
|
|
3441
|
+
type AlertSeverity = 'info' | 'success' | 'warning' | 'error';
|
|
3442
|
+
interface AlertConfig {
|
|
3443
|
+
type: AlertChannel;
|
|
3444
|
+
webhookUrl: string;
|
|
3445
|
+
on: AlertType[];
|
|
3446
|
+
scoreDropThreshold?: number;
|
|
3447
|
+
}
|
|
3448
|
+
interface AuditAlertPayload {
|
|
3449
|
+
projectId: string;
|
|
3450
|
+
projectName: string;
|
|
3451
|
+
url: string;
|
|
3452
|
+
score: number;
|
|
3453
|
+
previousScore?: number;
|
|
3454
|
+
issuesFound: number;
|
|
3455
|
+
errorCount?: number;
|
|
3456
|
+
prUrl?: string;
|
|
3457
|
+
prNumber?: number;
|
|
3458
|
+
timestamp: string;
|
|
3459
|
+
}
|
|
3460
|
+
interface AlertMessage {
|
|
3461
|
+
title: string;
|
|
3462
|
+
body: string;
|
|
3463
|
+
severity: AlertSeverity;
|
|
3464
|
+
url?: string;
|
|
3465
|
+
}
|
|
3466
|
+
interface AlertResult {
|
|
3467
|
+
success: boolean;
|
|
3468
|
+
skipped?: boolean;
|
|
3469
|
+
error?: string;
|
|
3470
|
+
}
|
|
3471
|
+
/**
|
|
3472
|
+
* Formats an alert message based on type and payload
|
|
3473
|
+
*/
|
|
3474
|
+
declare function formatAlertMessage(type: AlertType, payload: AuditAlertPayload): AlertMessage;
|
|
3475
|
+
/**
|
|
3476
|
+
* Determines if an alert should be sent based on config and payload
|
|
3477
|
+
*/
|
|
3478
|
+
declare function shouldSendAlert(config: AlertConfig, type: AlertType, payload?: AuditAlertPayload): boolean;
|
|
3479
|
+
/**
|
|
3480
|
+
* Sends an alert to Slack webhook
|
|
3481
|
+
*/
|
|
3482
|
+
declare function sendSlackAlert(webhookUrl: string, type: AlertType, payload: AuditAlertPayload): Promise<AlertResult>;
|
|
3483
|
+
/**
|
|
3484
|
+
* Sends an alert to Discord webhook
|
|
3485
|
+
*/
|
|
3486
|
+
declare function sendDiscordAlert(webhookUrl: string, type: AlertType, payload: AuditAlertPayload): Promise<AlertResult>;
|
|
3487
|
+
/**
|
|
3488
|
+
* Sends an alert based on config
|
|
3489
|
+
*/
|
|
3490
|
+
declare function sendAlert(config: AlertConfig, type: AlertType, payload: AuditAlertPayload): Promise<AlertResult>;
|
|
3491
|
+
/**
|
|
3492
|
+
* Sends alerts to multiple configs
|
|
3493
|
+
*/
|
|
3494
|
+
declare function sendAlerts(configs: AlertConfig[], type: AlertType, payload: AuditAlertPayload): Promise<AlertResult[]>;
|
|
3495
|
+
|
|
3496
|
+
/**
|
|
3497
|
+
* Report Generator
|
|
3498
|
+
*
|
|
3499
|
+
* Generates HTML and PDF reports for SEO audits with white-label branding support.
|
|
3500
|
+
*/
|
|
3501
|
+
interface ReportBranding {
|
|
3502
|
+
companyName?: string;
|
|
3503
|
+
logoUrl?: string;
|
|
3504
|
+
primaryColor?: string;
|
|
3505
|
+
accentColor?: string;
|
|
3506
|
+
whiteLabel?: boolean;
|
|
3507
|
+
contactEmail?: string;
|
|
3508
|
+
websiteUrl?: string;
|
|
3509
|
+
}
|
|
3510
|
+
interface ReportConfig {
|
|
3511
|
+
branding?: ReportBranding;
|
|
3512
|
+
includeExecutiveSummary?: boolean;
|
|
3513
|
+
includeRecommendations?: boolean;
|
|
3514
|
+
includePageDetails?: boolean;
|
|
3515
|
+
maxIssues?: number;
|
|
3516
|
+
}
|
|
3517
|
+
interface AuditIssueData {
|
|
3518
|
+
code: string;
|
|
3519
|
+
severity: 'error' | 'warning' | 'notice';
|
|
3520
|
+
category: string;
|
|
3521
|
+
title: string;
|
|
3522
|
+
affectedUrls: string[];
|
|
3523
|
+
description?: string;
|
|
3524
|
+
howToFix?: string;
|
|
3525
|
+
}
|
|
3526
|
+
interface ReportPageData {
|
|
3527
|
+
url: string;
|
|
3528
|
+
score: number;
|
|
3529
|
+
issues: number;
|
|
3530
|
+
}
|
|
3531
|
+
interface AuditReportData {
|
|
3532
|
+
url: string;
|
|
3533
|
+
domain: string;
|
|
3534
|
+
timestamp: string;
|
|
3535
|
+
score: number;
|
|
3536
|
+
healthScores: {
|
|
3537
|
+
overall: number;
|
|
3538
|
+
crawlability: number;
|
|
3539
|
+
indexability: number;
|
|
3540
|
+
onPage: number;
|
|
3541
|
+
content: number;
|
|
3542
|
+
links: number;
|
|
3543
|
+
performance: number;
|
|
3544
|
+
security: number;
|
|
3545
|
+
aiReadiness: number;
|
|
3546
|
+
social: number;
|
|
3547
|
+
localSeo: number;
|
|
3548
|
+
};
|
|
3549
|
+
summary: {
|
|
3550
|
+
errors: number;
|
|
3551
|
+
warnings: number;
|
|
3552
|
+
notices: number;
|
|
3553
|
+
passed: number;
|
|
3554
|
+
};
|
|
3555
|
+
issues: AuditIssueData[];
|
|
3556
|
+
pages: ReportPageData[];
|
|
3557
|
+
}
|
|
3558
|
+
/**
|
|
3559
|
+
* Generates an HTML report from audit data
|
|
3560
|
+
*/
|
|
3561
|
+
declare function generateHTMLReport(data: AuditReportData, config?: ReportConfig): string;
|
|
3562
|
+
/**
|
|
3563
|
+
* Generates a PDF report from audit data
|
|
3564
|
+
* Uses the HTML report as a base and converts to PDF
|
|
3565
|
+
*/
|
|
3566
|
+
declare function generatePDFReport(data: AuditReportData, config?: ReportConfig): Promise<Buffer>;
|
|
3567
|
+
|
|
3568
|
+
/**
|
|
3569
|
+
* GEO (Generative Engine Optimization) Tracker
|
|
3570
|
+
*
|
|
3571
|
+
* Tracks brand visibility in LLM responses to understand how AI models
|
|
3572
|
+
* recommend or mention your brand for relevant queries.
|
|
3573
|
+
*/
|
|
3574
|
+
type MentionType = 'brand' | 'domain' | 'alternative';
|
|
3575
|
+
type LLMProvider = 'openai' | 'anthropic' | 'google' | 'perplexity';
|
|
3576
|
+
type Sentiment = 'positive' | 'negative' | 'neutral';
|
|
3577
|
+
interface BrandConfig {
|
|
3578
|
+
brandName: string;
|
|
3579
|
+
domains: string[];
|
|
3580
|
+
alternativeNames?: string[];
|
|
3581
|
+
}
|
|
3582
|
+
interface Mention {
|
|
3583
|
+
type: MentionType;
|
|
3584
|
+
text: string;
|
|
3585
|
+
position: number;
|
|
3586
|
+
context: string;
|
|
3587
|
+
}
|
|
3588
|
+
interface GEOQuery {
|
|
3589
|
+
keyword: string;
|
|
3590
|
+
brand: BrandConfig;
|
|
3591
|
+
providers: LLMProvider[];
|
|
3592
|
+
}
|
|
3593
|
+
interface GEOResult {
|
|
3594
|
+
provider: LLMProvider;
|
|
3595
|
+
keyword: string;
|
|
3596
|
+
mentioned: boolean;
|
|
3597
|
+
position: number | null;
|
|
3598
|
+
sentiment: Sentiment | null;
|
|
3599
|
+
score: number;
|
|
3600
|
+
timestamp: string;
|
|
3601
|
+
contextSnippet?: string;
|
|
3602
|
+
error?: string;
|
|
3603
|
+
}
|
|
3604
|
+
interface ParsedResponse {
|
|
3605
|
+
mentioned: boolean;
|
|
3606
|
+
position: number | null;
|
|
3607
|
+
sentiment: Sentiment | null;
|
|
3608
|
+
contextSnippet: string | null;
|
|
3609
|
+
}
|
|
3610
|
+
interface TrackingOptions {
|
|
3611
|
+
fetch?: typeof fetch;
|
|
3612
|
+
}
|
|
3613
|
+
/**
|
|
3614
|
+
* Detects brand mentions in text
|
|
3615
|
+
*/
|
|
3616
|
+
declare function detectMentions(text: string, config: BrandConfig): Mention[];
|
|
3617
|
+
/**
|
|
3618
|
+
* Score a mention based on position, type, and context
|
|
3619
|
+
*/
|
|
3620
|
+
declare function scoreMention(mention: Mention | null): number;
|
|
3621
|
+
/**
|
|
3622
|
+
* Parse an LLM response to extract mention details
|
|
3623
|
+
*/
|
|
3624
|
+
declare function parseGEOResponse(response: string, config: BrandConfig): ParsedResponse;
|
|
3625
|
+
/**
|
|
3626
|
+
* Track LLM visibility for a brand across multiple providers
|
|
3627
|
+
*/
|
|
3628
|
+
declare function trackLLMVisibility(query: GEOQuery, options?: TrackingOptions): Promise<GEOResult[]>;
|
|
3629
|
+
|
|
3630
|
+
/**
|
|
3631
|
+
* GEO History Module
|
|
3632
|
+
*
|
|
3633
|
+
* Tracks LLM visibility over time, detects changes, generates reports,
|
|
3634
|
+
* and compares against competitors.
|
|
3635
|
+
*/
|
|
3636
|
+
|
|
3637
|
+
type GEOAlertType = 'new_mention' | 'lost_mention' | 'position_improved' | 'position_dropped' | 'sentiment_changed' | 'score_improved' | 'score_dropped';
|
|
3638
|
+
type TrendDirection = 'improving' | 'declining' | 'stable' | 'unknown';
|
|
3639
|
+
interface GEOHistory {
|
|
3640
|
+
brandName?: string;
|
|
3641
|
+
results: GEOResult[];
|
|
3642
|
+
maxResults?: number;
|
|
3643
|
+
}
|
|
3644
|
+
interface GEOHistoryOptions {
|
|
3645
|
+
brandName?: string;
|
|
3646
|
+
maxResults?: number;
|
|
3647
|
+
}
|
|
3648
|
+
interface GEOTrend {
|
|
3649
|
+
direction: TrendDirection;
|
|
3650
|
+
averageScore: number;
|
|
3651
|
+
mentionRate: number;
|
|
3652
|
+
dataPoints: number;
|
|
3653
|
+
firstScore?: number;
|
|
3654
|
+
lastScore?: number;
|
|
3655
|
+
}
|
|
3656
|
+
interface GEOAlert {
|
|
3657
|
+
type: GEOAlertType;
|
|
3658
|
+
message: string;
|
|
3659
|
+
provider: LLMProvider;
|
|
3660
|
+
keyword: string;
|
|
3661
|
+
previousValue?: any;
|
|
3662
|
+
currentValue?: any;
|
|
3663
|
+
timestamp: string;
|
|
3664
|
+
}
|
|
3665
|
+
interface GEOReport {
|
|
3666
|
+
brandName?: string;
|
|
3667
|
+
totalQueries: number;
|
|
3668
|
+
mentionRate: number;
|
|
3669
|
+
averageScore: number;
|
|
3670
|
+
byProvider: Record<string, ProviderStats>;
|
|
3671
|
+
byKeyword: Record<string, KeywordStats>;
|
|
3672
|
+
generatedAt: string;
|
|
3673
|
+
}
|
|
3674
|
+
interface ProviderStats {
|
|
3675
|
+
queries: number;
|
|
3676
|
+
mentions: number;
|
|
3677
|
+
mentionRate: number;
|
|
3678
|
+
averageScore: number;
|
|
3679
|
+
averagePosition: number | null;
|
|
3680
|
+
}
|
|
3681
|
+
interface KeywordStats {
|
|
3682
|
+
queries: number;
|
|
3683
|
+
mentions: number;
|
|
3684
|
+
mentionRate: number;
|
|
3685
|
+
averageScore: number;
|
|
3686
|
+
}
|
|
3687
|
+
interface CompetitorComparison {
|
|
3688
|
+
brand: string;
|
|
3689
|
+
competitor: string;
|
|
3690
|
+
brandMentionRate: number;
|
|
3691
|
+
competitorMentionRate: number;
|
|
3692
|
+
brandAverageScore: number;
|
|
3693
|
+
competitorAverageScore: number;
|
|
3694
|
+
brandAveragePosition: number | null;
|
|
3695
|
+
competitorAveragePosition: number | null;
|
|
3696
|
+
winner: string;
|
|
3697
|
+
}
|
|
3698
|
+
/**
|
|
3699
|
+
* Create a new GEO history instance
|
|
3700
|
+
*/
|
|
3701
|
+
declare function createGEOHistory(options?: GEOHistoryOptions): GEOHistory;
|
|
3702
|
+
/**
|
|
3703
|
+
* Add a tracking result to history
|
|
3704
|
+
*/
|
|
3705
|
+
declare function addTrackingResult(history: GEOHistory, result: GEOResult): GEOHistory;
|
|
3706
|
+
/**
|
|
3707
|
+
* Get visibility trend for a specific provider and keyword
|
|
3708
|
+
*/
|
|
3709
|
+
declare function getVisibilityTrend(history: GEOHistory, provider: LLMProvider, keyword: string): GEOTrend;
|
|
3710
|
+
/**
|
|
3711
|
+
* Detect visibility changes between history and new result
|
|
3712
|
+
*/
|
|
3713
|
+
declare function detectVisibilityChanges(history: GEOHistory, newResult: GEOResult): GEOAlert[];
|
|
3714
|
+
/**
|
|
3715
|
+
* Generate a summary report from history
|
|
3716
|
+
*/
|
|
3717
|
+
declare function generateGEOReport(history: GEOHistory): GEOReport;
|
|
3718
|
+
/**
|
|
3719
|
+
* Compare brand visibility against a competitor
|
|
3720
|
+
*/
|
|
3721
|
+
declare function compareCompetitorVisibility(brandHistory: GEOHistory, competitorName: string, competitorResults: GEOResult[]): CompetitorComparison;
|
|
3722
|
+
|
|
3723
|
+
/**
|
|
3724
|
+
* GEO Content Module
|
|
3725
|
+
*
|
|
3726
|
+
* Generate AI-citation-friendly content with structured data,
|
|
3727
|
+
* comparison tables, FAQs, and key facts formatted for LLM parsing.
|
|
3728
|
+
*/
|
|
3729
|
+
interface KeyFact {
|
|
3730
|
+
label: string;
|
|
3731
|
+
value: string | number;
|
|
3732
|
+
}
|
|
3733
|
+
interface FAQItem {
|
|
3734
|
+
question: string;
|
|
3735
|
+
answer: string;
|
|
3736
|
+
}
|
|
3737
|
+
interface ComparisonRow {
|
|
3738
|
+
feature: string;
|
|
3739
|
+
brand: string | boolean;
|
|
3740
|
+
competitor?: string | boolean;
|
|
3741
|
+
competitors?: Record<string, string | boolean>;
|
|
3742
|
+
}
|
|
3743
|
+
interface ComparisonConfig {
|
|
3744
|
+
brandName: string;
|
|
3745
|
+
competitorName?: string;
|
|
3746
|
+
competitorNames?: string[];
|
|
3747
|
+
useCheckmarks?: boolean;
|
|
3748
|
+
}
|
|
3749
|
+
interface AIContentConfig {
|
|
3750
|
+
productName: string;
|
|
3751
|
+
tagline?: string;
|
|
3752
|
+
description?: string;
|
|
3753
|
+
keyFacts?: KeyFact[];
|
|
3754
|
+
faqs?: FAQItem[];
|
|
3755
|
+
comparison?: {
|
|
3756
|
+
competitorName: string;
|
|
3757
|
+
rows: ComparisonRow[];
|
|
3758
|
+
};
|
|
3759
|
+
}
|
|
3760
|
+
interface KeyFactsOptions {
|
|
3761
|
+
format?: 'bullets' | 'paragraph' | 'inline';
|
|
3762
|
+
}
|
|
3763
|
+
interface FAQSchemaOptions {
|
|
3764
|
+
format?: 'json-ld' | 'markdown';
|
|
3765
|
+
}
|
|
3766
|
+
interface OptimizeOptions {
|
|
3767
|
+
brandName?: string;
|
|
3768
|
+
highlightNumbers?: boolean;
|
|
3769
|
+
structureLists?: boolean;
|
|
3770
|
+
emphasizeBrand?: boolean;
|
|
3771
|
+
addSourcePlaceholder?: boolean;
|
|
3772
|
+
}
|
|
3773
|
+
/**
|
|
3774
|
+
* Generate formatted key facts for AI citation
|
|
3775
|
+
*/
|
|
3776
|
+
declare function generateKeyFacts(facts: KeyFact[], options?: KeyFactsOptions): string;
|
|
3777
|
+
/**
|
|
3778
|
+
* Generate FAQ schema (JSON-LD or Markdown)
|
|
3779
|
+
*/
|
|
3780
|
+
declare function generateFAQSchema(faqs: FAQItem[], options?: FAQSchemaOptions): string;
|
|
3781
|
+
/**
|
|
3782
|
+
* Generate comparison table in markdown
|
|
3783
|
+
*/
|
|
3784
|
+
declare function generateComparisonTable(rows: ComparisonRow[], config: ComparisonConfig): string;
|
|
3785
|
+
/**
|
|
3786
|
+
* Generate complete AI-citable content block
|
|
3787
|
+
*/
|
|
3788
|
+
declare function generateAICitableContent(config: AIContentConfig): string;
|
|
3789
|
+
/**
|
|
3790
|
+
* Optimize existing content for AI citation
|
|
3791
|
+
*/
|
|
3792
|
+
declare function optimizeForAI(content: string, options?: OptimizeOptions): string;
|
|
3793
|
+
|
|
3794
|
+
/**
|
|
3795
|
+
* Framework Detection
|
|
3796
|
+
*
|
|
3797
|
+
* Detects web frameworks from:
|
|
3798
|
+
* 1. HTML signatures (data attributes, meta tags, scripts)
|
|
3799
|
+
* 2. package.json dependencies
|
|
3800
|
+
* 3. File structure patterns
|
|
3801
|
+
*/
|
|
3802
|
+
type Framework = 'react' | 'nextjs' | 'vue' | 'nuxt' | 'angular' | 'svelte' | 'sveltekit' | 'astro' | 'remix' | 'gatsby' | 'rails' | 'laravel' | 'django' | 'wordpress' | 'unknown';
|
|
3803
|
+
interface FrameworkInfo {
|
|
3804
|
+
framework: Framework;
|
|
3805
|
+
version?: string;
|
|
3806
|
+
confidence: 'high' | 'medium' | 'low';
|
|
3807
|
+
detected_from: 'html' | 'package.json' | 'files' | 'headers';
|
|
3808
|
+
meta_framework?: Framework;
|
|
3809
|
+
}
|
|
3810
|
+
/**
|
|
3811
|
+
* Detect framework from HTML content
|
|
3812
|
+
*/
|
|
3813
|
+
declare function detectFromHtml(html: string): FrameworkInfo | null;
|
|
3814
|
+
/**
|
|
3815
|
+
* Detect framework from package.json content
|
|
3816
|
+
*/
|
|
3817
|
+
declare function detectFromPackageJson(packageJson: {
|
|
3818
|
+
dependencies?: Record<string, string>;
|
|
3819
|
+
devDependencies?: Record<string, string>;
|
|
3820
|
+
}): FrameworkInfo | null;
|
|
3821
|
+
/**
|
|
3822
|
+
* Detect framework from HTTP response headers
|
|
3823
|
+
*/
|
|
3824
|
+
declare function detectFromHeaders(headers: Record<string, string>): FrameworkInfo | null;
|
|
3825
|
+
/**
|
|
3826
|
+
* Combined detection using multiple sources
|
|
3827
|
+
*/
|
|
3828
|
+
declare function detectFramework(options: {
|
|
3829
|
+
html?: string;
|
|
3830
|
+
packageJson?: {
|
|
3831
|
+
dependencies?: Record<string, string>;
|
|
3832
|
+
devDependencies?: Record<string, string>;
|
|
3833
|
+
};
|
|
3834
|
+
headers?: Record<string, string>;
|
|
3835
|
+
files?: string[];
|
|
3836
|
+
}): FrameworkInfo;
|
|
3837
|
+
/**
|
|
3838
|
+
* Get human-readable framework name
|
|
3839
|
+
*/
|
|
3840
|
+
declare function getFrameworkDisplayName(framework: Framework): string;
|
|
3841
|
+
|
|
3842
|
+
/**
|
|
3843
|
+
* Framework-Specific SEO Suggestion Engine
|
|
3844
|
+
*
|
|
3845
|
+
* Loads recipe files and provides framework-specific SEO suggestions.
|
|
3846
|
+
* Works with both CLI and Web UI.
|
|
3847
|
+
*/
|
|
3848
|
+
|
|
3849
|
+
interface FrameworkCheck {
|
|
3850
|
+
code: string;
|
|
3851
|
+
severity: IssueSeverity;
|
|
3852
|
+
title: string;
|
|
3853
|
+
description: string;
|
|
3854
|
+
howToFix: string;
|
|
3855
|
+
impact?: string;
|
|
3856
|
+
detection?: {
|
|
3857
|
+
html_patterns?: string[];
|
|
3858
|
+
missing_content?: boolean;
|
|
3859
|
+
title_in_js?: boolean;
|
|
3860
|
+
title_not_in_html?: boolean;
|
|
3861
|
+
};
|
|
3862
|
+
app_router_only?: boolean;
|
|
3863
|
+
pages_router_only?: boolean;
|
|
3864
|
+
}
|
|
3865
|
+
interface FrameworkRecipe {
|
|
3866
|
+
framework: Framework;
|
|
3867
|
+
display_name: string;
|
|
3868
|
+
category: string;
|
|
3869
|
+
base_framework?: Framework;
|
|
3870
|
+
ssr_default: boolean;
|
|
3871
|
+
seo_challenges?: string[];
|
|
3872
|
+
seo_strengths?: string[];
|
|
3873
|
+
checks: FrameworkCheck[];
|
|
3874
|
+
performance_tips?: string[];
|
|
3875
|
+
migration_paths?: Record<string, {
|
|
3876
|
+
effort: string;
|
|
3877
|
+
benefits: string[];
|
|
3878
|
+
guide?: string;
|
|
3879
|
+
}>;
|
|
3880
|
+
recommended_plugins?: Record<string, string[]>;
|
|
3881
|
+
recommended_gems?: Record<string, string[]>;
|
|
3882
|
+
integrations?: string[];
|
|
3883
|
+
}
|
|
3884
|
+
/**
|
|
3885
|
+
* Load a recipe from embedded content or file system
|
|
3886
|
+
*/
|
|
3887
|
+
declare function loadRecipe(framework: Framework): Promise<FrameworkRecipe | null>;
|
|
3888
|
+
/**
|
|
3889
|
+
* Get framework-specific issues based on HTML analysis
|
|
3890
|
+
*/
|
|
3891
|
+
declare function getFrameworkIssues(frameworkInfo: FrameworkInfo, html: string, url: string): Promise<AuditIssue[]>;
|
|
3892
|
+
/**
|
|
3893
|
+
* Get framework-specific suggestions for fixing issues
|
|
3894
|
+
*/
|
|
3895
|
+
declare function getFrameworkSuggestions(frameworkInfo: FrameworkInfo, issueCode: string): Promise<string | null>;
|
|
3896
|
+
/**
|
|
3897
|
+
* Get all available checks for a framework
|
|
3898
|
+
*/
|
|
3899
|
+
declare function getFrameworkChecks(framework: Framework): Promise<FrameworkCheck[]>;
|
|
3900
|
+
/**
|
|
3901
|
+
* Get performance tips for a framework
|
|
3902
|
+
*/
|
|
3903
|
+
declare function getPerformanceTips(framework: Framework): Promise<string[]>;
|
|
3904
|
+
/**
|
|
3905
|
+
* Get SEO challenges for a framework
|
|
3906
|
+
*/
|
|
3907
|
+
declare function getSeoChallenges(framework: Framework): Promise<string[]>;
|
|
3908
|
+
/**
|
|
3909
|
+
* Get migration paths from current framework
|
|
3910
|
+
*/
|
|
3911
|
+
declare function getMigrationPaths(framework: Framework): Promise<Record<string, {
|
|
3912
|
+
effort: string;
|
|
3913
|
+
benefits: string[];
|
|
3914
|
+
guide?: string;
|
|
3915
|
+
}>>;
|
|
3916
|
+
/**
|
|
3917
|
+
* Get total number of framework-specific checks
|
|
3918
|
+
*/
|
|
3919
|
+
declare function getTotalFrameworkChecks(): Promise<number>;
|
|
3920
|
+
/**
|
|
3921
|
+
* Get framework summary for display
|
|
3922
|
+
*/
|
|
3923
|
+
declare function getFrameworkSummary(framework: Framework): Promise<{
|
|
3924
|
+
name: string;
|
|
3925
|
+
category: string;
|
|
3926
|
+
ssrDefault: boolean;
|
|
3927
|
+
checkCount: number;
|
|
3928
|
+
strengths: string[];
|
|
3929
|
+
challenges: string[];
|
|
3930
|
+
} | null>;
|
|
3931
|
+
/**
|
|
3932
|
+
* Embed recipe content for bundling (called at build time)
|
|
3933
|
+
*/
|
|
3934
|
+
declare function embedRecipe(framework: Framework, content: string): void;
|
|
3935
|
+
|
|
3936
|
+
/**
|
|
3937
|
+
* Framework Detection and SEO Recipes
|
|
3938
|
+
*
|
|
3939
|
+
* Provides framework-specific SEO suggestions for:
|
|
3940
|
+
* - React, Next.js, Gatsby, Remix
|
|
3941
|
+
* - Vue, Nuxt
|
|
3942
|
+
* - Angular
|
|
3943
|
+
* - Svelte, SvelteKit
|
|
3944
|
+
* - Astro
|
|
3945
|
+
* - Ruby on Rails
|
|
3946
|
+
* - Laravel, Django
|
|
3947
|
+
* - WordPress
|
|
3948
|
+
*
|
|
3949
|
+
* Usage:
|
|
3950
|
+
*
|
|
3951
|
+
* ```typescript
|
|
3952
|
+
* import { detectFramework, getFrameworkIssues } from './frameworks';
|
|
3953
|
+
*
|
|
3954
|
+
* // Detect framework from HTML
|
|
3955
|
+
* const frameworkInfo = detectFramework({ html });
|
|
3956
|
+
*
|
|
3957
|
+
* // Get framework-specific issues
|
|
3958
|
+
* const issues = await getFrameworkIssues(frameworkInfo, html, url);
|
|
3959
|
+
* ```
|
|
3960
|
+
*/
|
|
3961
|
+
|
|
3962
|
+
declare const SUPPORTED_FRAMEWORKS: readonly ["react", "nextjs", "vue", "nuxt", "angular", "svelte", "sveltekit", "astro", "remix", "gatsby", "rails", "laravel", "django", "wordpress"];
|
|
3963
|
+
|
|
3964
|
+
type index_Framework = Framework;
|
|
3965
|
+
type index_FrameworkCheck = FrameworkCheck;
|
|
3966
|
+
type index_FrameworkInfo = FrameworkInfo;
|
|
3967
|
+
type index_FrameworkRecipe = FrameworkRecipe;
|
|
3968
|
+
declare const index_SUPPORTED_FRAMEWORKS: typeof SUPPORTED_FRAMEWORKS;
|
|
3969
|
+
declare const index_detectFramework: typeof detectFramework;
|
|
3970
|
+
declare const index_detectFromHeaders: typeof detectFromHeaders;
|
|
3971
|
+
declare const index_detectFromHtml: typeof detectFromHtml;
|
|
3972
|
+
declare const index_detectFromPackageJson: typeof detectFromPackageJson;
|
|
3973
|
+
declare const index_embedRecipe: typeof embedRecipe;
|
|
3974
|
+
declare const index_getFrameworkChecks: typeof getFrameworkChecks;
|
|
3975
|
+
declare const index_getFrameworkDisplayName: typeof getFrameworkDisplayName;
|
|
3976
|
+
declare const index_getFrameworkIssues: typeof getFrameworkIssues;
|
|
3977
|
+
declare const index_getFrameworkSuggestions: typeof getFrameworkSuggestions;
|
|
3978
|
+
declare const index_getFrameworkSummary: typeof getFrameworkSummary;
|
|
3979
|
+
declare const index_getMigrationPaths: typeof getMigrationPaths;
|
|
3980
|
+
declare const index_getPerformanceTips: typeof getPerformanceTips;
|
|
3981
|
+
declare const index_getSeoChallenges: typeof getSeoChallenges;
|
|
3982
|
+
declare const index_getTotalFrameworkChecks: typeof getTotalFrameworkChecks;
|
|
3983
|
+
declare const index_loadRecipe: typeof loadRecipe;
|
|
3984
|
+
declare namespace index {
|
|
3985
|
+
export { type index_Framework as Framework, type index_FrameworkCheck as FrameworkCheck, type index_FrameworkInfo as FrameworkInfo, type index_FrameworkRecipe as FrameworkRecipe, index_SUPPORTED_FRAMEWORKS as SUPPORTED_FRAMEWORKS, index_detectFramework as detectFramework, index_detectFromHeaders as detectFromHeaders, index_detectFromHtml as detectFromHtml, index_detectFromPackageJson as detectFromPackageJson, index_embedRecipe as embedRecipe, index_getFrameworkChecks as getFrameworkChecks, index_getFrameworkDisplayName as getFrameworkDisplayName, index_getFrameworkIssues as getFrameworkIssues, index_getFrameworkSuggestions as getFrameworkSuggestions, index_getFrameworkSummary as getFrameworkSummary, index_getMigrationPaths as getMigrationPaths, index_getPerformanceTips as getPerformanceTips, index_getSeoChallenges as getSeoChallenges, index_getTotalFrameworkChecks as getTotalFrameworkChecks, index_loadRecipe as loadRecipe };
|
|
3986
|
+
}
|
|
3987
|
+
|
|
3988
|
+
/**
|
|
3989
|
+
* WASM Adapter
|
|
3990
|
+
*
|
|
3991
|
+
* This file creates the global RankCLI object that the WASM wrapper expects.
|
|
3992
|
+
* It adapts the async runFullAudit to a sync-compatible interface for VM execution.
|
|
3993
|
+
*
|
|
3994
|
+
* When this code is embedded in WASM and executed in a Node.js VM:
|
|
3995
|
+
* - The VM has limited async capabilities
|
|
3996
|
+
* - We provide a sync interface that queues work for the host
|
|
3997
|
+
*/
|
|
3998
|
+
|
|
3999
|
+
interface SyncAuditResult {
|
|
4000
|
+
success: boolean;
|
|
4001
|
+
score: number;
|
|
4002
|
+
issues: AuditIssue[];
|
|
4003
|
+
checksRun: number;
|
|
4004
|
+
tier: string;
|
|
4005
|
+
}
|
|
4006
|
+
/**
|
|
4007
|
+
* Synchronous audit function for VM execution
|
|
4008
|
+
* Only runs checks that don't require network requests
|
|
4009
|
+
*/
|
|
4010
|
+
declare function runSyncAudit(url: string, html: string, checksLimit: number): SyncAuditResult;
|
|
4011
|
+
|
|
4012
|
+
export { type AIContentConfig, type AIKeywordResearchOptions, type AgentDefinition, type AgentTool, type AlertChannel, type AlertConfig, type AlertMessage, type AlertResult, type AlertSeverity, type AlertType, type AuditAlertPayload, type AuditIssue, type AuditIssueData, type AuditOptions, type AuditPRResult, type AuditReport, type AuditReportData, type AuditRunnerOptions, type AuditRunnerResult, type AuditSchedule, type BlogPostConfig, type BrandConfig, type CIAction, type CIKeywordOptions, type CIKeywordResult, COMMIT_TYPES, type ChangelogConfig, type ChangelogResult, type CommitConfig, type ComparisonConfig, type ComparisonRow, type CompetitiveInsight, type CompetitiveSearchOptions, type CompetitiveSearchResult, type CompetitorComparison, type CompetitorKeywordResult, type CompetitorOverlap, type CompetitorTool, type ContentElements, type ContentGeneratorOptions, type ContentRecommendation, type ConventionalCommit, type CrawlResult, type CrawlStats, type CrawledPage, type CreateAuditPROptions, type CreatePROptions, type DataForSEOCredentials, type DiscoveredPage, type EnhancedToolIdea, type ExecOptions, type ExecuteOptions, type ExecutionResult, type FAQItem, type FAQSchemaOptions, type FeaturedSnippetAnalysis, type Fix, type FixFile, type FixGeneratorOptions, type FixResult, type FrameworkInfo$1 as FrameworkInfo, type FreeKeywordResult, type FreeToolIdea, type GA4Config, type GEOAlert, type GEOAlertType, type GEOHistory, type GEOHistoryOptions, type GEOQuery, type GEOReport, type GEOResult, type GEOTrend, type GSCConfig, type GSCCredentials, type GSCPerformanceData, type GSCQueryData, type GSCQueryResult, type GeneratedContent, type GeneratedFix, type HeadingStructure, type HeadlineAnalysis, type HealthScore, ISSUE_DEFINITIONS, type ImageInfo$1 as ImageInfo, type InjectionResult, type IntentAnalysis, type IssueCategory, type IssueDefinition, type IssueSeverity, type KeyFact, type KeyFactsOptions, type KeywordAction, type KeywordCluster, type KeywordData, type KeywordDensityAnalysis, type KeywordOpportunity, type KeywordRecommendation, type KeywordResearchOptions, type KeywordResearchResult, type KeywordStats, type KeywordTopic, type LLMJudgeOptions, type LLMProvider, LOCATION_CODES, type LSIKeyword, type LinkInfo, type Mention, type MentionType, type MetaData, type NGram, type NLPAnalysisResult, OG_IMAGE_SPECS, type OptimizeOptions, type PRConfig, type PRDescription, PRIORITY_WEIGHTS, type PRResult, type PageAudit, type PageData, type PageMeta, type PaidKeywordResult, type ParsedResponse, type PlanTier, type ProviderStats, type QuickWin, type ReadabilityResult, type ReadmeConfig, type ReadmeResult, type ReportBranding, type ReportConfig, type ReportData, type ReportPageData, type RouteInfo, type SEOAnalysisResult, type SEOFixCommit, type SEOFixSummary, type SEOIssue, type SEORecommendation, type SEOScore, SEO_SCOPES, SITE_PROFILE_QUESTIONS, type ScheduledAuditConfig, type ScheduledAuditResult, type SchemaData, type SearchIntent, type Sentiment, type SiteCrawlResult, type SiteProfile, type SiteSummary, type SnippetRecommendation, type SnippetType, type SocialMetaConfig, type SocialMetaFix, type SummarizerOptions, type TFIDFResult, type ToolFeasibilityScore, type ToolFunction, type ToolResult, type TopicClusterResult, type TopicModel, type TrackingOptions, type TrendDirection, type UncertaintyAssessment, type WizardQuestion, type WizardResponse, type WizardResult, type WizardSession, type WorkflowConfig, addTrackingResult, analyzeAnchorText, analyzeCanonicalAdvanced, analyzeClientRendering, analyzeContentFreshness, analyzeConversionElements, analyzeDOMStructure, analyzeEntitySEO, analyzeFeaturedSnippetPotential, analyzeFreshnessSignals, analyzeFunnelIntent, analyzeHeadings, analyzeHeadline, analyzeHreflang, analyzeImages, analyzeInteractiveTools, analyzeKeywordDensity, analyzeKeywordPlacement, analyzeKeywords, analyzeLinks, analyzeLocalSEO, analyzeMobile, analyzeModernImages, analyzeNavBoostSignals, analyzeOnPage, analyzePagination, analyzePerformance, analyzePlatformPresence, analyzeReadability, analyzeRedirectChain, analyzeRedirects, analyzeResponsiveImages, analyzeSERPPreview, analyzeSecurity, analyzeSecurityHeaders, analyzeSocialMeta, analyzeStructuredData, analyzeTopicalClusters, analyzeTrackerBloat, analyzeUrl, analyzeUrlSafety, applyFixes, buildGSCApiRequest, buildGSCRequest, calculateBM25, calculateTFIDF$1 as calculateKeywordTFIDF, calculateNextRun, calculateTFIDF, checkAIBotBlocking, checkAMP, checkAdsTxt, checkAppleTouchIcon, checkBalance, checkCertificate, checkDMARC, checkGitHubCLI, checkInternalRedirects, checkJSRenderingRatio, checkLlmsTxt, checkMobileResources, checkPlaintextEmails, checkRedirects, checkRobots, checkRobotsTxt, checkSPF, checkSitemap, classifyIntent, classifyIntents, clusterKeywordsByEmbedding, compareCompetitorVisibility, comparePeriods, completeWizard, crawlSite, crawlUrl, createAuditPR, createFallbackSummary, createGEOHistory, createPullRequest, createSEOCommit, createSEOCommits, detectDuplicates, detectFramework$1 as detectFramework, detectGitHubPages, detectMentions, detectSoft404, detectTechnologies, detectVisibilityChanges, discoverCompetitorKeywords, discoverPagesFromLinks, discoverRoutesFromRepo, enhanceSummaryWithCompetitors, enhanceToolIdea, enrichKeywordsWithEstimates, ensureGitRepo, evaluateAndEnhanceToolIdeas, evaluateToolFeasibility, executeAgent, extractContentHash, extractEntityPhrases, extractImages, extractKeyPhrases, extractLinks, extractMeta, extractNgrams, extractSchema, extractSeedKeywords, extractTopics, fetchCoreWebVitals, findAlmostPage1Keywords, findCTROpportunities, findHtmlEntry, findLSIKeywords, findPageFiles, findTopPerformers, formatAlertMessage, formatCIResult, formatCompetitorReport, formatConventionalCommit, formatFeaturedSnippetReport, formatHeadlineReport, formatIntentReport, formatKeywordDensityReport, formatKeywordReport, formatPRBody, formatPRTitle, formatReadabilityReport, formatReport, formatSEOCommitMessage, formatTopicReport, formatWizardProgress, index as frameworks, generateAICitableContent, generateAllFixes, generateAstroMeta, generateBlogPost, generateBranchName, generateChangelog, generateCommitSummary, generateComparisonTable, generateCompleteSocialMetaSetup, generateDuplicateIssues, generateFAQSchema, generateFixes, generateGA4EnvTemplate, generateGA4ReactComponent, generateGA4Script, generateGA4ViteScript, generateGEOReport, generateGSCVerificationTag, generateGitHubActionSetup, generateHTMLReport, generateHTMLSocialMeta, generateHeadlineVariations, generateJsonReport, generateKeyFacts, generateMarkdownReport, generateNextAppMetadata, generateNextPagesHead, generatePDFReport, generatePRDescription, generateReactHelmetSocialMeta, generateRemixMeta, generateSecretsDoc, generateSocialMetaFix, generateSvelteKitMeta, generateUncertaintyQuestions, generateWizardQuestions, generateWorkflow, getAutocompleteSuggestions, getDateRange, getExpandedSuggestions, getGSCSetupInstructions, getGitUser, getKeywordData, getKeywordSuggestions, getMaxKdThreshold, getNextQuestion, getRelatedKeywords, getVisibilityTrend, groupKeywordsByTopic, identifyQuickWins, injectGA4, injectGSCVerification, interpolatePrompt, isGitRepo, listFiles, loadAgent, loadAgentByName, mergePages, optimizeForAI, optimizeReadme, parseGEOResponse, parseGSCResponse, parseSitemap, prioritizeKeywords, processWizardResponse, readFile, routesToUrls, runAIKeywordResearch, runAIReadinessChecks, runAdditionalChecks, runAuditWithFixes, runCIKeywordResearch, runCrawlabilityChecks, runDirectAnalysis, runFullAudit, runKeywordResearch, runNLPAnalysis, runScheduledAudit, runSyncAudit, scoreContentSEO, scoreMention, searchCompetitors, searchFormatConverters, searchHackerNews, sendAlert, sendAlerts, sendDiscordAlert, sendSlackAlert, shouldRunAudit, shouldSendAlert, startWizardSession, suggestSchemaTypes, summarizeSite, tokenize, tools, trackLLMVisibility, transformGSCData, urlSafetyDatabase, wizardResponsesToContext, writeFile, writeGitHubActionFiles };
|