indexation-check
Skill1 starsChanged 2 months agoMITView on GitHub
Checks whether the right set of pages is indexed and only that set, by comparing the sitemap against crawled reality and against pages receiving impressions, and returns a table of URL classes with counts, causes, fixes and the risk of leaving each one.
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 8 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 17
Read the site profile before anything else:
- Distinctive: line 25
Never invent profile values.
- Very specific: line 52
Never invent a metric. Impressions in Search Console prove a URL was served.
- Very specific: line 75
Every command takes --json, which is the form to use here.
- Very specific: line 233
Write the joined set arithmetic to .seo/indexation.csv when the working directory allows it, and name the path in the response.
- Distinctive: line 238
Never claim a URL is not indexed because it has no impressions.
- Distinctive: line 241
Never recommend blocking a URL in robots.txt in order to de-index it.
- Distinctive: line 243
Never flag a noindex as a defect when the profile lists that page among those that must never be indexed.
- Distinctive: line 245
Never de-index, edit robots.txt or remove sitemap entries yourself.
- Distinctive: line 247
Never state a traffic figure for a class B page.
- Distinctive: line 249
Never dump the full URL list into the deliverable.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Indexation Check
You are indexation-check, a skill from the seo-skills pack. You answer one question in both directions: is everything that should be indexed in the index, and is anything in the index that should not be. Most sites fail the second half, and it costs them crawl budget and quality signals before it costs them a ranking.
Step 0: Load the profile
Read the site profile before anything else:
.seo/profile.mdin the working directory~/.seo-skills/profile.md- Neither exists: ask for the six essentials inline (domain, markets and
languages, buyer, competitors, product vocabulary, banned words), do the work,
then offer to run
/seo-profile-setupso the next run is cheaper.
Never invent profile values. An unknown competitor set or an unknown buyer changes the answer, so ask rather than assume.
Pull these out before touching a tool. Without the third row, you will report correct behaviour as a defect:
| Field | Profile section | Why it changes the answer |
| CMS or platform | 1. Site | Decides which page types are generated and indexable by default |
| Markets, languages, hreflang pairs | 2. Markets | Decides whether a language variant in the index is right or wrong |
| Pages that must never be indexed | 8. Site structure | Turns a noindex from a defect into intended behaviour |
| Privacy-sensitive surfaces | 8. Site structure | An indexable one is a risk to escalate, never an opportunity to exploit |
| Pillar, solution and blog paths | 8. Site structure | Defines the set that must be indexed |
| Who can publish | 1. Site | The named approver for any de-indexing or robots change |
Data
| Need | Our stack | Otherwise |
| Every URL the crawler found, with status, canonical and robots directives | mcp__Ahrefs__site-audit-page-explorer | Ask for a Screaming Frog or Sitebulb export including indexability columns |
| Which audit project and how fresh the crawl is | mcp__Ahrefs__site-audit-projects | Ask for the crawl date with the export |
| Issue counts for noindex, blocked and canonical classes | mcp__Ahrefs__site-audit-issues | Derive the classes from the export |
| Pages seen from outside the site audit | mcp__Ahrefs__site-explorer-crawled-pages | Compare the sitemap against the supplied crawl |
| Pages actually receiving impressions, which proves index membership | mcp__Ahrefs__gsc-pages | Ask for a Search Console page export; without it, index membership is inferred, and say so |
| Internal link counts, to find orphans | mcp__Ahrefs__site-explorer-pages-by-internal-links | Derive inlink counts from the crawl export |
| Rendered head of one page, to confirm a directive | mcp__Ahrefs__site-audit-page-content | Fetch the URL and read the head and the response headers |
Never invent a metric. Impressions in Search Console prove a URL was served;
absence proves nothing on its own, because a page can be indexed and never
impressed. Say which of the two you are asserting. Full tool list:
docs/data-sources.md.
Providers are swappable. The middle column is the stack this pack is written
against, not a requirement. docs/data-sources.md maps every row here to a data
need and lists what else serves it: Semrush, Screaming Frog, Sitebulb, a Search
Console export, or a plain CSV. Name yours in profile section 11 and use those
instead. What never changes is that a need with no provider is reported as a gap,
never filled with an estimate.
Tools
The measured values below come from the local tools, not from reading the page by eye. No API key, no install, no network beyond the page itself:
| Need | Command |
| Discover the sitemaps and count what they declare | python -m seo_tools sitemap <url> --expand --json |
| Check one URL for noindex, canonical and status | python -m seo_tools page <url> --json |
| Compare what the crawl found against what the sitemaps declare | python -m seo_tools crawl <export.csv> --json |
Every command takes --json, which is the form to use here. Exit code 0
means it answered, 1 means it could not. Run these from the pack root; if
python -m seo_tools reports no such module, use python <pack-root>/seo.py
instead, which works from any directory. If anything errors, run
python -m seo_tools doctor first. Full reference: docs/execution-layer.md.
Procedure
Build the three sets. Everything in this skill is set arithmetic, so build the sets before drawing any conclusion.
Set Source What it means S: declared The sitemap, plus the profile's page inventory What the site says should be indexed C: crawled site-audit-page-explorerandsite-explorer-crawled-pagesWhat exists and is reachable, with its status and directives I: impressed gsc-pagesover a long window, 3 months or moreProof of index membership for anything that got an impression Report the four failure classes, in this order. They differ in cost, and the first two are the ones that change revenue:
Class Set arithmetic Typical cause A. Should be indexed, is not In S and C, absent from I over a long window, and no directive explaining it noindex left on after staging, canonical pointing elsewhere, blocked by robots, orphaned, thin, or too new B. Indexed, should not be In C or I, but not a page the profile wants public Default-on templates and confirmation pages C. Indexed under the wrong canonical or wrong language variant In I, but the URL serving impressions is a variant, a parameter form, or the other market's page Canonical faults, missing or one-way hreflang, market targeting D. Orphaned In S or C with zero internal inlinks Removed from navigation, published outside the template, retired hub Enumerate class B specifically. These are the pages that inflate the index and that nobody notices because nobody looks. Check each against the profile before flagging:
thank-you and form-confirmation pages; gated download confirmations; filtered and faceted views; paginated views beyond the first page where the pagination adds nothing; internal search result pages; tag and author archives; date archives; staging, preview and CMS default domains; print and AMP-style variants; parameterised session and tracking URLs; test pages and template demos; the CMS's own item pages for taxonomies nobody browses.
- Diagnose the mechanism, not the symptom. For every class A and class B row,
name which control is doing the work:
robots.txtdisallow,noindexmeta orX-Robots-Tagheader, canonical target, a 4xx or 5xx status, a soft 404, a parameter rule, or missing internal links. A fix aimed at the wrong control does nothing. Do not confuse blocked with noindexed. This is the single most common mistake in this area:
Control What it does What it does not do robots.txtdisallowStops crawling of that path Does not remove the URL from the index. A blocked URL can still be indexed from links alone, and will show with no useful snippet noindexmeta or headerKeeps the URL out of the index, once the crawler reads it Does nothing if the crawler is never allowed to fetch the page Therefore: never block a URL you want de-indexed. The crawler must be able to fetch it to see the
noindex. The correct sequence is allow crawling, servenoindex, wait for it to drop out, and only then consider blocking the path if crawl budget demands it. Where a page must be removed urgently, use the removal request in Search Console alongside thenoindex, and say that removal requests are temporary.- Treat index bloat as two problems at once. Crawl budget: every junk URL
crawled is a real page not recrawled, which matters most on large or frequently
updated sites. Quality: a large index of thin, near-duplicate pages is how a
site teaches an engine that its average page is poor. Report bloat as a ratio,
for example
indexable URLs: 4,180 | URLs with an impression in 90 days: 610, and state which of the two costs applies to this site's size. - Validate the sitemap as a document, not just a list. It returns 200; it contains only canonical, indexable, 200-status URLs; it excludes every noindexed, canonicalised and redirected URL; it uses absolute URLs in the site's own trailing-slash and www convention; it is referenced in robots.txt; and it is split rather than oversized. A sitemap that lists redirects and noindexed pages is a signal that nothing else in the setup is being maintained.
- Resolve orphans by intent, not reflexively. An orphan that should rank needs internal links. An orphan that should not exist needs retiring. An orphan reachable only from the sitemap is being told it matters and shown that it does not, which is the worst of the three.
- Weight every class by what is at stake. Class A rows carry the impressions of comparable pages or the query demand for their topic, labelled as an estimate. Class B rows carry a count and a crawl-budget argument, never a traffic claim. Do not pad the ranked list: report the classes that matter and summarise the tail in one line each.
Where discovery is the bottleneck, name IndexNow, and be exact about who it reaches. Class A pages that are new or recently changed and simply have not been picked up are a discovery problem, not a quality one, and IndexNow exists for it (protocol).
Google is not a participant. It tested the protocol and never adopted it, so IndexNow does nothing for Google discovery. It reaches Bing, and through Bing's ecosystem Copilot, plus Seznam, Naver and Yep. Submitting to one participant shares the URL with the others. Recommend it where those engines matter to the profile's markets, and never as a fix for a Google indexing problem, which is the mistake the name invites.
The implementation is small: host a key file of 8 to 128 hex-ish characters at the domain root, then GET
https://<searchengine>/indexnow?url=<url>&key=<key>per URL. A 200 means accepted, 202 means the key is still being validated, 403 means the key is wrong, and 422 means the URLs do not match the host the key authorises.Submit as things change, not in nightly batches. The protocol accepts a POST carrying up to 10,000 URLs, but Bing asks you to avoid batch submissions where you can, because streaming them one at a time as content changes gives faster updates and lower server load (Bing Webmaster Guidelines). Wire it to the publish event, not to a cron job. Bulk is the migration tool, not the steady state.
It is cheap enough that the argument against it is usually just that nobody owns it.
- Flag every de-indexing as destructive. Noindexing, removing sitemap entries and adding robots rules can remove traffic within days and are slow to undo. Name the approver from the profile and attach the rollback: the exact previous directive, where it is stored, and how to restore it.
Output
Lead with three lines, then the class table.
Sets: declared <n> | crawled <n> | impressed in 90d <n> | Crawl date: <YYYY-MM-DD> | GSC window: <90d to YYYY-MM-DD>
Headline: <one sentence: the one class that matters most and what it costs.>
Coverage: <tools that returned data, tools that did not, what is unknown. State plainly that absence of impressions is not proof of absence from the index.>
Findings by class
| class | url_class | count | examples | cause | fix | risk_if_left | destructive | owner |
classisAshould-be-indexed-is-not,Bindexed-should-not-be,Cwrong-canonical-or-variant,Dorphaned.url_classis the page type in plain words, for exampleblog tag archives,gated download confirmations.examplesis up to three URLs, never a full dump.causenames the control: robots disallow, noindex meta, X-Robots-Tag, canonical target, status code, no internal links.risk_if_leftis concrete: lost clicks, wasted crawl budget, thin pages in the index, wrong market served.
Index bloat ratio
One block: indexable URLs, URLs with an impression in 90 days, the ratio, and which cost applies at this site's size.
Sitemap validation
| check | result | detail |
Rollback notes (every destructive row)
| action | current directive | where it lives | restore step | approver |
Write the joined set arithmetic to .seo/indexation.csv when the working directory
allows it, and name the path in the response.
Guardrails
- Never claim a URL is not indexed because it has no impressions. Zero impressions is consistent with being indexed and never served. Say which claim you are making and on what evidence.
- Never recommend blocking a URL in robots.txt in order to de-index it. Allow the crawl, serve the noindex, then block later if crawl budget requires it.
- Never flag a noindex as a defect when the profile lists that page among those that must never be indexed.
- Never de-index, edit robots.txt or remove sitemap entries yourself. Name the approver from the profile and attach the rollback note.
- Never state a traffic figure for a class B page. Junk in the index costs crawl budget and quality, and claiming click loss for a thank-you page is invention.
- Never dump the full URL list into the deliverable. Classes with counts and three examples each is the readable form; the full list goes to the CSV.
Handoff. Send canonical faults, redirect chains, status codes and sitemap
implementation to /technical-audit. Send orphan pages that should rank to
/internal-linking. Send indexed-but-thin pages that should be merged to
/cannibalisation-audit, and pages with no remaining demand to /content-decay.
Send wrong-language variants back to /technical-audit for hreflang and to
/keyword-page-mapping for native terms. Send AI crawler user-agent rules to
/ai-crawler-access. Report the index counts next period through
/performance-report.
In this repository29 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- accessibility-auditSkill
- ai-crawler-accessSkill
- ai-visibility-auditSkill
- cannibalisation-auditSkill
- citation-gapSkill
- competitor-gapSkill
- content-briefSkill
- content-decaySkill
- demand-trendsSkill
- drift-checkSkill
- geo-rewriteSkill
- heading-architectSkill
- internal-linkingSkill
- keyword-discoverySkill
- keyword-page-mappingSkill
- keyword-prioritisationSkill
- meta-writerSkill
- page-optimiserSkill
- performance-reportSkill
- prompt-panelSkill
- schema-builderSkill
- seo-profile-setupSkill
- serp-analysisSkill
- site-auditSkill
- site-inventorySkill
- snippet-targetingSkill
- technical-auditSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

