Recommendations Specification
How the Analyzer generates, categorizes, and surfaces actionable recommendations — the Recommendation interface, all 15 recommendation codes grouped by category, and guidance on which fixes to tackle first.
Recommendation interface
Each checker emits zero or more Recommendation objects. The Analyzer aggregates them into the AIReadinessReport.recommendations array. The interface is defined in lib/analyzer/types.ts:
| Field | Type | Description |
|---|---|---|
| code | string | A stable, uppercase snake_case identifier for the recommendation (e.g. ADD_LLMS_TXT). Use this field to programmatically identify and act on specific recommendations. |
| category | AnalysisCategory | The analysis category that produced this recommendation: llmsTxt, aiMetadata, crawlerRules, or structuredSignals. |
| title | string | A short, human-readable title suitable for display in a report or UI (e.g. “Create an llms.txt file”). |
| description | string | A detailed explanation of the issue and the corrective action to take. May include URLs, field names, or implementation guidance. |
Recommendations are per-category
Recommendation codes
The following 15 codes are emitted by the four checkers. Codes are grouped by AnalysisCategory.
llmsTxt
| Code | Trigger condition |
|---|---|
| ADD_LLMS_TXT | /llms.txt returns HTTP 404. The file does not exist. |
| POPULATE_LLMS_TXT | /llms.txt returns HTTP 200 but the response body is empty. |
| FIX_LLMS_TXT_CONTENT_TYPE | /llms.txt is served with a non-text content type (not text/* or JSON). |
| IMPROVE_LLMS_TXT | /llms.txt body is fewer than 100 characters, or contains no informative signals (no URLs, paths, or site description pattern). |
| FIX_LLMS_TXT_ACCESS | /llms.txt returns an unexpected HTTP status other than 200 or 404 (e.g. 403, 500). |
aiMetadata
| Code | Trigger condition |
|---|---|
| COMPLETE_CRITICAL_METADATA | At least one critical tag is present but one or more are missing (partial warn state). |
| ADD_CRITICAL_METADATA | All four critical tags (<title>, meta[name="description"], meta[property="og:title"], meta[property="og:description"]) are absent (fail state). |
| IMPROVE_SUPPLEMENTAL_METADATA | One or more non-critical tags are missing and the overall status is warn. Emitted alongside COMPLETE_CRITICAL_METADATA when applicable. |
crawlerRules
| Code | Trigger condition |
|---|---|
| ADD_ROBOTS_TXT | /robots.txt returns HTTP 404. No crawler rules are in place. |
| ALLOW_AI_CRAWLERS | A global Disallow: / rule exists, or all 10 AI crawlers are explicitly blocked (fail state). |
| REVIEW_AI_CRAWLER_ACCESS | A majority of AI crawlers (≥6 of 10) are blocked, or ≥5 are unspecified and ≥1 is blocked (warn state). |
structuredSignals
| Code | Trigger condition |
|---|---|
| ADD_JSONLD | No JSON-LD blocks found, but microdata or RDFa markup is present on the page. |
| ADD_STRUCTURED_DATA | No structured data markup of any kind (JSON-LD, microdata, RDFa) is found. Emitted in both warn (sitemap present) and fail (no sitemap) states. |
| ADD_SITEMAP | No structured data markup and no valid /sitemap.xml found (fail state only). |
| FIX_INVALID_JSONLD | One or more <script type="application/ld+json"> blocks contain invalid JSON that cannot be parsed. |
Prioritization
Because each AnalysisCategory contributes equally (25%) to the overall score, fixing a category from not_found (10 points) to pass (100 points) adds 22.5 points to the overall score. The order in which you address recommendations affects how quickly your score improves.
- Start with llmsTxt and aiMetadata. Together they account for 50% of the score. Both are typically fast to implement — an
llms.txtfile and a complete<head>can be added in minutes. AddressADD_LLMS_TXTandADD_CRITICAL_METADATAfirst. - Fix fail conditions before warn conditions. A
failresult scores 20 points; awarnresult scores 65 points. Moving fromfailtopassgains 80 points in that category; moving fromwarntopassgains only 35. PrioritizeALLOW_AI_CRAWLERSandADD_CRITICAL_METADATAoverREVIEW_AI_CRAWLER_ACCESSorIMPROVE_LLMS_TXT. - Address not_found before unknown. A
not_foundresult (10 points) scores lower thanunknown(40 points) because a 404 is a definitive signal that the resource is absent. FixADD_LLMS_TXT,ADD_ROBOTS_TXT, andADD_STRUCTURED_DATAbefore investigating transient network issues. - Supplemental improvements last. Recommendations like
IMPROVE_SUPPLEMENTAL_METADATA,ADD_JSONLD, andIMPROVE_LLMS_TXTrefine an already-partial implementation. Address them after allfailandnot_foundconditions are resolved.
Use recommendation codes to automate fixes
@geo-ai/core, @geo-ai/next, etc.) generate the artifacts that resolve these recommendations. If your report contains ADD_LLMS_TXT, run the GEO AI generator to produce a compliant llms.txt. If it contains ADD_JSONLD, use the structured data generator to emit the correct JSON-LD blocks.