Scoring Specification
How the Analyzer converts four category check results into a single overall score — the STATUS_SCORES mapping, equal category weights, the rounding formula, and the grade scale used to interpret the result.
Check status values
Every checker returns a CheckStatus value for its category. The Analyzer maps each status to a numeric score using the STATUS_SCORES constant defined in lib/analyzer/types.ts:
| Status | Score | Meaning |
|---|---|---|
| pass | 100 | The category is fully implemented and meets all Analyzer criteria. |
| warn | 65 | The category is partially implemented or has a recoverable issue (e.g. thin content, missing optional fields, or implicit rather than explicit configuration). |
| fail | 20 | The category has a critical implementation error that actively harms AI visibility (e.g. all crawlers blocked, all critical metadata absent). |
| not_found | 10 | The required resource was not found (HTTP 404). The category is not implemented. |
| unknown | 40 | The Analyzer could not evaluate the category due to a network error or unparseable response. The score is penalized but less severely than a confirmed failure. |
not_found scores lower than unknown
not_found result (score 10) is penalized more heavily than unknown (score 40) because a 404 is a definitive signal that the resource does not exist, whereas unknown may reflect a transient network condition rather than a missing implementation.Category weights
The four AnalysisCategory values each contribute equally to the overall score. No category is weighted more heavily than another:
| Category | Weight | Checker function |
|---|---|---|
| llmsTxt | 25% | checkLlmsTxt |
| aiMetadata | 25% | checkMetadata |
| crawlerRules | 25% | checkCrawlerRules |
| structuredSignals | 25% | checkStructuredSignals |
llms.txt and AI metadata together account for 50%
llmsTxt and aiMetadata from not_found to pass adds up to 45 points to the overall score. These two categories are the highest-leverage starting point for most sites.Score formula
The calculateScore function in lib/analyzer/score.ts computes the overall score by averaging the four category scores and rounding to the nearest integer:
overall = round((llmsTxt + aiMetadata + crawlerRules + structuredSignals) / 4)
Each category score is the STATUS_SCORES value for that category's CheckStatus. The result is a whole number between 0 and 100 inclusive.
Rounding uses standard half-up rounding
Math.round() rounds 0.5 up. A score of 48.75 rounds to 49; a score of 48.5 rounds to 49; a score of 48.25 rounds to 48.Grade scale
The Analyzer maps the overall score to a grade label for display in reports and the analyzer UI:
| Score range | Grade | Interpretation |
|---|---|---|
| 90–100 | Excellent | All four layers are implemented and passing. The site is fully GEO-ready. |
| 75–89 | Good | Most layers are passing. One or two categories have minor issues or are returning warn. |
| 50–74 | Fair | Some layers are implemented but others are missing or failing. Meaningful improvements are available. |
| 25–49 | Poor | Most layers are missing or failing. The site has limited AI search visibility. |
| 0–24 | Not optimized | No layers are implemented, or critical failures exist across multiple categories. The site is not visible to AI search engines. |
Interpretation
The overall score is a composite signal, not a precise measurement. Use it to track progress over time and to prioritize which categories to address first.
- Excellent (90–100). All four categories are passing. The site exposes an
llms.txtfile, complete AI metadata, explicit AI crawler rules, and valid structured data. No high-priority recommendations are expected. - Good (75–89). The site has implemented most of the specification. A score in this range typically means one category is returning
warn— for example, anllms.txtfile exists but has thin content, or structured data is present as microdata rather than JSON-LD. Address thewarncategory to reach Excellent. - Fair (50–74). Two or more categories are returning
warnornot_found. The site has partial AI optimization. Prioritize the categories with the lowest scores —not_found(10) andfail(20) have the most room for improvement. - Poor (25–49). Most categories are missing or failing. The site is unlikely to appear in AI-generated answers. Start with
llmsTxtandaiMetadata— together they account for 50% of the score and are typically the fastest to implement. - Not optimized (0–24). No meaningful AI optimization is in place, or one or more categories are actively blocking AI access (e.g. all crawlers blocked via
robots.txt). Fix anyfailconditions first, then addressnot_foundcategories.
A high score does not guarantee AI citation