SEO SKILL

Full-site SEO audit

A full-site SEO audit that crawls, delegates to specialists and returns a 0 to 100 health score.

No key, no account neededClaude Code

Install the plugin
bash install.sh   # from a clone of github.com/AgriciDaniel/claude-seo, pinned to v2.3.1

Run this in a terminal inside your project folder. Claude Code, Cursor and Codex then read the skill from where it lands.

  1. Step 01Open a terminal in your project folder
  2. Step 02Paste the command and press Enter
  3. Step 03Pick the agents to install to
  4. Step 04Ask the agent for the job; it reads the skill

seo-auditAgriciDaniel/claude-seoMIT licencev2.3.1updated 2026-09-10

Give it a URL. It renders the homepage, works out what kind of business the site is, crawls up to 500 pages, and hands the findings to up to fifteen specialist sub-agents: Technical, Content, Schema, Sitemap, Performance, Visual, GEO, and the conditional ones (Local, Maps, Google Data, Backlinks, Clustering, Drift, Ecommerce).

What comes back is a folder: a full report, a prioritised action plan, a JSON envelope, per-category findings, screenshots if Playwright is present, and an offer to render an A4 PDF.

It is the orchestrator of the claude-seo plugin, so it is only as complete as the sub-skills and scripts installed beside it.

When to use it

The phrases that trigger it

Say any of these and an agent that has the skill installed will usually load it; you can also call it by name. The phrases are the skill’s own, from its description.

  • audit
  • full SEO check
  • analyze my site
  • website health check

What’s inside

The playbook, section by section

  • A seven-step process

    Render the homepage, detect the business type, crawl, delegate, score, persist the artefacts under `{domain}-audit/`, report.

  • Fifteen specialists, seven or eight always on

    Technical, Content, Schema, Sitemap, Performance, Visual and GEO run every time; Local, Maps, Google APIs, Backlinks, Clustering, Drift, Ecommerce and Search Experience are conditional. The frontmatter says 8 always and 7 conditional, the listing says 7 and 8; the skill disagrees with itself by one.

  • Weighted scoring

    Technical 22%, Content 23%, On-page 20%, Schema 10%, Performance 10%, AI Readiness 10%, Images 5%. The weights are the skill author’s choice, stated as such in the skill.

  • A JSON envelope the PDF reads

    Summary, categories with severity-tagged findings, a four-phase action plan, and artefact paths, so `google_report.py` can render a report even with no Google data.

  • Error handling as a table

    Unreachable URL, robots.txt blocks, 429s, timeouts on big sites, and a sub-agent running out of turns each have a written response. Partial findings are merged, not lost.

See it in action

One real run, in full

The request on the left went to the skill as installed. On the right is everything it returned, unedited; scroll inside the box to read it all.

You ask

Audit https://addition-labs.com. Cap the crawl at 10 pages. No subagents are available; run the specialist checks inline. Give the health score and the action plan.

The skill delivers

SEO Audit: addition-labs.com

Audit date: 2026-09-11 · Crawl: 10 pages (user cap) of 168 in the sitemap · Method: render_page.py, fetch_page.py, parse_html.py, sitemap_discovery.py, content_quality.py, analyze_visual.py, capture_screenshot.py via the claude-seo launcher; specialist checks run inline (no subagents available).

Executive Summary

SEO Health Score: 70 / 100

CategoryWeightScore
Technical SEO22%72
Content Quality23%70
On-Page SEO20%72
Schema / Structured Data10%78
Performance (CWV)10%55 (resource-weight estimate, no LCP/INP/CLS measured)
AI Search Readiness10%82
Images5%50

Business type detected: Agency. Signals: /case-studies (5 named clients), /industries (12 pages), client logos and "our partners" on the homepage, /services with four channels. A /pricing page is a secondary SaaS-like signal but the homepage copy ("the new-gen marketing agency for ecommerce and B2B brands") settles it. No local-service signals (the Sheridan, WY address in schema is a registered-agent address, no service area or map), so seo-local was not run. No e-commerce or drift baseline. Google API, Moz/Bing backlink and DataForSEO credentials are not configured, so those enrichments were skipped.

