seo-audit
Use when reviewing a page or site for organic search, or diagnosing why something isn't ranking: crawl and index signals, on-page elements, content quality, and how to order the fixes.
Install
npx skills add https://github.com/fcakyon/claude-codex-settings/tree/main/plugins/seo-skills/skills/seo-audit
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install fcakyon-claude-codex-settings@llmmart
git clone https://github.com/fcakyon/claude-codex-settings.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole fcakyon/claude-codex-settings collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
SEO audit
Audit in priority order, because the layers depend on each other. A page that can't be indexed doesn't benefit from a better title.
- Can it be found and indexed? Robots rules, canonical tags, noindex, redirect chains.
- Is the foundation sound? HTTPS, mobile rendering, speed, URL structure.
- Is the page optimized? Title, meta description, headings, keyword alignment, internal links, images.
- Does it deserve to rank? Depth, first-hand experience, sourcing, whether it beats what already ranks.
- Does it have credibility? Who links to it, who cites it.
Work down the list and stop where the evidence stops. Most asks are answered at layers 3 and 4.
What a fetch can and can't tell you
web_fetch returns the server's HTML as text. Everything you report as observed has to come from that, from a source you read, or from the caller.
Readable from a fetch: title tag, meta description, heading order and text, body copy, visible links and their anchor text, canonical tag, robots meta, hreflang in the HTML head, server-rendered JSON-LD, robots.txt and sitemap.xml when you fetch them directly.
Not readable, so not yours to assert: anything JavaScript injects after load, Core Web Vitals and any speed measurement, whether Google has actually indexed a URL, rank position, search volume, traffic, backlink counts, and whole-site facts like orphan pages or crawl budget that need a crawl you can't run.
The trap worth naming: CMS SEO plugins commonly inject JSON-LD client side, so a fetch shows no schema on a page that has plenty. Never conclude "no schema" from a fetch. Report that the server HTML carried none, and send them to the Rich Results Test at https://search.google.com/test/rich-results, which renders JavaScript.
For a check you can't run, name the check and the tool rather than skipping it silently. Search Console covers index coverage and queries; PageSpeed Insights covers Core Web Vitals; a crawler like Screaming Frog covers site-wide structure.
Diagnosing a page that isn't ranking
Work outward from the page before reaching for site-wide theories.
- Does the page target one query, and do the title, H1, URL, and opening paragraph agree on which one? Disagreement here explains more ranking problems than anything technical.
- Is another page on the site competing for the same query? Two mediocre pages on one keyword lose to one good one, and the fix is usually to merge them and redirect.
- Is the intent right? A product page will not rank for a question query however well optimized it is.
- Is it thinner than what ranks? Compare against the pages currently ranking rather than against a word count.
- Did something change? A migration, a redesign, or a template change dated near the drop is the first thing to check, and a drop that starts on a single date usually has a single cause.
References
references/audit-checklist.md: the per-area checks, each marked with whether a fetch can verify it.references/international-seo.md: hreflang, canonical interaction, and locale URL structure for multi-language sites, with the errors that silently void a whole cluster.
Reporting
Give each finding the problem, why it matters for search, the evidence, the fix, and its rank against the others. Open with the few things worth doing first, and close with what you couldn't check and what it would take. Group by layer, not by page, so someone can fix a class of problem once.
Files (claude-codex-settings)
-
references
-
audit-checklist.md 5.7 KB
# Audit checklist Per-area checks in priority order. The Evidence column says what it takes to verify the check honestly: `fetch` means a single `web_fetch` of the page or file is enough, `tool` means it needs access you don't have, so name it as unchecked rather than asserting it. ## 1. Crawl and index | Check | Evidence | | --- | --- | | `robots.txt` exists and doesn't block anything important | fetch | | `robots.txt` references the sitemap | fetch | | `sitemap.xml` exists, parses, and lists canonical indexable URLs only | fetch | | Sitemap has no redirected, 404, or noindexed URLs in it | fetch | | Page has a canonical tag, self-referencing when the page is the original | fetch | | No `noindex` on a page that should rank | fetch | | One canonical host (www or not, http or https) with the others redirecting | fetch | | Trailing-slash handling is consistent | fetch | | No redirect chains or loops on key paths | fetch | | The URL is actually indexed | tool: Search Console | | Indexed count matches expected count | tool: Search Console | | Crawl budget, faceted-navigation explosion, parameter duplication | tool: crawler | | Orphan pages across the site | tool: crawler | Soft 404s and near-duplicate clusters need Search Console. A page that returns 200 with no real content is visible from a fetch, so call that out directly. ## 2. Foundations | Check | Evidence | | --- | --- | | HTTPS everywhere, valid certificate, no mixed content | fetch | | Viewport meta present, layout not fixed-width | fetch | | URLs readable, lowercase, hyphenated, no session IDs or content in query strings | fetch | | Largest Contentful Paint under 2.5s | tool: PageSpeed Insights | | Interaction to Next Paint under 200ms | tool: PageSpeed Insights | | Cumulative Layout Shift under 0.1 | tool: PageSpeed Insights | | Server response time, caching headers, CDN, font loading | tool: PageSpeed Insights or WebPageTest | Page weight and blocking scripts are partly visible in fetched HTML: a head full of synchronous third-party scripts is worth flagging as a likely speed problem, framed as a hypothesis for them to confirm. ## 3. On-page | Check | Target | | --- | --- | | Title tag | Unique per page, primary keyword near the front, roughly 50 to 60 characters, brand at the end if included | | Meta description | Unique, roughly 150 characters or under since mobile truncates near 120, states the value and earns the click. Not a ranking factor | | H1 | Exactly one, describes the page, contains the target query or its clear paraphrase | | Heading order | H1 then H2 then H3 with no skipped levels, subheads readable as a map of the page | | Target query | Appears in the first 100 words, naturally, along with the phrasings a reader would actually use | | Keyword alignment | Title, H1, URL, and opening all point at the same query | | Cannibalization | No other page on the site targets the same query | | Internal links | Descriptive anchor text, no "click here", important pages linked more often, no broken links | | Images | Descriptive filenames, alt text that describes the image, compressed, modern format, lazy loaded below the fold | All of the above are fetch-verifiable except cannibalization, which needs either a site-wide crawl or the caller telling you what else exists. Ask. ## 4. Content quality Judge against the pages currently ranking for the query, not against a word count. Google is explicit that word count is not a ranking factor. - Experience: does it show first-hand use, original data, or real examples, or does it read assembled from other pages? - Expertise: is the author named and credentialed where that matters, and are claims sourced? - Trust: is there a real business behind it, contact details, a privacy policy, and no contradiction between what the page claims and what it shows? - Depth: does it answer the obvious follow-up question, or stop at the headline answer? - Currency: is anything dated, superseded, or describing a product that has changed? - Thin pages: tag and category pages with nothing unique, doorway pages, and pages that exist only to hold a keyword. ## 5. Authority Off-page work needs a backlink tool, so treat this as scoping rather than measurement: name whether the page has any obvious reason to be linked or cited, and what asset would earn links if it doesn't. Do not estimate a domain metric you cannot read. ## Common patterns by site type - SaaS: thin feature pages, blog disconnected from product pages, missing comparison and alternative pages, no glossary. - Ecommerce: thin category pages, duplicated manufacturer descriptions, missing product schema, faceted navigation generating duplicates, out-of-stock pages left to rot. - Content sites: stale posts never refreshed, several posts competing for one query, no topic clustering, weak internal linking, missing author pages. - Local: inconsistent name, address, and phone across pages, missing LocalBusiness schema, no location pages. - Multi-locale: see `international-seo.md`, since the failure modes there are specific and severe. ## Sources - Google Search Central, Search Essentials: https://developers.google.com/search/docs/essentials - Google Search Central, Creating helpful, reliable, people-first content: https://developers.google.com/search/docs/fundamentals/creating-helpful-content - Google Search Central, Robots.txt introduction: https://developers.google.com/search/docs/crawling-indexing/robots/intro - Google Search Central, Consolidate duplicate URLs: https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls - Google Search Central, Sitemaps overview: https://developers.google.com/search/docs/crawling-indexing/sitemaps/overview - web.dev, Core Web Vitals: https://web.dev/articles/vitals - Google Rich Results Test: https://search.google.com/test/rich-results -
international-seo.md 4.9 KB
# International SEO For sites serving several languages or regions. The failure modes here are unusually severe: a single missing annotation can void a whole locale cluster, and thin locale pages drag on site-wide quality rather than just their own rankings. Most of this is fetch-verifiable, since hreflang and canonical tags are in the served HTML. ## Hreflang Three placements are equivalent: a `<link>` in the head, an HTTP `Link` header, or `<xhtml:link>` in the sitemap. Pick one. If you use more than one and they disagree, the conflicting pair gets dropped. Past roughly ten locales, prefer the sitemap: it costs no page weight and no per-request work. What has to be true: - Every page includes a self-referencing entry. Without it, all hreflang on the page is ignored. - Links are reciprocal. If A points to B, B points back to A, or the pair is discarded. - Codes are ISO 639-1 language plus optional ISO 3166-1 alpha-2 region: `en`, `en-GB`. Never `en-UK`. - `x-default` is present and points at the fallback, either a language selector or the default locale. - Every target returns 200, is indexable, and matches its own canonical. - No duplicate language-region code points at two different URLs. The five errors worth checking first, because each is silent: a missing self-reference, a one-directional pair, an invalid code like `en-UK`, a target that is non-canonical or 404 or blocked, and HTML annotations that disagree with the sitemap. At scale, `<xhtml:link>` children don't count toward the 50,000-URL sitemap limit, but the 50 MB file limit becomes the binding constraint, so plan 2,000 to 5,000 URLs per file once every entry carries full hreflang. Hreflang is not required on every page: concentrate it where wrong-language traffic actually lands. Bing treats hreflang as a weak signal, so supplement with `<html lang>` for it. ## Canonical interaction This is where most multi-locale sites break, because canonical beats hreflang when the two disagree. - Each locale page self-canonicals: `/ar/page` points at `/ar/page`. - Never canonical across locales. Pointing French at English suppresses the French page entirely. - The canonical URL must appear in the page's own hreflang set. If it doesn't, all hreflang on the page is ignored. - Protocol and domain have to match across canonical, hreflang, and sitemap. - Paginated locale pages self-canonical per page. Never point page 2 at page 1. Common causes: a CMS canonicalizing every deep page to the homepage, a template canonicalizing all locales to English, and a protocol mismatch between canonical and hreflang. ## Locale URLs Subdirectories (`/en/`, `/ar/`) are the recommended default. Subdomains and ccTLDs work. Query parameters (`?lang=en`) do not. - Prefix every locale, including the default. Hiding the default locale's prefix stops Google distinguishing the versions. - Handle the root either as `x-default` with a redirect, or as the default locale's content. - Don't negotiate content by IP or `Accept-Language`. Googlebot crawls from US IPs and sends no `Accept-Language`, so it will only ever see one version. - Keep trailing-slash and case consistent across paths, canonicals, hreflang, and sitemaps, and 301 the non-canonical form. Search Console's International Targeting report is deprecated, so geotargeting now rests on hreflang, content signals, and linking patterns. ## Content across locales - Translate the whole page, not the chrome. Google reads visible content to determine language, so translating navigation while the body stays in the source language produces duplicates. - Machine translation is not inherently spam, but translations published at scale with no review can fall under scaled content abuse. - Don't create a locale you can't make genuinely useful. Thin locale pages are the worst of the options: noindexing them wastes crawl budget, and cross-locale canonicalizing them conflicts with hreflang. - Localize the details that signal a real regional presence: currency, phone format, address, date format. ## Framework note Next.js `alternates.languages` does not add a self-referencing `<xhtml:link>` for the `<loc>` URL. Add the current locale explicitly, or every page in the set ships without its self-reference and all hreflang is ignored. ## Sources - Google Search Central, Localized versions of your pages: https://developers.google.com/search/docs/specialty/international/localized-versions - Google Search Central, Managing multi-regional and multilingual sites: https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites - Google Search Central, Consolidate duplicate URLs: https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls - Google Search Central, Spam policies (scaled content abuse): https://developers.google.com/search/docs/essentials/spam-policies - Next.js, Internationalization metadata: https://nextjs.org/docs/app/api-reference/functions/generate-metadata
-
-
SKILL.md 3.6 KB
--- name: seo-audit description: "Use when reviewing a page or site for organic search, or diagnosing why something isn't ranking: crawl and index signals, on-page elements, content quality, and how to order the fixes." license: MIT --- # SEO audit Audit in priority order, because the layers depend on each other. A page that can't be indexed doesn't benefit from a better title. 1. Can it be found and indexed? Robots rules, canonical tags, noindex, redirect chains. 2. Is the foundation sound? HTTPS, mobile rendering, speed, URL structure. 3. Is the page optimized? Title, meta description, headings, keyword alignment, internal links, images. 4. Does it deserve to rank? Depth, first-hand experience, sourcing, whether it beats what already ranks. 5. Does it have credibility? Who links to it, who cites it. Work down the list and stop where the evidence stops. Most asks are answered at layers 3 and 4. ## What a fetch can and can't tell you `web_fetch` returns the server's HTML as text. Everything you report as observed has to come from that, from a source you read, or from the caller. Readable from a fetch: title tag, meta description, heading order and text, body copy, visible links and their anchor text, canonical tag, `robots` meta, `hreflang` in the HTML head, server-rendered JSON-LD, `robots.txt` and `sitemap.xml` when you fetch them directly. Not readable, so not yours to assert: anything JavaScript injects after load, Core Web Vitals and any speed measurement, whether Google has actually indexed a URL, rank position, search volume, traffic, backlink counts, and whole-site facts like orphan pages or crawl budget that need a crawl you can't run. The trap worth naming: CMS SEO plugins commonly inject JSON-LD client side, so a fetch shows no schema on a page that has plenty. Never conclude "no schema" from a fetch. Report that the server HTML carried none, and send them to the Rich Results Test at https://search.google.com/test/rich-results, which renders JavaScript. For a check you can't run, name the check and the tool rather than skipping it silently. Search Console covers index coverage and queries; PageSpeed Insights covers Core Web Vitals; a crawler like Screaming Frog covers site-wide structure. ## Diagnosing a page that isn't ranking Work outward from the page before reaching for site-wide theories. - Does the page target one query, and do the title, H1, URL, and opening paragraph agree on which one? Disagreement here explains more ranking problems than anything technical. - Is another page on the site competing for the same query? Two mediocre pages on one keyword lose to one good one, and the fix is usually to merge them and redirect. - Is the intent right? A product page will not rank for a question query however well optimized it is. - Is it thinner than what ranks? Compare against the pages currently ranking rather than against a word count. - Did something change? A migration, a redesign, or a template change dated near the drop is the first thing to check, and a drop that starts on a single date usually has a single cause. ## References - `references/audit-checklist.md`: the per-area checks, each marked with whether a fetch can verify it. - `references/international-seo.md`: hreflang, canonical interaction, and locale URL structure for multi-language sites, with the errors that silently void a whole cluster. ## Reporting Give each finding the problem, why it matters for search, the evidence, the fix, and its rank against the others. Open with the few things worth doing first, and close with what you couldn't check and what it would take. Group by layer, not by page, so someone can fix a class of problem once.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.