@houtini/seo-audit-console 0.2.0
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/LICENSE +92 -0
- package/README.md +211 -0
- package/dist/audit/checks.d.ts +35 -0
- package/dist/audit/checks.d.ts.map +1 -0
- package/dist/audit/checks.js +1475 -0
- package/dist/audit/checks.js.map +1 -0
- package/dist/audit/drift.d.ts +40 -0
- package/dist/audit/drift.d.ts.map +1 -0
- package/dist/audit/drift.js +148 -0
- package/dist/audit/drift.js.map +1 -0
- package/dist/audit/engine.d.ts +33 -0
- package/dist/audit/engine.d.ts.map +1 -0
- package/dist/audit/engine.js +186 -0
- package/dist/audit/engine.js.map +1 -0
- package/dist/audit/opportunities.d.ts +23 -0
- package/dist/audit/opportunities.d.ts.map +1 -0
- package/dist/audit/opportunities.js +149 -0
- package/dist/audit/opportunities.js.map +1 -0
- package/dist/audit/report.d.ts +11 -0
- package/dist/audit/report.d.ts.map +1 -0
- package/dist/audit/report.js +59 -0
- package/dist/audit/report.js.map +1 -0
- package/dist/audit/schema-validate.d.ts +35 -0
- package/dist/audit/schema-validate.d.ts.map +1 -0
- package/dist/audit/schema-validate.js +293 -0
- package/dist/audit/schema-validate.js.map +1 -0
- package/dist/audit/templates.d.ts +43 -0
- package/dist/audit/templates.d.ts.map +1 -0
- package/dist/audit/templates.js +129 -0
- package/dist/audit/templates.js.map +1 -0
- package/dist/audit/topicGaps.d.ts +42 -0
- package/dist/audit/topicGaps.d.ts.map +1 -0
- package/dist/audit/topicGaps.js +181 -0
- package/dist/audit/topicGaps.js.map +1 -0
- package/dist/core/AuditDatabase.d.ts +33 -0
- package/dist/core/AuditDatabase.d.ts.map +1 -0
- package/dist/core/AuditDatabase.js +481 -0
- package/dist/core/AuditDatabase.js.map +1 -0
- package/dist/core/Backlinks.d.ts +33 -0
- package/dist/core/Backlinks.d.ts.map +1 -0
- package/dist/core/Backlinks.js +110 -0
- package/dist/core/Backlinks.js.map +1 -0
- package/dist/core/Crawler.d.ts +23 -0
- package/dist/core/Crawler.d.ts.map +1 -0
- package/dist/core/Crawler.js +588 -0
- package/dist/core/Crawler.js.map +1 -0
- package/dist/core/DataForSeoClient.d.ts +86 -0
- package/dist/core/DataForSeoClient.d.ts.map +1 -0
- package/dist/core/DataForSeoClient.js +232 -0
- package/dist/core/DataForSeoClient.js.map +1 -0
- package/dist/core/Entities.d.ts +23 -0
- package/dist/core/Entities.d.ts.map +1 -0
- package/dist/core/Entities.js +62 -0
- package/dist/core/Entities.js.map +1 -0
- package/dist/core/GscClient.d.ts +22 -0
- package/dist/core/GscClient.d.ts.map +1 -0
- package/dist/core/GscClient.js +93 -0
- package/dist/core/GscClient.js.map +1 -0
- package/dist/core/GscSync.d.ts +20 -0
- package/dist/core/GscSync.d.ts.map +1 -0
- package/dist/core/GscSync.js +133 -0
- package/dist/core/GscSync.js.map +1 -0
- package/dist/core/JobManager.d.ts +30 -0
- package/dist/core/JobManager.d.ts.map +1 -0
- package/dist/core/JobManager.js +68 -0
- package/dist/core/JobManager.js.map +1 -0
- package/dist/core/RankTracker.d.ts +25 -0
- package/dist/core/RankTracker.d.ts.map +1 -0
- package/dist/core/RankTracker.js +78 -0
- package/dist/core/RankTracker.js.map +1 -0
- package/dist/core/Refresh.d.ts +32 -0
- package/dist/core/Refresh.d.ts.map +1 -0
- package/dist/core/Refresh.js +73 -0
- package/dist/core/Refresh.js.map +1 -0
- package/dist/core/UrlInspector.d.ts +22 -0
- package/dist/core/UrlInspector.d.ts.map +1 -0
- package/dist/core/UrlInspector.js +92 -0
- package/dist/core/UrlInspector.js.map +1 -0
- package/dist/core/WikidataClient.d.ts +19 -0
- package/dist/core/WikidataClient.d.ts.map +1 -0
- package/dist/core/WikidataClient.js +59 -0
- package/dist/core/WikidataClient.js.map +1 -0
- package/dist/core/agentReadiness.d.ts +34 -0
- package/dist/core/agentReadiness.d.ts.map +1 -0
- package/dist/core/agentReadiness.js +119 -0
- package/dist/core/agentReadiness.js.map +1 -0
- package/dist/core/ctrModel.d.ts +2 -0
- package/dist/core/ctrModel.d.ts.map +1 -0
- package/dist/core/ctrModel.js +6 -0
- package/dist/core/ctrModel.js.map +1 -0
- package/dist/core/dashboardData.d.ts +312 -0
- package/dist/core/dashboardData.d.ts.map +1 -0
- package/dist/core/dashboardData.js +550 -0
- package/dist/core/dashboardData.js.map +1 -0
- package/dist/core/dataStorage.d.ts +42 -0
- package/dist/core/dataStorage.d.ts.map +1 -0
- package/dist/core/dataStorage.js +193 -0
- package/dist/core/dataStorage.js.map +1 -0
- package/dist/core/draftBrief.d.ts +27 -0
- package/dist/core/draftBrief.d.ts.map +1 -0
- package/dist/core/draftBrief.js +69 -0
- package/dist/core/draftBrief.js.map +1 -0
- package/dist/core/extract.d.ts +67 -0
- package/dist/core/extract.d.ts.map +1 -0
- package/dist/core/extract.js +262 -0
- package/dist/core/extract.js.map +1 -0
- package/dist/core/gscFreshness.d.ts +18 -0
- package/dist/core/gscFreshness.d.ts.map +1 -0
- package/dist/core/gscFreshness.js +32 -0
- package/dist/core/gscFreshness.js.map +1 -0
- package/dist/core/linkGraph.d.ts +19 -0
- package/dist/core/linkGraph.d.ts.map +1 -0
- package/dist/core/linkGraph.js +125 -0
- package/dist/core/linkGraph.js.map +1 -0
- package/dist/core/passageScore.d.ts +19 -0
- package/dist/core/passageScore.d.ts.map +1 -0
- package/dist/core/passageScore.js +59 -0
- package/dist/core/passageScore.js.map +1 -0
- package/dist/core/paths.d.ts +5 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +15 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/queryData.d.ts +35 -0
- package/dist/core/queryData.d.ts.map +1 -0
- package/dist/core/queryData.js +200 -0
- package/dist/core/queryData.js.map +1 -0
- package/dist/core/reranker.d.ts +8 -0
- package/dist/core/reranker.d.ts.map +1 -0
- package/dist/core/reranker.js +68 -0
- package/dist/core/reranker.js.map +1 -0
- package/dist/core/robots.d.ts +11 -0
- package/dist/core/robots.d.ts.map +1 -0
- package/dist/core/robots.js +76 -0
- package/dist/core/robots.js.map +1 -0
- package/dist/core/sitemap.d.ts +15 -0
- package/dist/core/sitemap.d.ts.map +1 -0
- package/dist/core/sitemap.js +100 -0
- package/dist/core/sitemap.js.map +1 -0
- package/dist/core/sql.d.ts +6 -0
- package/dist/core/sql.d.ts.map +1 -0
- package/dist/core/sql.js +6 -0
- package/dist/core/sql.js.map +1 -0
- package/dist/core/types.d.ts +22 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/url-key.d.ts +39 -0
- package/dist/core/url-key.d.ts.map +1 -0
- package/dist/core/url-key.js +106 -0
- package/dist/core/url-key.js.map +1 -0
- package/dist/generators/index.d.ts +45 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +184 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1387 -0
- package/dist/server.js.map +1 -0
- package/dist/src/ui/dashboard.html +347 -0
- package/dist/src/ui/sync-progress.html +104 -0
- package/package.json +101 -0
- package/server.json +57 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UrlInspector.js","sourceRoot":"","sources":["../../src/core/UrlInspector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare class WikidataClient {
|
|
2
|
+
private readonly cache;
|
|
3
|
+
private readonly ttlMs;
|
|
4
|
+
constructor(cacheDbPath: string, ttlDays?: number);
|
|
5
|
+
private getJson;
|
|
6
|
+
/** Best entity match for free text (e.g. an H1). Returns null if nothing matches. */
|
|
7
|
+
searchEntity(query: string, language?: string): Promise<{
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
} | null>;
|
|
12
|
+
/** Parent/whole entities of a QID: P279 (subclass of) + P361 (part of). */
|
|
13
|
+
relatedEntities(qid: string): Promise<{
|
|
14
|
+
related: string;
|
|
15
|
+
relation: string;
|
|
16
|
+
}[]>;
|
|
17
|
+
close(): void;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=WikidataClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WikidataClient.d.ts","sourceRoot":"","sources":["../../src/core/WikidataClient.ts"],"names":[],"mappings":"AAYA,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,WAAW,EAAE,MAAM,EAAE,OAAO,SAAK;YAQ/B,OAAO;IAWrB,qFAAqF;IAC/E,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAO,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IASvH,2EAA2E;IACrE,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAapF,KAAK,IAAI,IAAI;CACd"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { mkdirSync } from 'node:fs';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* Minimal Wikidata client over the PUBLIC API (no auth) — entity search + claims — with a
|
|
6
|
+
* long SQLite cache (entities are stable). Used by the 6d entity layer. Wikidata asks for a
|
|
7
|
+
* descriptive User-Agent.
|
|
8
|
+
*/
|
|
9
|
+
const UA = 'seo-audit-console/0.1 (https://github.com/houtini-ai/seo-audit-console)';
|
|
10
|
+
const API = 'https://www.wikidata.org/w/api.php';
|
|
11
|
+
export class WikidataClient {
|
|
12
|
+
cache;
|
|
13
|
+
ttlMs;
|
|
14
|
+
constructor(cacheDbPath, ttlDays = 45) {
|
|
15
|
+
this.ttlMs = ttlDays * 86400000;
|
|
16
|
+
mkdirSync(dirname(cacheDbPath), { recursive: true });
|
|
17
|
+
this.cache = new Database(cacheDbPath);
|
|
18
|
+
this.cache.pragma('journal_mode = WAL');
|
|
19
|
+
this.cache.exec(`CREATE TABLE IF NOT EXISTS wd_cache (url TEXT PRIMARY KEY, body TEXT NOT NULL, fetched_at TEXT NOT NULL)`);
|
|
20
|
+
}
|
|
21
|
+
async getJson(url) {
|
|
22
|
+
const row = this.cache.prepare('SELECT body, fetched_at FROM wd_cache WHERE url = ?').get(url);
|
|
23
|
+
if (row && Date.now() - Date.parse(row.fetched_at) < this.ttlMs)
|
|
24
|
+
return JSON.parse(row.body);
|
|
25
|
+
const res = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' }, signal: AbortSignal.timeout(15000) });
|
|
26
|
+
if (!res.ok)
|
|
27
|
+
throw new Error(`Wikidata ${res.status} for ${url}`);
|
|
28
|
+
const json = await res.json();
|
|
29
|
+
this.cache.prepare(`INSERT INTO wd_cache (url, body, fetched_at) VALUES (?,?,datetime('now'))
|
|
30
|
+
ON CONFLICT(url) DO UPDATE SET body=excluded.body, fetched_at=datetime('now')`).run(url, JSON.stringify(json));
|
|
31
|
+
return json;
|
|
32
|
+
}
|
|
33
|
+
/** Best entity match for free text (e.g. an H1). Returns null if nothing matches. */
|
|
34
|
+
async searchEntity(query, language = 'en') {
|
|
35
|
+
const q = query.trim();
|
|
36
|
+
if (!q)
|
|
37
|
+
return null;
|
|
38
|
+
const url = `${API}?action=wbsearchentities&format=json&type=item&limit=1&language=${encodeURIComponent(language)}&uselang=${encodeURIComponent(language)}&search=${encodeURIComponent(q)}`;
|
|
39
|
+
const j = await this.getJson(url);
|
|
40
|
+
const hit = j?.search?.[0];
|
|
41
|
+
return hit?.id ? { id: hit.id, label: hit.label ?? q, description: hit.description } : null;
|
|
42
|
+
}
|
|
43
|
+
/** Parent/whole entities of a QID: P279 (subclass of) + P361 (part of). */
|
|
44
|
+
async relatedEntities(qid) {
|
|
45
|
+
const out = [];
|
|
46
|
+
for (const [prop, relation] of [['P279', 'subclass_of'], ['P361', 'part_of']]) {
|
|
47
|
+
const url = `${API}?action=wbgetclaims&format=json&entity=${qid}&property=${prop}`;
|
|
48
|
+
const j = await this.getJson(url);
|
|
49
|
+
for (const cl of j?.claims?.[prop] ?? []) {
|
|
50
|
+
const id = cl?.mainsnak?.datavalue?.value?.id;
|
|
51
|
+
if (id)
|
|
52
|
+
out.push({ related: id, relation });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
close() { this.cache.close(); }
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=WikidataClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WikidataClient.js","sourceRoot":"","sources":["../../src/core/WikidataClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-readiness checker — is a site ready for AI agents to discover and use it? Models the
|
|
3
|
+
* signals from Cloudflare's "Is Your Site Agent-Ready?" (isitagentready.com): Discoverability,
|
|
4
|
+
* Content, Bot-Access-Control, Capabilities. Each check is a cheap HTTP probe of a fixed path or
|
|
5
|
+
* header (deterministic — cite the bytes). Returns a 0–100 score, a level, and a per-check
|
|
6
|
+
* checklist with copy-paste-ready fixes. The agentic-SEO/GEO frontier — almost no audit tool
|
|
7
|
+
* does this. (Reference impl of the SERVING side: c:\dev\yubnub.)
|
|
8
|
+
*/
|
|
9
|
+
export type AgentCategory = 'Discoverability' | 'Content' | 'Bot access control' | 'Capabilities';
|
|
10
|
+
export interface AgentCheck {
|
|
11
|
+
id: string;
|
|
12
|
+
category: AgentCategory;
|
|
13
|
+
label: string;
|
|
14
|
+
present: boolean;
|
|
15
|
+
detail: string;
|
|
16
|
+
fix: string;
|
|
17
|
+
}
|
|
18
|
+
export interface AgentReadiness {
|
|
19
|
+
siteUrl: string;
|
|
20
|
+
origin: string;
|
|
21
|
+
score: number;
|
|
22
|
+
level: string;
|
|
23
|
+
byCategory: {
|
|
24
|
+
category: AgentCategory;
|
|
25
|
+
passed: number;
|
|
26
|
+
total: number;
|
|
27
|
+
}[];
|
|
28
|
+
checks: AgentCheck[];
|
|
29
|
+
commerceNote: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function checkAgentReadiness(siteUrl: string): Promise<AgentReadiness>;
|
|
32
|
+
/** Human-readable markdown report (for the tool result). */
|
|
33
|
+
export declare function buildAgentReadinessMarkdown(r: AgentReadiness): string;
|
|
34
|
+
//# sourceMappingURL=agentReadiness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentReadiness.d.ts","sourceRoot":"","sources":["../../src/core/agentReadiness.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAAG,SAAS,GAAG,oBAAoB,GAAG,cAAc,CAAC;AAClG,MAAM,WAAW,UAAU;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AACjI,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAC9D,UAAU,EAAE;QAAE,QAAQ,EAAE,aAAa,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACzE,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAiCD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAmDlF;AAED,4DAA4D;AAC5D,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAerE"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-readiness checker — is a site ready for AI agents to discover and use it? Models the
|
|
3
|
+
* signals from Cloudflare's "Is Your Site Agent-Ready?" (isitagentready.com): Discoverability,
|
|
4
|
+
* Content, Bot-Access-Control, Capabilities. Each check is a cheap HTTP probe of a fixed path or
|
|
5
|
+
* header (deterministic — cite the bytes). Returns a 0–100 score, a level, and a per-check
|
|
6
|
+
* checklist with copy-paste-ready fixes. The agentic-SEO/GEO frontier — almost no audit tool
|
|
7
|
+
* does this. (Reference impl of the SERVING side: c:\dev\yubnub.)
|
|
8
|
+
*/
|
|
9
|
+
const UA = 'Mozilla/5.0 (compatible; SEOAuditConsole/1.0; +https://houtini.com)';
|
|
10
|
+
// The AI crawlers a site would name in robots.txt if it had AI-specific rules.
|
|
11
|
+
const AI_BOTS = /(GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|Claude-Web|anthropic-ai|Google-Extended|PerplexityBot|CCBot|Bytespider|Amazonbot|Applebot-Extended|cohere-ai|Meta-ExternalAgent|DuckAssistBot)/i;
|
|
12
|
+
async function probe(url, accept = '*/*') {
|
|
13
|
+
try {
|
|
14
|
+
const res = await fetch(url, { headers: { 'user-agent': UA, accept }, redirect: 'follow', signal: AbortSignal.timeout(8000) });
|
|
15
|
+
const ct = (res.headers.get('content-type') ?? '').toLowerCase();
|
|
16
|
+
const text = res.ok ? (await res.text()).slice(0, 20000) : '';
|
|
17
|
+
return { ok: res.ok, status: res.status, ct, text, link: res.headers.get('link') };
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return { ok: false, status: 0, ct: '', text: '', link: null };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// `res.ok` alone is not "present": a SPA/CDN with a catch-all 200 route serves its HTML
|
|
24
|
+
// shell for /llms.txt, /agents.md and every /.well-known/* probe — the exact soft-404
|
|
25
|
+
// pattern the audit's own soft-404-shell check exists to catch. Validate the body shape.
|
|
26
|
+
const looksHtml = (p) => /text\/html/.test(p.ct) || /^\s*(<!doctype\s|<html[\s>])/i.test(p.text);
|
|
27
|
+
const textReal = (p) => p.ok && p.text.trim().length > 0 && !looksHtml(p);
|
|
28
|
+
const jsonReal = (p) => {
|
|
29
|
+
if (!p.ok || looksHtml(p))
|
|
30
|
+
return false;
|
|
31
|
+
if (/json/.test(p.ct))
|
|
32
|
+
return true;
|
|
33
|
+
try {
|
|
34
|
+
JSON.parse(p.text);
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const xmlReal = (p) => p.ok && (/xml/.test(p.ct) || /<\?xml|<(urlset|sitemapindex)[\s>]/i.test(p.text));
|
|
42
|
+
function originOf(siteUrl) {
|
|
43
|
+
const bare = siteUrl.replace(/^sc-domain:/, '');
|
|
44
|
+
try {
|
|
45
|
+
return new URL(/^https?:\/\//.test(bare) ? bare : `https://${bare}`).origin;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return `https://${bare.replace(/\/.*$/, '')}`;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export async function checkAgentReadiness(siteUrl) {
|
|
52
|
+
const origin = originOf(siteUrl);
|
|
53
|
+
const u = (p) => origin + p;
|
|
54
|
+
const [robots, sitemap, home, homeMd, llms, agentsMd, mcpCard, skills, apiCatalog, oauthPR, oauthAS, webBotAuth] = await Promise.all([
|
|
55
|
+
probe(u('/robots.txt')), probe(u('/sitemap.xml')), probe(u('/')), probe(u('/'), 'text/markdown'),
|
|
56
|
+
probe(u('/llms.txt')), probe(u('/agents.md')), probe(u('/.well-known/mcp/server-card.json')),
|
|
57
|
+
probe(u('/.well-known/agent-skills/index.json')), probe(u('/.well-known/api-catalog')),
|
|
58
|
+
probe(u('/.well-known/oauth-protected-resource')), probe(u('/.well-known/oauth-authorization-server')),
|
|
59
|
+
probe(u('/.well-known/http-message-signatures-directory')),
|
|
60
|
+
]);
|
|
61
|
+
const robotsReal = textReal(robots);
|
|
62
|
+
const robotsTxt = robotsReal ? robots.text : '';
|
|
63
|
+
const hasAiRules = robotsReal && AI_BOTS.test(robotsTxt);
|
|
64
|
+
const hasContentSignals = robotsReal && /content-signal\s*:/i.test(robotsTxt);
|
|
65
|
+
const hasSitemapDirective = robotsReal && /^\s*sitemap\s*:/im.test(robotsTxt);
|
|
66
|
+
const mdNegotiated = homeMd.ok && /text\/markdown/.test(homeMd.ct);
|
|
67
|
+
const sitemapReal = xmlReal(sitemap);
|
|
68
|
+
const llmsReal = textReal(llms);
|
|
69
|
+
const agentsMdReal = textReal(agentsMd);
|
|
70
|
+
const checks = [
|
|
71
|
+
{ id: 'robots-txt', category: 'Discoverability', present: robotsReal, label: 'robots.txt present', detail: robotsReal ? `200 (${robotsTxt.length} bytes)` : robots.ok ? 'returns HTML (catch-all route, not a real robots.txt)' : `not found (${robots.status})`, fix: 'Serve a /robots.txt — the base discovery file every crawler and agent checks first.' },
|
|
72
|
+
{ id: 'sitemap', category: 'Discoverability', present: sitemapReal || hasSitemapDirective, label: 'XML sitemap', detail: sitemapReal ? 'sitemap.xml found' : hasSitemapDirective ? 'declared in robots.txt' : sitemap.ok ? 'returns non-XML (catch-all route)' : 'none found', fix: 'Publish /sitemap.xml and reference it with a `Sitemap:` line in robots.txt.' },
|
|
73
|
+
{ id: 'link-headers', category: 'Discoverability', present: !!home.link, label: 'Link response headers (RFC 8288)', detail: home.link ? home.link.slice(0, 120) : 'no Link header on the homepage', fix: 'Emit Link: headers pointing agents to your API/docs/llms.txt (rel="describedby" etc.).' },
|
|
74
|
+
{ id: 'llms-txt', category: 'Content', present: llmsReal, label: 'llms.txt', detail: llmsReal ? `200 (${llms.text.length} bytes)` : llms.ok ? 'returns HTML (catch-all route, not a real llms.txt)' : `not found (${llms.status})`, fix: 'Add /llms.txt — a plain-text reading list pointing agents at your most useful pages/docs.' },
|
|
75
|
+
{ id: 'agents-md', category: 'Content', present: agentsMdReal, label: 'agents.md', detail: agentsMdReal ? `200 (${agentsMd.text.length} bytes)` : agentsMd.ok ? 'returns HTML (catch-all route, not a real agents.md)' : `not found (${agentsMd.status})`, fix: 'Add /agents.md describing how agents should use your site (allowed actions, endpoints, etiquette).' },
|
|
76
|
+
{ id: 'markdown-negotiation', category: 'Content', present: mdNegotiated, label: 'Markdown content negotiation', detail: mdNegotiated ? 'serves text/markdown on Accept' : 'returns HTML only', fix: 'Honour `Accept: text/markdown` (or an index.md fallback) so agents read clean content without parsing HTML.' },
|
|
77
|
+
{ id: 'ai-bot-rules', category: 'Bot access control', present: hasAiRules, label: 'AI-bot rules in robots.txt', detail: hasAiRules ? 'names AI crawlers (GPTBot/ClaudeBot/…)' : 'no AI-specific user-agents', fix: 'Add explicit allow/disallow rules for AI user-agents (GPTBot, ClaudeBot, Google-Extended, PerplexityBot, CCBot…).' },
|
|
78
|
+
{ id: 'content-signals', category: 'Bot access control', present: hasContentSignals, label: 'Content Signals', detail: hasContentSignals ? 'Content-Signal directives present' : 'none', fix: 'Add Cloudflare Content-Signal directives (ai-train / ai-input / search) to robots.txt to state how your content may be used.' },
|
|
79
|
+
{ id: 'web-bot-auth', category: 'Bot access control', present: jsonReal(webBotAuth), label: 'Web Bot Auth', detail: jsonReal(webBotAuth) ? 'signature directory present' : 'not found', fix: 'Publish /.well-known/http-message-signatures-directory so well-behaved agents can authenticate.' },
|
|
80
|
+
{ id: 'mcp-server-card', category: 'Capabilities', present: jsonReal(mcpCard), label: 'MCP server card', detail: jsonReal(mcpCard) ? 'server-card.json present' : 'not found', fix: 'Expose /.well-known/mcp/server-card.json so agents can discover your MCP server + tools.' },
|
|
81
|
+
{ id: 'agent-skills', category: 'Capabilities', present: jsonReal(skills), label: 'Agent Skills', detail: jsonReal(skills) ? 'agent-skills index present' : 'not found', fix: 'Declare capabilities at /.well-known/agent-skills/index.json (agentskills.io).' },
|
|
82
|
+
{ id: 'api-catalog', category: 'Capabilities', present: jsonReal(apiCatalog), label: 'API Catalog (RFC 9727)', detail: jsonReal(apiCatalog) ? 'api-catalog present' : 'not found', fix: 'Publish /.well-known/api-catalog listing your machine-usable APIs.' },
|
|
83
|
+
{ id: 'oauth-discovery', category: 'Capabilities', present: jsonReal(oauthPR) || jsonReal(oauthAS), label: 'OAuth discovery (RFC 8414/9728)', detail: (jsonReal(oauthPR) || jsonReal(oauthAS)) ? 'oauth metadata present' : 'not found', fix: 'If agents need authenticated actions, expose OAuth metadata at /.well-known/oauth-protected-resource (RFC 9728).' },
|
|
84
|
+
];
|
|
85
|
+
const cats = ['Discoverability', 'Content', 'Bot access control', 'Capabilities'];
|
|
86
|
+
const byCategory = cats.map(category => {
|
|
87
|
+
const cc = checks.filter(c => c.category === category);
|
|
88
|
+
return { category, passed: cc.filter(c => c.present).length, total: cc.length };
|
|
89
|
+
});
|
|
90
|
+
const passed = checks.filter(c => c.present).length;
|
|
91
|
+
const score = Math.round((passed / checks.length) * 100);
|
|
92
|
+
const level = score >= 80 ? 'Agent-native' : score >= 50 ? 'Agent-friendly' : score >= 20 ? 'Some agent signals' : 'Basic web presence';
|
|
93
|
+
return {
|
|
94
|
+
siteUrl, origin, score, level, byCategory, checks,
|
|
95
|
+
commerceNote: 'Commerce protocols (x402, ACP, UCP, MPP) are emerging and not reliably detectable from a passive probe — review manually if you transact with agents.',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/** Human-readable markdown report (for the tool result). */
|
|
99
|
+
export function buildAgentReadinessMarkdown(r) {
|
|
100
|
+
const icon = (b) => b ? '✅' : '⬜';
|
|
101
|
+
const out = [
|
|
102
|
+
`# Agent readiness — ${r.siteUrl.replace(/^sc-domain:/, '')}`,
|
|
103
|
+
`**${r.score}/100 · ${r.level}** — how ready your site is for AI agents to discover and use it.`,
|
|
104
|
+
`\n${r.byCategory.map(c => `${c.category} ${c.passed}/${c.total}`).join(' · ')}\n`,
|
|
105
|
+
];
|
|
106
|
+
let cat = '';
|
|
107
|
+
for (const c of r.checks) {
|
|
108
|
+
if (c.category !== cat) {
|
|
109
|
+
cat = c.category;
|
|
110
|
+
out.push(`\n## ${cat}`);
|
|
111
|
+
}
|
|
112
|
+
out.push(`- ${icon(c.present)} **${c.label}** — ${c.detail}`);
|
|
113
|
+
if (!c.present)
|
|
114
|
+
out.push(` - Fix: ${c.fix}`);
|
|
115
|
+
}
|
|
116
|
+
out.push('', `> ${r.commerceNote}`);
|
|
117
|
+
return out.join('\n');
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=agentReadiness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentReadiness.js","sourceRoot":"","sources":["../../src/core/agentReadiness.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,MAAM,EAAE,GAAG,qEAAqE,CAAC;AACjF,+EAA+E;AAC/E,MAAM,OAAO,GAAG,8LAA8L,CAAC;AAG/M,KAAK,UAAU,KAAK,CAAC,GAAW,EAAE,MAAM,GAAG,KAAK;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/H,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QACjE,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAAC,CAAC;AAC5E,CAAC;AAED,wFAAwF;AACxF,sFAAsF;AACtF,yFAAyF;AACzF,MAAM,SAAS,GAAG,CAAC,CAAQ,EAAW,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,+BAA+B,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACjH,MAAM,QAAQ,GAAG,CAAC,CAAQ,EAAW,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC1F,MAAM,QAAQ,GAAG,CAAC,CAAQ,EAAW,EAAE;IACrC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,SAAS,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;AAClE,CAAC,CAAC;AACF,MAAM,OAAO,GAAG,CAAC,CAAQ,EAAW,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,qCAAqC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAExH,SAAS,QAAQ,CAAC,OAAe;IAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAChD,IAAI,CAAC;QAAC,OAAO,IAAI,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,WAAW,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;IAAC,CAAC;AAC/I,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAe;IACvD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAE5C,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACnI,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC;QAChG,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC;QAC5F,KAAK,CAAC,CAAC,CAAC,sCAAsC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC;QACtF,KAAK,CAAC,CAAC,CAAC,uCAAuC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,yCAAyC,CAAC,CAAC;QACtG,KAAK,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC;KAC3D,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,MAAM,UAAU,GAAG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,iBAAiB,GAAG,UAAU,IAAI,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9E,MAAM,mBAAmB,GAAG,UAAU,IAAI,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9E,MAAM,YAAY,GAAG,MAAM,CAAC,EAAE,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACnE,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAExC,MAAM,MAAM,GAAiB;QAC3B,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,SAAS,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,uDAAuD,CAAC,CAAC,CAAC,cAAc,MAAM,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,qFAAqF,EAAE;QAC9V,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,IAAI,mBAAmB,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,YAAY,EAAE,GAAG,EAAE,6EAA6E,EAAE;QACnW,EAAE,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,kCAAkC,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,gCAAgC,EAAE,GAAG,EAAE,wFAAwF,EAAE;QACnS,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,qDAAqD,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,2FAA2F,EAAE;QACtU,EAAE,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,QAAQ,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,sDAAsD,CAAC,CAAC,CAAC,cAAc,QAAQ,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,oGAAoG,EAAE;QACtW,EAAE,EAAE,EAAE,sBAAsB,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,8BAA8B,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,mBAAmB,EAAE,GAAG,EAAE,6GAA6G,EAAE;QACpT,EAAE,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,oBAAoB,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,4BAA4B,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC,4BAA4B,EAAE,GAAG,EAAE,mHAAmH,EAAE;QACxU,EAAE,EAAE,EAAE,iBAAiB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,8HAA8H,EAAE;QAC9T,EAAE,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,oBAAoB,EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,iGAAiG,EAAE;QAChS,EAAE,EAAE,EAAE,iBAAiB,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,0FAA0F,EAAE;QAChR,EAAE,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,gFAAgF,EAAE;QAChQ,EAAE,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,oEAAoE,EAAE;QAC9P,EAAE,EAAE,EAAE,iBAAiB,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,iCAAiC,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,kHAAkH,EAAE;KACnW,CAAC;IAEF,MAAM,IAAI,GAAoB,CAAC,iBAAiB,EAAE,SAAS,EAAE,oBAAoB,EAAE,cAAc,CAAC,CAAC;IACnG,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;QACrC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC;IAClF,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,oBAAoB,CAAC;IAExI,OAAO;QACL,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM;QACjD,YAAY,EAAE,uJAAuJ;KACtK,CAAC;AACJ,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,2BAA2B,CAAC,CAAiB;IAC3D,MAAM,IAAI,GAAG,CAAC,CAAU,EAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACnD,MAAM,GAAG,GAAa;QACpB,uBAAuB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,EAAE;QAC7D,KAAK,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,KAAK,mEAAmE;QAChG,KAAK,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI;KACnF,CAAC;IACF,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;YAAC,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC;QAAC,CAAC;QACtE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,CAAC,CAAC,OAAO;YAAE,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;IACpC,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ctrModel.d.ts","sourceRoot":"","sources":["../../src/core/ctrModel.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,MAAuE,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Position → expected-CTR curve (desktop+mobile blended). Single source of truth shared by the
|
|
2
|
+
// audit engine (ctr-below-expected check, priority model) and the dashboard (quick-wins matrix),
|
|
3
|
+
// so "expected CTR" means exactly the same thing in findings and in the UI.
|
|
4
|
+
const CTR_CURVE = { 1: 0.28, 2: 0.15, 3: 0.11, 4: 0.08, 5: 0.06, 6: 0.05, 7: 0.04, 8: 0.032, 9: 0.028, 10: 0.025 };
|
|
5
|
+
export const expectedCtr = (pos) => CTR_CURVE[Math.max(1, Math.min(10, Math.round(pos)))] ?? 0.02;
|
|
6
|
+
//# sourceMappingURL=ctrModel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ctrModel.js","sourceRoot":"","sources":["../../src/core/ctrModel.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,iGAAiG;AACjG,4EAA4E;AAC5E,MAAM,SAAS,GAA2B,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;AAE3I,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC"}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
export interface DashboardData {
|
|
2
|
+
siteUrl: string;
|
|
3
|
+
empty?: boolean;
|
|
4
|
+
dateRange?: {
|
|
5
|
+
current: string;
|
|
6
|
+
prior: string;
|
|
7
|
+
maxDate: string;
|
|
8
|
+
rawMaxDate: string;
|
|
9
|
+
trimmedDays: number;
|
|
10
|
+
};
|
|
11
|
+
summary?: {
|
|
12
|
+
current: {
|
|
13
|
+
clicks: number;
|
|
14
|
+
impressions: number;
|
|
15
|
+
ctr: number;
|
|
16
|
+
position: number;
|
|
17
|
+
};
|
|
18
|
+
prior: {
|
|
19
|
+
clicks: number;
|
|
20
|
+
impressions: number;
|
|
21
|
+
ctr: number;
|
|
22
|
+
position: number;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
rankTrend?: {
|
|
26
|
+
date: string;
|
|
27
|
+
clicks: number;
|
|
28
|
+
impressions: number;
|
|
29
|
+
position: number;
|
|
30
|
+
}[];
|
|
31
|
+
rankHistory?: {
|
|
32
|
+
period: string;
|
|
33
|
+
pos_1_3: number;
|
|
34
|
+
pos_4_10: number;
|
|
35
|
+
pos_11_20: number;
|
|
36
|
+
pos_21_100: number;
|
|
37
|
+
etv: number;
|
|
38
|
+
keyword_count: number;
|
|
39
|
+
}[];
|
|
40
|
+
dateAlignment?: {
|
|
41
|
+
gsc: {
|
|
42
|
+
start: string;
|
|
43
|
+
end: string;
|
|
44
|
+
} | null;
|
|
45
|
+
dataforseo: {
|
|
46
|
+
start: string;
|
|
47
|
+
end: string;
|
|
48
|
+
} | null;
|
|
49
|
+
overlap: {
|
|
50
|
+
start: string;
|
|
51
|
+
end: string;
|
|
52
|
+
} | null;
|
|
53
|
+
note: string;
|
|
54
|
+
};
|
|
55
|
+
rankingDistribution?: {
|
|
56
|
+
date: string;
|
|
57
|
+
b1: number;
|
|
58
|
+
b2: number;
|
|
59
|
+
b3: number;
|
|
60
|
+
b4: number;
|
|
61
|
+
}[];
|
|
62
|
+
strikingDistance?: {
|
|
63
|
+
query: string;
|
|
64
|
+
position: number;
|
|
65
|
+
impressions: number;
|
|
66
|
+
clicks: number;
|
|
67
|
+
}[];
|
|
68
|
+
quickWins?: {
|
|
69
|
+
query: string;
|
|
70
|
+
position: number;
|
|
71
|
+
impressions: number;
|
|
72
|
+
clicks: number;
|
|
73
|
+
ctr: number;
|
|
74
|
+
expectedCtr: number;
|
|
75
|
+
type: 'striking' | 'snippet' | 'serp' | 'ok';
|
|
76
|
+
potential: number;
|
|
77
|
+
}[];
|
|
78
|
+
contentDecay?: {
|
|
79
|
+
urlKey: string;
|
|
80
|
+
prevClicks: number;
|
|
81
|
+
clicks: number;
|
|
82
|
+
lost: number;
|
|
83
|
+
dropPct: number;
|
|
84
|
+
impressions: number;
|
|
85
|
+
position: number;
|
|
86
|
+
}[];
|
|
87
|
+
cannibalisationTable?: {
|
|
88
|
+
query: string;
|
|
89
|
+
urlCount: number;
|
|
90
|
+
totalImpressions: number;
|
|
91
|
+
totalClicks: number;
|
|
92
|
+
verdict: 'split' | 'dominant';
|
|
93
|
+
crossType: boolean;
|
|
94
|
+
urls: {
|
|
95
|
+
url: string;
|
|
96
|
+
impressions: number;
|
|
97
|
+
clicks: number;
|
|
98
|
+
position: number;
|
|
99
|
+
template: string;
|
|
100
|
+
}[];
|
|
101
|
+
}[];
|
|
102
|
+
brandedSplit?: {
|
|
103
|
+
brand: string;
|
|
104
|
+
branded: {
|
|
105
|
+
clicks: number;
|
|
106
|
+
impressions: number;
|
|
107
|
+
};
|
|
108
|
+
nonBranded: {
|
|
109
|
+
clicks: number;
|
|
110
|
+
impressions: number;
|
|
111
|
+
};
|
|
112
|
+
priorBrandedClicks: number;
|
|
113
|
+
priorNonBrandedClicks: number;
|
|
114
|
+
};
|
|
115
|
+
topKeywords?: {
|
|
116
|
+
query: string;
|
|
117
|
+
clicks: number;
|
|
118
|
+
prevClicks: number;
|
|
119
|
+
clicksChange: number;
|
|
120
|
+
position: number;
|
|
121
|
+
prevPosition: number;
|
|
122
|
+
}[];
|
|
123
|
+
deviceBreakdown?: {
|
|
124
|
+
device: string;
|
|
125
|
+
clicks: number;
|
|
126
|
+
prevClicks: number;
|
|
127
|
+
impressions: number;
|
|
128
|
+
ctr: number;
|
|
129
|
+
position: number;
|
|
130
|
+
}[];
|
|
131
|
+
countryBreakdown?: {
|
|
132
|
+
country: string;
|
|
133
|
+
clicks: number;
|
|
134
|
+
prevClicks: number;
|
|
135
|
+
impressions: number;
|
|
136
|
+
}[];
|
|
137
|
+
pagePerformance?: {
|
|
138
|
+
urlKey: string;
|
|
139
|
+
clicks: number;
|
|
140
|
+
prevClicks: number;
|
|
141
|
+
clicksChangePct: number;
|
|
142
|
+
impressions: number;
|
|
143
|
+
position: number;
|
|
144
|
+
category: string;
|
|
145
|
+
}[];
|
|
146
|
+
keywordMovement?: {
|
|
147
|
+
query: string;
|
|
148
|
+
firstPos: number;
|
|
149
|
+
lastPos: number;
|
|
150
|
+
delta: number;
|
|
151
|
+
firstDate: string;
|
|
152
|
+
lastDate: string;
|
|
153
|
+
category: string;
|
|
154
|
+
}[];
|
|
155
|
+
equityScatter?: {
|
|
156
|
+
x: number;
|
|
157
|
+
y: number;
|
|
158
|
+
t: string;
|
|
159
|
+
}[];
|
|
160
|
+
templateMismatch?: {
|
|
161
|
+
template: string;
|
|
162
|
+
pages: number;
|
|
163
|
+
iprPct: number;
|
|
164
|
+
trafficPct: number;
|
|
165
|
+
}[];
|
|
166
|
+
cannibalisation?: {
|
|
167
|
+
query: string;
|
|
168
|
+
urls: {
|
|
169
|
+
url: string;
|
|
170
|
+
points: {
|
|
171
|
+
week: string;
|
|
172
|
+
position: number;
|
|
173
|
+
}[];
|
|
174
|
+
}[];
|
|
175
|
+
}[];
|
|
176
|
+
topLinkedPages?: {
|
|
177
|
+
url: string;
|
|
178
|
+
inlinks: number;
|
|
179
|
+
status: number | null;
|
|
180
|
+
indexable: boolean;
|
|
181
|
+
reason: string | null;
|
|
182
|
+
}[];
|
|
183
|
+
crawlHealth?: {
|
|
184
|
+
responseCodes: {
|
|
185
|
+
label: string;
|
|
186
|
+
count: number;
|
|
187
|
+
tone?: string;
|
|
188
|
+
}[];
|
|
189
|
+
indexability: {
|
|
190
|
+
label: string;
|
|
191
|
+
count: number;
|
|
192
|
+
tone?: string;
|
|
193
|
+
}[];
|
|
194
|
+
speed: {
|
|
195
|
+
label: string;
|
|
196
|
+
count: number;
|
|
197
|
+
tone?: string;
|
|
198
|
+
}[];
|
|
199
|
+
htmlSize: {
|
|
200
|
+
label: string;
|
|
201
|
+
count: number;
|
|
202
|
+
tone?: string;
|
|
203
|
+
}[];
|
|
204
|
+
depth: {
|
|
205
|
+
label: string;
|
|
206
|
+
count: number;
|
|
207
|
+
tone?: string;
|
|
208
|
+
}[];
|
|
209
|
+
titles: {
|
|
210
|
+
label: string;
|
|
211
|
+
count: number;
|
|
212
|
+
tone?: string;
|
|
213
|
+
}[];
|
|
214
|
+
metas: {
|
|
215
|
+
label: string;
|
|
216
|
+
count: number;
|
|
217
|
+
tone?: string;
|
|
218
|
+
}[];
|
|
219
|
+
onPage: {
|
|
220
|
+
label: string;
|
|
221
|
+
count: number;
|
|
222
|
+
tone?: string;
|
|
223
|
+
}[];
|
|
224
|
+
serverErrors: {
|
|
225
|
+
url: string;
|
|
226
|
+
status: number;
|
|
227
|
+
}[];
|
|
228
|
+
slowPages: {
|
|
229
|
+
url: string;
|
|
230
|
+
ms: number;
|
|
231
|
+
}[];
|
|
232
|
+
largeImages: {
|
|
233
|
+
url: string;
|
|
234
|
+
kb: number;
|
|
235
|
+
usedOn: number;
|
|
236
|
+
}[];
|
|
237
|
+
imageStats: {
|
|
238
|
+
sampled: number;
|
|
239
|
+
over100kb: number;
|
|
240
|
+
over300kb: number;
|
|
241
|
+
} | null;
|
|
242
|
+
totalPages: number;
|
|
243
|
+
};
|
|
244
|
+
agentReadiness?: {
|
|
245
|
+
score: number;
|
|
246
|
+
level: string;
|
|
247
|
+
checkedAt: string;
|
|
248
|
+
byCategory: {
|
|
249
|
+
category: string;
|
|
250
|
+
passed: number;
|
|
251
|
+
total: number;
|
|
252
|
+
}[];
|
|
253
|
+
checks: {
|
|
254
|
+
id: string;
|
|
255
|
+
category: string;
|
|
256
|
+
label: string;
|
|
257
|
+
present: boolean;
|
|
258
|
+
detail: string;
|
|
259
|
+
fix: string;
|
|
260
|
+
}[];
|
|
261
|
+
};
|
|
262
|
+
findings?: {
|
|
263
|
+
runId: string;
|
|
264
|
+
total: number;
|
|
265
|
+
finishedAt: string | null;
|
|
266
|
+
byCheck: {
|
|
267
|
+
check_id: string;
|
|
268
|
+
category: string;
|
|
269
|
+
severity: string;
|
|
270
|
+
count: number;
|
|
271
|
+
priority: number;
|
|
272
|
+
}[];
|
|
273
|
+
top: {
|
|
274
|
+
check_id: string;
|
|
275
|
+
category: string;
|
|
276
|
+
severity: string;
|
|
277
|
+
url_key: string | null;
|
|
278
|
+
evidence: string;
|
|
279
|
+
traffic_at_risk: string;
|
|
280
|
+
effort: string;
|
|
281
|
+
priority: number;
|
|
282
|
+
recommendation: string;
|
|
283
|
+
impact?: number;
|
|
284
|
+
size?: string;
|
|
285
|
+
}[];
|
|
286
|
+
recommendations: {
|
|
287
|
+
category: string;
|
|
288
|
+
checks: {
|
|
289
|
+
checkId: string;
|
|
290
|
+
title: string;
|
|
291
|
+
fix: string;
|
|
292
|
+
severity: string;
|
|
293
|
+
count: number;
|
|
294
|
+
example: {
|
|
295
|
+
urlKey: string | null;
|
|
296
|
+
evidence: Record<string, unknown>;
|
|
297
|
+
clicks: number;
|
|
298
|
+
impressions: number;
|
|
299
|
+
} | null;
|
|
300
|
+
examples: {
|
|
301
|
+
urlKey: string | null;
|
|
302
|
+
evidence: Record<string, unknown>;
|
|
303
|
+
clicks: number;
|
|
304
|
+
impressions: number;
|
|
305
|
+
}[];
|
|
306
|
+
}[];
|
|
307
|
+
}[];
|
|
308
|
+
} | null;
|
|
309
|
+
}
|
|
310
|
+
/** Build the dashboard payload for a property from its synced GSC history. */
|
|
311
|
+
export declare function getDashboardData(dataDir: string, siteUrl: string): DashboardData;
|
|
312
|
+
//# sourceMappingURL=dashboardData.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboardData.d.ts","sourceRoot":"","sources":["../../src/core/dashboardData.ts"],"names":[],"mappings":"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"}
|