Top 5 issues
  1. Navigation, footer and the homepage case-study rail are JavaScript-only. Raw HTML of the homepage has 5 <a> tags (4 service links + #contact); the rendered DOM has 216 (96 unique). <nav> does not exist in the server response. Every crawled sub-page shows the same pattern (3 to 13 raw links). Google renders JS so this is not an indexing block, but the internal link graph, the client proof ("10,000+ dog parents", "100,000+ people in Turkey") and 43 of the 53 discovered URLs are invisible to any fetcher that does not execute JS, which includes most AI-search fetchers. The four resource sections (guides, glossary, compare, tools) are unreachable from the raw HTML of any crawled page.
  2. Hero images are 1 MB PNGs. seo.png 1,045,633 B, aeo.png 1,050,206 B, google-ads.png 1,129,315 B; the fourth panel (chatgpt-ads-official.webp) is 180 KB, which shows the target. No width/height, no srcset, no fetchpriority, and Cache-Control: max-age=0. seo.png is the visible hero panel and the likely LCP element.
  3. Broken link in the rendered nav: /shopify/chatgpt-ads returns 404 and is not in the sitemap.
  4. No security headers beyond HSTS. CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy and Permissions-Policy are all absent.
  5. Duplicate hosts/paths return 200: https://www.addition-labs.com/ and /index.html both serve the page instead of redirecting (the canonical tag points to the apex, so this is mitigated, not solved).
Top 5 quick wins
  1. Re-export the three hero PNGs as WebP/AVIF at rendered size and add width/height (expected ~100-200 KB each, like the existing webp).
  2. Fix or unlink /shopify/chatgpt-ads.
  3. vercel.json: redirect www. to apex and /index.html to /; add X-Content-Type-Options: nosniff, Referrer-Policy, and frame-ancestors; long-lived cache for /img, /fonts, /logo (JS/CSS already immutable).
  4. Homepage meta description is 50 characters ("We grow businesses with AI powered search systems."); the /industries/b2b (157) and /industries/ecommerce (154) descriptions are cut mid-sentence ("...from the problem they describe to."). Rewrite all three.
  5. Add <lastmod> to the sitemap: 0 of 168 URLs carry it.

Technical SEO (72)

Crawlability. robots.txt is User-agent: * / Allow: / plus the sitemap line; nothing is blocked for any bot. sitemap.xml is a valid single urlset with 168 URLs; sitemap_index.xml, sitemap-index.xml, wp-sitemap.xml correctly 404. Every URL discovered in the crawl is in the sitemap. The rendered homepage links to four URLs not in the sitemap: /cookies, /privacy, /terms (fine) and /shopify/chatgpt-ads (404).

Indexability. All 10 crawled pages: HTTP 200, self-referencing canonical, no meta robots, no X-Robots-Tag, lang="en", viewport meta present. /services/seo/ (trailing slash) 308-redirects to the clean path. Unknown paths return a real 404.

JS dependence. This is the audit's main structural finding. render_page.py --mode auto classified the homepage as not-SPA (body copy is server-rendered, 1,686 characters of extracted text raw vs 3,203 rendered), so the core copy is fine. What is missing from the raw response is the chrome: <nav>, the footer link columns (services, industries, resources, tools, legal), and the case-study rail with client names, numbers and outbound links. Raw-vs-rendered vocabulary diff: 241 words exist only after render, and they are the navigation and proof vocabulary (Industries, Resources, Case Studies, Pricing, Contact, Tools, Glossary, the client metrics).

Security. HTTPS everywhere, http:// 308s to https://, HSTS max-age=63072000. No other security headers.

Server. Vercel edge, X-Vercel-Cache: HIT, TTFB 0.136-0.145 s across three samples, HTML 37.8 KB.

Content Quality (70)

E-E-A-T. The homepage does the experience work: five named clients with linked sites and concrete claims (rendered only, see above). Service pages have none of it: no named person, no credential, no date, no reviewer, no proof block, and zero outbound links on any of the nine sub-pages crawled. /about is in the sitemap but outside the 10-page cap, so team signals were not verified.

Thin content. Raw word counts: /services/seo 440, /services/aeo 429, /services/chatgpt-ads 431, /services/google-ads 404, /services/seo/audit 416, /services/seo/content 403, /services/seo/consulting 414, /industries/ecommerce 374, /industries/b2b 270. These are short for commercial landing pages, and the three SEO sub-pages share one template (same H2 count, same image count, same schema). content_quality.py flags /services/seo as low-density (0.174) and /industries/b2b as repetitive (33).

What is good. content_quality.py: homepage 96, /industries/b2b 95, service pages 76-78; filler 0 and AI-pattern 0 on every page. The copy is specific and in a real voice. The FAQ answers on /services/seo and /services/google-ads are direct one-paragraph answers.

Duplicate content. None found among the 10 pages beyond the www/index.html duplicates above.

Readability. Not scored numerically by the tooling; sentences are short and plain on every page read.

On-Page SEO (72)

Titles. All unique, 20-48 characters, | Addition suffix. SEO Audit | Addition (20) and SEO Content | Addition (22) leave room for a qualifier ("for Shopify stores").

Meta descriptions. Present on all 10. Homepage 50 chars (too short); two industry descriptions truncated mid-sentence; the rest are 114-148 characters and read well.

Headings. One H1 per page. Homepage H1 is correct ("Turning Search Visibility into Sales.", with an aria-label). On the seven service pages the H1 wraps two spans, an eyebrow label and the headline, with no separator: a text parser reads AEO / AI VisibilityBeing cited is not being recommended. The homepage has two one-word H3s ("You", "We") flagged by parse_html.

Internal linking. Raw HTML: home 4 internal links, /industries/b2b 3, /services/aeo 8, /services/seo 13. No contextual body links from service pages to the guides, glossary or compare pages that support them.

Schema & Structured Data (78)

Current. Homepage: Organization (legalName ADDITION LABS LLC, email, PostalAddress, sameAs LinkedIn, logo) + WebSite linked via publisher @id. Sub-pages: Service (serviceType, provider, areaServed, description, url) and BreadcrumbList on most; WebPage on /services/aeo and /services/chatgpt-ads; FAQPage on /services/seo and /services/google-ads. All JSON-LD blocks parse as valid.

Validation issues. None syntactic. Consistency: /services/seo and /services/google-ads have Service + FAQPage but no BreadcrumbList; /services/aeo and /services/chatgpt-ads have BreadcrumbList + WebPage but no Service. areaServed: "US" on the SEO service while the cited clients are Turkish and EU brands.

FAQPage (Info). Google retired FAQ rich results for all sites on 7 May 2026; the markup earns no SERP feature. Leave it, do not add more for SERP reasons, no AI-citation benefit is claimed.

Missing opportunities. dateModified on Service/WebPage; a Person per service owner once one is named; BreadcrumbList everywhere from one template.

Performance (55, unmeasured CWV)

What was not measured. pagespeed_check.py returned PSI rate limit exceeded (240 QPM / 25,000 QPD) because no Google API key is configured, and CrUX field data needs the same key. There are therefore no LCP, INP or CLS numbers in this audit; the score is an estimate from resource weights and should be replaced by a real measurement (Phase 4).

What was measured.

  • TTFB 0.136-0.145 s; HTML 37.8 KB; JS bundle 20 KB (immutable cached); two variable fonts preloaded at 29 KB each.
  • Stylesheet /assets/planPicker-i2NZ610t.css is 228 KB, the only CSS file, render-blocking in <head> on every page.
  • Hero panels: three PNGs at 1.05-1.13 MB each plus one 180 KB WebP; no dimensions, no srcset, no fetchpriority; images cached max-age=0.
  • 86 of 91 homepage <img> tags have no width/height; 54 are loading="lazy", so late-arriving undimensioned images are a CLS risk.
  • Playwright: 0 console errors; desktop render 7.7 s, mobile render 3.0 s (wall-clock for a full render on this network, not a CWV metric).

Images (50)

  • No <img> is missing an alt attribute (0 of 91 on home, 0 on every sub-page). 64 of 91 on home are explicit alt="", mostly repeated platform logos; the same google-c.svg is alt="Google" in one place and alt="" elsewhere. Sub-pages: /industries/b2b 26/26 empty, /industries/ecommerce 35/36, /services/aeo 40/53.
  • The four hero panels have descriptive alt text.
  • 0 <picture>, 0 srcset on the homepage: 1 MB PNGs are sent to mobile as-is.
  • OG image: 1200×630 PNG, 66 KB, present on all pages.

AI Search Readiness (82)

  • Crawler access: nothing blocked; GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot and Google-Extended are all allowed by the wildcard rule.
  • llms.txt: /llms.txt returns 200 with a site description, the legal entity and address, and 168 links, the same set as the sitemap, each with a one-line summary. /llms-full.txt also 200.
  • Citability: body copy is server-rendered on every crawled page; FAQ answers are self-contained; Organization schema gives entity clarity.
  • Gap: the proof that makes the agency citable (client names, numbers, links) is JS-only on the homepage, and no page carries a visible date or dateModified (render_page publication_date: null).

Visual

Screenshots at desktop, laptop, tablet, mobile in addition-labs.com-audit/screenshots/. Desktop: H1, sub-copy, the four service panels and the "Schedule a meeting" CTA are above the fold. Mobile: the cookie banner occupies roughly the lower 40% of the viewport with a large empty block between its copy and the two buttons, pushing the hero sub-copy and CTA behind/below it. analyze_visual.py reports horizontal_scroll: true on mobile (no obvious offender in the capture; needs a manual check).

Action Plan

Priority definitions: Critical blocks indexing or causes penalties; High significantly impacts rankings (1 week); Medium is an optimisation (1 month); Low is backlog. Nothing found is Critical: the site is crawlable, indexable and secure at transport level.

Phase 1: Critical fixes (Week 1)
#PriorityActionHow we would know it failed
1HighServer-render <nav>, footer and the homepage case-study rail (prerender at build on Vite; keep JS as enhancement). Unblocks 4, 9, 11.`curl -s https://addition-labs.com/ \grep -c '<a '` still returns 5.
2HighRe-export the three hero PNGs as WebP/AVIF at rendered size; add width/height, srcset, fetchpriority="high" on the first panel.Any /img/hero-search/* still > 300 KB.
3MediumPublish or unlink /shopify/chatgpt-ads.URL still 404 while linked from nav.
Phase 2: High-impact improvements (Weeks 2-3)
#PriorityActionHow we would know it failed
4Mediumvercel.json: 308 www. to apex and /index.html to /; headers X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, CSP frame-ancestors; Cache-Control: max-age=31536000, immutable for /img, /fonts, /logo.curl -I https://www.addition-labs.com/ still 200.
5MediumRewrite the homepage meta description to 140-155 chars naming the four channels and the two audiences; finish the two truncated industry descriptions.Description length on / still < 100.
6LowMove the eyebrow span out of the service-page H1s (make it a <p class="eyebrow">).parse_html H1 still concatenates two lines.
7MediumAdd width/height to every <img>; srcset for hero and industry illustrations.Images without dimensions still > 10 on home.
8MediumSplit critical CSS for the hero; audit the 228 KB stylesheet for unused rules.CSS transfer still > 150 KB on /.
9LowEmit <lastmod> in the sitemap from build content dates.grep -c lastmod sitemap.xml still 0.
Phase 3: Content & authority (Month 2)
#PriorityActionHow we would know it failed
10MediumAdd to each pillar and sub-service page: one proof block (client, metric, method, timeframe), a named owner (name, role, LinkedIn) and a "last reviewed" date. Depends on nothing; strengthens 12.Service pages still name no person and link to no case study.
11MediumContextual body links from each service page to its matching guide, glossary and compare pages (today reachable only through rendered nav). Depends on 1 for the raw-HTML graph.Raw internal links per service page still < 15.
12LowStandardise schema on BreadcrumbList + Service (+ WebPage) from one template; correct areaServed; add dateModified.Two service pages still differ in schema set.
13LowCite primary sources on platform-fact claims (ChatGPT Ads, Performance Max).Sub-pages still have 0 external links.
14LowCollapse the mobile cookie banner to content height; find and fix the mobile horizontal-overflow element.Banner still covers > 25% of a 375 px viewport.
Phase 4: Monitoring & iteration (Ongoing)
  • Configure a Google API key (claude-seo run google_auth.py --setup) and re-run pagespeed_check.py for real LCP/INP/CLS; the Performance score above is provisional until then.
  • Leading indicators without re-auditing: Search Console index coverage for the 168 sitemap URLs (watch "Discovered, currently not indexed" for the resources sections), and the raw-HTML anchor count on /.
  • Re-run this audit after Phase 1 and compare: raw link count, hero weight, index coverage.

Artifacts written

addition-labs.com-audit/FULL-AUDIT-REPORT.md, ACTION-PLAN.md, audit-data.json, findings/{technical,content,on-page,schema,performance,geo,images,visual}.md, screenshots/addition-labs_com_{desktop,laptop,tablet,mobile}.png.

PDF report generated: addition-labs.com-audit/Google-SEO-Report-addition-labs.com-full.pdf (via google_report.py --type full; the Google-data sections inside it are empty because no Google API credentials are configured).

Limits of this audit

  • 10 of 168 pages crawled (user cap): the four pillar service pages, three SEO sub-pages, two industry pillars and the homepage. Guides, glossary, compare pages, tools, case studies, /about, /pricing, /contact were not fetched; findings about them are inferred from the sitemap and rendered links only.
  • No Core Web Vitals numbers (PSI rate-limited without a key; no CrUX key).
  • No backlink, SERP or keyword data (no Moz/Bing/DataForSEO credentials; Common Crawl domain cache empty).
  • No Google Search Console or GA4 data.

What this run could not do

No Core Web Vitals lab or field numbers (the PageSpeed check hit its rate limit without an API key; no CrUX key), no Search Console or GA4 data, no backlink metrics, no stored baseline for drift, and 158 of the 168 sitemap pages beyond the 10-page cap were not crawled. The seo-sxo, seo-cluster, seo-local and seo-backlinks specialist passes did not run, so they are not represented in the score.

Method behind it

Where we would differ, and why

Our own audit guide walks the same categories by hand and shows which of them move rankings and which are hygiene. Read it beside the skill’s score: the score tells you where you stand, the guide tells you what to fix first for a store.

The health score is a heuristic the plugin invented; Google publishes no such number. Treat 62 versus 68 as a direction, not a measurement.

The crawl cap of 500 pages is generous for a brochure site and small for a catalogue. On a large store, audit a section, not the domain.

Out of the box the Performance category cannot be measured: pagespeed_check.py calls PageSpeed Insights without a key and hits the shared quota at once. The 10% weight is scored from a lab proxy or left unscored until you add a Google API key.

How to run an ecommerce SEO audit

A PageSpeed Insights report showing a failed Core Web Vitals assessment, with LCP red and INP and CLS green
Thresholds from web.dev, last updated 7 May 2025. This is the one group on an audit checklist that arrives with a pass mark.From How to run an ecommerce SEO audit

SKILL.md

The file the agent reads

Written by Daniel Agrici and published under the MIT licence. Read the full file (1,145 words) on GitHub, at the commit we reviewed: AgriciDaniel/claude-seo/skills/seo-audit/SKILL.md.

Questions

Questions people ask before installing

Does it need DataForSEO or Google API keys?

No. Without them it runs the crawl-based checks and lab estimates. With Google credentials it replaces lab Core Web Vitals with CrUX field data and adds Search Console indexation; with DataForSEO it adds live SERP positions and backlink data.

Can I run just this skill without the whole plugin?

Not usefully. It calls the plugin launcher and delegates to sibling sub-skills. Install claude-seo as a plugin, then say "audit" with a URL.

What if the sub-agents are not available?

The skill says to run the specialists inline. Four of them (search-experience, clustering, local, backlinks) exist only as agents with no bundled script, so inline they have nothing to run and are absent from the score. The remaining checks run through the launcher scripts.