agentleFS
DarynaRodriguezDarynaRodriguez/seo-skills/skills/indexation-check/SKILL.md

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
  1. Distinctive:

    Read the site profile before anything else:

    line 17
  2. Distinctive:

    Never invent profile values.

    line 25
  3. Very specific:

    Never invent a metric. Impressions in Search Console prove a URL was served.

    line 52
  4. Very specific:

    Every command takes --json, which is the form to use here.

    line 75
  5. Very specific:

    Write the joined set arithmetic to .seo/indexation.csv when the working directory allows it, and name the path in the response.

    line 233
  6. Distinctive:

    Never claim a URL is not indexed because it has no impressions.

    line 238
  7. Distinctive:

    Never recommend blocking a URL in robots.txt in order to de-index it.

    line 241
  8. Distinctive:

    Never flag a noindex as a defect when the profile lists that page among those that must never be indexed.

    line 243
  9. Distinctive:

    Never de-index, edit robots.txt or remove sitemap entries yourself.

    line 245
  10. Distinctive:

    Never state a traffic figure for a class B page.

    line 247
  11. Distinctive:

    Never dump the full URL list into the deliverable.

    line 249

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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:

  1. .seo/profile.md in the working directory
  2. ~/.seo-skills/profile.md
  3. 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-setup so 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:

FieldProfile sectionWhy it changes the answer
CMS or platform1. SiteDecides which page types are generated and indexable by default
Markets, languages, hreflang pairs2. MarketsDecides whether a language variant in the index is right or wrong
Pages that must never be indexed8. Site structureTurns a noindex from a defect into intended behaviour
Privacy-sensitive surfaces8. Site structureAn indexable one is a risk to escalate, never an opportunity to exploit
Pillar, solution and blog paths8. Site structureDefines the set that must be indexed
Who can publish1. SiteThe named approver for any de-indexing or robots change

Data

NeedOur stackOtherwise
Every URL the crawler found, with status, canonical and robots directivesmcp__Ahrefs__site-audit-page-explorerAsk for a Screaming Frog or Sitebulb export including indexability columns
Which audit project and how fresh the crawl ismcp__Ahrefs__site-audit-projectsAsk for the crawl date with the export
Issue counts for noindex, blocked and canonical classesmcp__Ahrefs__site-audit-issuesDerive the classes from the export
Pages seen from outside the site auditmcp__Ahrefs__site-explorer-crawled-pagesCompare the sitemap against the supplied crawl
Pages actually receiving impressions, which proves index membershipmcp__Ahrefs__gsc-pagesAsk for a Search Console page export; without it, index membership is inferred, and say so
Internal link counts, to find orphansmcp__Ahrefs__site-explorer-pages-by-internal-linksDerive inlink counts from the crawl export
Rendered head of one page, to confirm a directivemcp__Ahrefs__site-audit-page-contentFetch 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:

NeedCommand
Discover the sitemaps and count what they declarepython -m seo_tools sitemap <url> --expand --json
Check one URL for noindex, canonical and statuspython -m seo_tools page <url> --json
Compare what the crawl found against what the sitemaps declarepython -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

  1. Build the three sets. Everything in this skill is set arithmetic, so build the sets before drawing any conclusion.

    SetSourceWhat it means
    S: declaredThe sitemap, plus the profile's page inventoryWhat the site says should be indexed
    C: crawledsite-audit-page-explorer and site-explorer-crawled-pagesWhat exists and is reachable, with its status and directives
    I: impressedgsc-pages over a long window, 3 months or moreProof of index membership for anything that got an impression
  2. Report the four failure classes, in this order. They differ in cost, and the first two are the ones that change revenue:

    ClassSet arithmeticTypical cause
    A. Should be indexed, is notIn S and C, absent from I over a long window, and no directive explaining itnoindex left on after staging, canonical pointing elsewhere, blocked by robots, orphaned, thin, or too new
    B. Indexed, should not beIn C or I, but not a page the profile wants publicDefault-on templates and confirmation pages
    C. Indexed under the wrong canonical or wrong language variantIn I, but the URL serving impressions is a variant, a parameter form, or the other market's pageCanonical faults, missing or one-way hreflang, market targeting
    D. OrphanedIn S or C with zero internal inlinksRemoved from navigation, published outside the template, retired hub
  3. 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.

  4. Diagnose the mechanism, not the symptom. For every class A and class B row, name which control is doing the work: robots.txt disallow, noindex meta or X-Robots-Tag header, 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.
  5. Do not confuse blocked with noindexed. This is the single most common mistake in this area:

    ControlWhat it doesWhat it does not do
    robots.txt disallowStops crawling of that pathDoes not remove the URL from the index. A blocked URL can still be indexed from links alone, and will show with no useful snippet
    noindex meta or headerKeeps the URL out of the index, once the crawler reads itDoes 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, serve noindex, 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 the noindex, and say that removal requests are temporary.

  6. 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.
  7. 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.
  8. 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.
  9. 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.
  10. 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.

  11. 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

classurl_classcountexamplescausefixrisk_if_leftdestructiveowner
  • class is A should-be-indexed-is-not, B indexed-should-not-be, C wrong-canonical-or-variant, D orphaned.
  • url_class is the page type in plain words, for example blog tag archives, gated download confirmations.
  • examples is up to three URLs, never a full dump.
  • cause names the control: robots disallow, noindex meta, X-Robots-Tag, canonical target, status code, no internal links.
  • risk_if_left is 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

checkresultdetail

Rollback notes (every destructive row)

actioncurrent directivewhere it livesrestore stepapprover

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.

Download now (ZIP)

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.