geo-auditor
v0.4.3
Published
Deterministic GEO / AI-readiness auditor — score any web page for how well AI crawlers (GPTBot, ClaudeBot, PerplexityBot) can access, ingest and understand it. Audit a live URL or raw HTML; get findings with concrete fixes.
Maintainers
Readme
geo-auditor
Does AI actually understand your website? Find out in one line:
npx geo-auditor your-site.comNo install, no signup, no API key. Type a bare host — https:// is added for you —
and get a 0–100 AI-readiness score plus a ranked list of what to fix, in seconds.
https://your-site.com
72/100 ██████████████░░░░░░ AI-readiness
0 ░░░░░░░░░░░░ Freshness & trust
36 ████░░░░░░░░ Structured data
91 ███████████░ Metadata & identity
100 ████████████ Crawler access
3 to fix · 14 passing
warning schema.json-ld
No JSON-LD structured data found.
→ Add JSON-LD structured data so AI can parse your entities.
info freshness.dates
No published or updated date found.
→ Expose a published/updated date.Deterministic GEO / AI-readiness auditing for web pages.
Answer engines like ChatGPT, Claude, and Perplexity can only cite what they can
fetch and understand. geo-auditor scores a page against the concrete
signals they depend on — crawler access, server-rendered content, structured
data, metadata, discovery files, and freshness — and returns findings with
explicit fixes, not a vague grade.
- ⚡ Zero-install —
npx geo-auditor <url>runs the full audit remotely; no clone, no build. Or add it to CI as a score gate. - 🔁 Deterministic & versioned — same input, same score. Every check is a transparent rule, stamped with an engine + scoring version so results compare like-for-like over time.
- 🧪 Two modes — audit a live URL (fetches robots.txt / sitemap.xml / llms.txt for you) or a raw HTML string with no network, ideal for CI and unit tests.
- 🛠 Actionable — each finding carries evidence and a
what / why / howfix. - 📦 Tiny & typed — first-class TypeScript types, two small dependencies, runs on Node 18+ (and Bun, Deno).
Use it from the terminal
npx geo-auditor example.com # bare host — https:// added for you
npx geo-auditor https://example.com --min 90 # exit non-zero below 90 (CI gate)
npx geo-auditor --html dist/index.html --url https://acme.com/
curl -s https://acme.com | npx geo-auditor - --url https://acme.com/
npx geo-auditor example.com --json # raw JSON Result for piping| Flag | Meaning |
|---|---|
| --html <file> | Audit a local HTML file, no network |
| - | Audit HTML piped on stdin, no network |
| --url <url> | Page identity for --html/stdin (canonical & HTTPS checks) |
| --min <0–100> | Exit 1 if the overall score is below this — a CI gate |
| --json | Print the raw JSON Result instead of the report |
The URL is tolerant — a bare host like www.example.com is qualified to https://
for you; an explicit http:// is left as-is.
Use it as a library
npm install geo-auditorQuick start
Audit a live URL
import { audit } from "geo-auditor";
const report = await audit("https://example.com");
console.log(report.score.overall); // 0–100
for (const f of report.findings.filter((f) => !f.passed)) {
console.log(`[${f.severity}] ${f.evidence}`);
if (f.fix) console.log(` → ${f.fix.what}`);
}Audit raw HTML (offline / CI)
import { auditHtml } from "geo-auditor";
const html = await renderMyPage();
const report = await auditHtml(html, { url: "https://example.com/blog/post" });
// Fail your build if AI-readiness regresses:
if (report.score.overall < 90) {
throw new Error(`AI-readiness ${report.score.overall}/100 — below threshold`);
}HTML mode runs only the checks derivable from the HTML itself. Network-only signals (robots.txt, sitemap.xml, llms.txt, response headers) are skipped — use
auditto cover those. Pass{ url }so canonical / clean-URL / HTTPS checks know the page's real identity.
What it checks
~two dozen checks across six categories:
| Category | Examples |
|---|---|
| Crawler access | AI bots allowed in robots.txt, page indexable, HTTPS |
| Content ingestibility | real text present in raw HTML (not JS-only), <main>/<article> landmark |
| Structured data | JSON-LD present & valid, entity schema, schema completeness, heading hierarchy |
| Metadata & identity | title, meta description, canonical, lang, Open Graph |
| Discovery & AI-guidance | sitemap.xml, llms.txt, clean URLs |
| Freshness & trust | dates, author, sameAs links, Last-Modified |
The result shape
interface Result {
target: string;
engineVersion: string;
scoringVersion: string;
scannedAt: string; // ISO
score: {
overall: number; // 0–100
categories: { category: string; score: number; findingCount: number }[];
scoringVersion: string;
};
findings: {
id: string;
category: string;
severity: "critical" | "warning" | "info";
passed: boolean;
evidence: string;
fix?: { what: string; why: string; how: string };
}[];
}Compose your own pipeline
The high-level audit / auditHtml are built on exported primitives — bring your
own checks or resource provider:
import {
scanTarget,
CheckRegistry,
registerDefaultChecks,
HttpResourceProvider,
defineCheck,
} from "geo-auditor";
const registry = registerDefaultChecks(new CheckRegistry());
registry.register(
defineCheck({
id: "custom.my-signal",
scope: "page",
category: "metadata-identity",
requires: ["html"],
evaluate: (ctx) => ({ passed: true, severity: "info", evidence: "…" }),
}),
);
const report = await scanTarget(
{ url: "https://example.com" },
{ provider: new HttpResourceProvider(), registry },
);Notes
- Not rendered. It reads raw HTML, exactly as a non-JS crawler would — that's the point: it measures what AI ingests, not what a browser paints.
- Scope. It measures whether AI can ingest your page, not whether it will recommend you.
License
MIT
