seo-ai-crawlers (M14)
SkillWeb & browsingAudit AI crawler access and citability for a page — confirm retrieval/citation bots (OAI-SearchBot, Claude-SearchBot, PerplexityBot) are allowed and the Googlebot vs Google-Extended split is correct, classify training vs search/retrieval vs user-fetch user-agents, check the page is server-rendered e
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the seo-ai-crawlers (M14) skill
What this skill tells your AI
The instructions your AI receives, as published by hainrixz/claude-seo-ai in skills/seo-ai-crawlers/SKILL.md and read by ahel’s review.
Two separate questions live in this module, and only one of them has vendor documentation behind it:
- Google's AI features. A page can appear in AI Overviews / AI Mode only if it is indexed and eligible to be shown in Google Search with a snippet. Those gates are documented, so
M14.ai_eligibility.*carries the onlyestablishedfindings here. - Third-party AI crawlers. Who may fetch and cite the page — OpenAI, Anthropic, Perplexity, Apple, Amazon, Meta, Mistral, DuckDuckGo, Cohere. Access is documented per user-agent; the citation effect is not, so those findings stay
directional.
The training-vs-retrieval-vs-user-fetch distinction decides every robots recommendation. Reference: references/ai-crawlers.md (UA table with sources, Content-Signal, eligibility gates, presets). AI discovery files (llms.txt, agents.md, /.well-known/ucp, agentic sitemap) are module M21 — see seo-ai-discovery; agentic-commerce readiness is M18 (seo-ecommerce).
Inputs
Work from the PageSnapshot named in your dispatch envelope: read parsed from <run_dir>/pages/<slug>.json plus robots_directives, headers (x-robots-tag), and render{needed,used,delta}; Grep pages/<slug>.html for verbatim evidence. <run_dir>/site/robots.json carries, for the audited path, verdicts, effective_access{[bot]:{class, fetch, url_allowed, via, rule, signals, doc_url, robots_reliability}}, content_signals{present, placement, global, by_group[], malformed[], cloudflare_managed_hint}, groups, and ua_table_version. When the run included a user-agent diff, <run_dir>/ua-diff.json holds per-UA status/title/h1/word_count/canonical/robots/jsonld. Deterministic findings already emitted by audit.mjs are listed in <run_dir>/findings.deterministic.json — do not re-emit those ids; add model-judged findings only. If invoked directly with a URL/path and no snapshot exists, first run node "${CLAUDE_PLUGIN_ROOT}/scripts/snapshot.mjs" <target> --out "${CLAUDE_PLUGIN_DATA}/runs" and use the printed snapshot path.
Audits
Working from the PageSnapshot (parsed_rendered when render.used is not none, else parsed) plus site/robots.json:
- Google AI-feature eligibility (the established gate). Collect every
<meta name="robots">/<meta name="googlebot">tag and everyX-Robots-Tagheader value (header and meta both count; the most restrictive wins). Readnoindex/none,nosnippet,max-snippet:N, and thedata-nosnippetattributes — fordata-nosnippet, measure how much of the main content it covers and specifically whether it wraps the H1 or the lead passage. Also confirm Googlebot itself is not disallowed for this path. Record the scope: a directive coming from a template or a site-wide header isscope: template|site; one hand-written into a single document isscope: page. - Effective per-bot access. Read
effective_accessfor the audited path — not for/. A site can allow/and disallow/blog/, so root-level posture is not an answer. Check the retrieval/citation bots (OAI-SearchBot,Claude-SearchBot,PerplexityBot,Amazonbot,DuckAssistBot,Google-CloudVertexBot), the classic engines (Googlebot,Bingbot,Applebot), the training tokens (GPTBot,ClaudeBot,Google-Extended,Applebot-Extended,CCBot,Meta-ExternalAgent,cohere-ai,Bytespider), the user-fetch tokens (ChatGPT-User,Claude-User,Claude-Web,Perplexity-User,Meta-ExternalFetcher,MistralAI-User), andOAI-AdsBot. Current OpenAI tokens ship asGPTBot/1.4andOAI-SearchBot/1.4; match user-agents case-insensitively on the token, never on the full UA string. Anthropic publishes its crawler IP ranges atclaude.com/crawling/bots.json. Quoteua_table_versionin the report so a stale table is visible. - Content-Signal posture.
content_signalsreports thesearch/ai-input/ai-trainkeys, whether the line is global (Cloudflare's managed robots.txt appends it after all groups) or inside aUser-agentgroup, and any malformed pairs. A group line overrides the global line for that group. ADisallowalways wins over a signal:Disallow: /blocks the bot whateverai-trainsays, andAllow+ai-input=nomeans the page is still fetchable while consent is withheld — say exactly that, never "blocked". - User-agent divergence. Compare what the origin serves to
default,googlebot,gptbot,oai-searchbot, andclaude-searchbot: differing status, title, H1, word count, canonical, robots directives, or JSON-LD. Separate a bot challenge (403/429/503, interstitial, CAPTCHA markup, near-zero word count) from a genuine content difference. The search-axis cloaking judgment — Googlebot vs a browser being served different content — belongs to M2 (M2.cloaking.ua_content_divergence); M14 owns only the AI-bot access side. - Renderability for non-JS crawlers. Use the M4
renderblock. If the H1, the primary body, or the JSON-LD exists only inrendered_html_pathand is absent fromraw_html_path, the page is not reliably readable by AI crawlers that do not execute JavaScript. - Google-Extended sanity. If
Google-Extendedis disallowed, state plainly that this does not remove the site from AI Overviews or AI Mode — it limits Gemini training and grounding only.
Fixes
- AUTO (
fixable: auto): a citation-friendlyrobots.txtpreset, choice-gated — the user picksallow-citations(allow search/retrieval, opt out of training),allow-all, orblock-all. Presets inreferences/ai-crawlers.md; each ends with aContent-Signal:line that restates the same intent in that vocabulary. Deterministic, additive, verifiable; emitted as a diff forfix. - PROPOSED (
fixable: proposed): removing anosnippet/max-snippet:0/noindexthat the user confirms is unintended, and liftingdata-nosnippetoff the primary content. Never auto-written: a snippet control is often deliberate (paywall, licensing). - ADVISORY (
fixable: advisory): edge/WAF rules — unblocking a challenged AI bot, or blocking an agent that ignoresrobots.txt(e.g.Bytespider). The tool never writes infrastructure config. Never fabricate sitemap URLs, contact emails, or link targets — ask the user or leave a clearly-markedTODOplaceholder.
Verification
node "${CLAUDE_PLUGIN_ROOT}/scripts/parse-robots-sitemap.mjs" --url <final_url> --path <audited path>(methodrobots_parse) — resolves the effective directive per user-agent against the audited path and returnscontent_signals,effective_access, andua_table_version. Use--robots <robots_url>or--file <path>for an offline robots file.node "${CLAUDE_PLUGIN_ROOT}/scripts/ai-eligibility.mjs" --snapshot <pages/<slug>.json>(or--url <u>) — every meta-robots/X-Robots-Tagdirective,max-snippetvalue, and thedata-nosnippetcoverage share, including whether it wraps the H1/lead (methodsdom_assert+header_check).node "${CLAUDE_PLUGIN_ROOT}/scripts/ua-diff.mjs" --url <final_url> --ua default,googlebot,gptbot,oai-searchbot,claude-searchbot(methodua_diff) — per-UA response fields plus challenge detection.render_diffagainst the M4 result for the renderability check (primary content present inraw_html_path).- When the required tier is unavailable (
robots.txtunfetchable, no M4 render result, no UA diff run), status isneeds_apiormanual_review— never a falsepass.
Findings
Findings conform to schema/finding.schema.json. evidence.observed quotes the page, header, or robots line verbatim; verification.reproduce is one of the runnable commands above; expected_impact is banded + confidence-tagged (no naked %). Severity policy: 5 is reserved for catastrophic, eligibility-killing facts at site/template scope; 4 major · 3 moderate · 2 minor · 1 cosmetic · 0 informational — and only an established severity-5 fail in an active category can cap a score (references/scoring-model.md).
Google AI-feature eligibility — axis ai, confidence established except where noted; sources: Google AI features and your website and the robots-meta / X-Robots-Tag spec:
M14.ai_eligibility.not_indexable—noindex/none, or Googlebot disallowed for this path (fail, severity 5 at site/template scope, 4 for a single page,fixable: proposed).M14.ai_eligibility.nosnippet—nosnippetin a meta tag or header (fail, severity 5 site/template, 4 single page,fixable: proposed).M14.ai_eligibility.max_snippet_zero—max-snippet:0(fail, severity 5 site/template, 4 single page,fixable: proposed).M14.ai_eligibility.max_snippet_low— a positivemax-snippet:Nbelow our 50-word cutoff (warn, severity 2,fixable: advisory, confidencedirectional— the cutoff is ours, Google publishes no threshold).M14.ai_eligibility.data_nosnippet_primary—data-nosnippetwraps the H1 or the lead passage (fail, severity 4,fixable: proposed).M14.ai_eligibility.data_nosnippet_partial—data-nosnippetpresent but only around ancillary blocks (pass, severity 1).M14.ai_eligibility.ok— indexable and snippet-eligible, no suppressing directive (pass, severity 3).M14.google_extended.blocked_info—Google-Extendeddisallowed; informational, because it does not affect AI Overviews or AI Mode (pass, severity 1).
Third-party crawler access — axis ai:
M14.citation_bots.blocked— aDisallowreachesOAI-SearchBot/Claude-SearchBot/PerplexityBot(or another retrieval bot) on the audited path (fail, severity 4,fixable: auto). Confidence isestablishedonly when at least one blocked token is vendor-documented including its robots.txt behaviour (lib/bots.mjsrobots_reliability: 'documented'with adoc_url); when the block reaches only legacy or undocumented tokens (Claude-Web,MistralAI-User, or alimitedone likeMeta-ExternalFetcher) they are still listed as evidence, marked as such, and the confidence drops todirectional. The citation loss itself is stated asdirectionalinrationaleeither way.M14.retrieval.allowed— every retrieval/citation bot may fetch the audited path (pass, severity 4, confidencedirectional).M14.render.content_js_only— primary content, H1, or JSON-LD only inrendered_html_path(warn, severity 4,fixable: advisory, confidencedirectional).M14.access.ai_bot_challenged— an AI user-agent gets a challenge/interstitial or a near-empty body where the default UA gets the page (warn, severity 4,fixable: advisory, confidencedirectional).M14.access.googlebot_blocked_at_edge— the spoofedGooglebotUA is refused at the edge (warn, severity 2,fixable: advisory, confidencespeculative— refusing an unverified spoof is legitimate defence; verify with reverse DNS before acting).
Content-Signal — axis ai, never established (no vendor documents compliance; the IETF draft expired 2026-04 and defines vocabulary only):
M14.content_signal.ai_input_no—ai-input=no(warn, severity 3,fixable: advisory,directional): consent withheld for answer-engine input while the page stays fetchable.M14.content_signal.search_no—search=no(warn, severity 3,fixable: advisory,directional).M14.content_signal.ai_train_no—ai-train=no(pass, severity 1): a legitimate, low-cost preference that costs no citations.M14.content_signal.malformed— unknown key, non-yes|novalue, or an unparseable pair (warn, severity 2,fixable: auto).M14.content_signal.absent— noContent-Signalline (not_applicable, severity 0 — absence is not a defect).
Probes (owned by the geo command, listed here because they carry the M14 prefix): M14.probe.web_presence and M14.gsc_ai.impressions_present|zero_impressions|unavailable are severity 0, live under report.json.probes, and never move or cap a score.
Honesty
Google's own statements bound every claim in this module:
- A page reaches AI Overviews / AI Mode by being indexed and snippet-eligible in Search. There is no AI-specific file, token, schema type, or rewriting step that adds eligibility.
Google-Extendeddoes not affect AI Overviews or AI Mode. It limits training and Gemini/Vertex grounding. Blocking it is a training choice, not an AI-visibility choice.- Google Search ignores
llms.txt. It is reported under M21 at weight 0 and never moves the M14 category. - Search Console's generative-AI report exposes impressions only, and the Search Analytics API exposes no AI dimensions (checked 2026-08) — the tool never claims API-level AI citation data.
Further caveats:
- Content-Signal is metadata, not enforcement. No AI vendor documents compliance with it; every
M14.content_signal.*finding isdirectionalat most. ADisallowline does the work — never present a signal as a substitute, and never call anai-input=nopage "blocked" when it is still served. - UA-diff results are spoofed-UA results. We send the token, not a verified crawler: a site may legitimately refuse an unverified
Googlebotstring, and a CDN may serve a challenge to any unknown client. Treat divergence as a lead to verify (reverse DNS, server logs, Search Console URL Inspection), never as proof of cloaking. That is whyM14.access.googlebot_blocked_at_edgeisspeculative. - Blocking a training bot does not block the matching search bot —
GPTBot≠OAI-SearchBot,ClaudeBot≠Claude-SearchBot. Most "block AI" guides get this wrong and cost the site citations. Bytespiderand some user-fetchers (Meta documents thatMeta-ExternalFetchermay bypass robots.txt) do not reliably honorrobots.txt; a robots rule is best-effort and real enforcement needs an edge rule (advisory).robots.txtcontrols crawling, not indexing — to keep a page out of the index usenoindexand do not alsoDisallowit, or the crawler never sees the directive.
Signals
- GitHub stars
- 59
- Forks
- 5
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
seo-ai-crawlers- Source
- github.com/hainrixz/claude-seo-ai