seo-technical-auditor
Audit technical SEO - indexation, sitemap, robots.txt, Core Web Vitals hints, redirects, canonical tags, and crawl errors. Use when a site underperforms in search or before a relaunch.
Install
npx skills add https://github.com/Navinspire-ia/navin/tree/main/navin/skills/seo-technical-auditor
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install navinspire-ia-navin@llmmart
git clone https://github.com/Navinspire-ia/navin.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole navinspire-ia/navin collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
SEO Technical Auditor
Find and prioritize technical issues that block ranking. Evidence first, checklist second. Operate like a senior technical SEO: grounded fetches, impact × effort triage, no invented CWV scores.
When to use
- Full site technical audit before relaunch or after traffic drops
- Indexation / crawlability suspicion
- Pre-migration checklist
When not to use
- Pure content strategy with no URL (use
keyword-research/seo-content-writer) - Paid ranking reports without API access (use MCP
search-consoleif connected, elseseo-data-provideror ask for GSC/PSI exports)
Audit checklist
| Area | What to check | How |
|---|---|---|
| Indexation | noindex, canonical conflicts, site: coverage |
fetch pages + web_search site:domain |
| robots.txt | blocked paths, sitemap line, crawl-delay | web_fetch https://domain/robots.txt |
| Sitemap | valid XML, fresh URLs, sample 404s | fetch /sitemap.xml (+ index children) |
| Redirects | chains, http→https, www, trailing slash | fetch variants; note status chain |
| Meta / head | title, description, robots, canonical, hreflang | sample 5-15 money pages |
| Structured data | JSON-LD presence/type | parse <script type="application/ld+json"> |
| Internal links | orphans, deep money pages | sample nav + footer + in-content |
| Performance | LCP/CLS/INP hints only | ask for PSI/CrUX URL or note "requires PSI" |
| HTTPS | mixed content signals | fetch http upgrade + page assets notes |
| Hreflang | reciprocal FR/EN/AR | head tags on language variants |
Workflow
- Run
seoactionpipelinefirst for a full audit, or composecrawl,audit,schema,psi,crux,score, andreport. - Treat engine findings and their evidence objects as the source of truth.
- Use
serp_snapshotonly with DataForSEO or Semrush credentials and retain source/confidence. - Preserve every
data_gap; do not replace missing PSI, CrUX, ranking, position, or volume data with estimates. - Add expert interpretation and prioritize findings as Critical / Important / Nice-to-have.
- The canonical health score comes from
seoactionscore. For legacy imported findings only, the helper remains available:
python navin/skills/seo-technical-auditor/scripts/audit_score.py findings.json
Or from workspace: python <skill_dir>/scripts/audit_score.py seo/audit-findings.json
- Save report under
seo/technical-audit-<domain>-<date>.mdand feedseo-report-*.html.
Finding severity
| Severity | Meaning | Examples |
|---|---|---|
| Critical | Blocks crawl/index or money page | sitewide noindex, sitemap 404, https broken |
| Important | Material ranking/UX drag | canonical loops, missing titles, thin money pages |
| Nice to have | Polish | missing FAQ schema, minor meta length |
Report format
## Technical SEO Audit - <domain>
Date / scope / pages sampled
### Critical (blocks ranking)
1. issue - URL - evidence - fix - effort (S/M/L)
### Important
...
### Nice to have
...
### Quick wins (this week)
- ...
### Data gaps
- Core Web Vitals: requires PageSpeed Insights / CrUX
- Index coverage: prefer MCP `search-console` when connected; else GSC export if site: is inconclusive
Rules
- Prefer live GSC via MCP
search-console(Settings → MCP) for index coverage, queries, and page performance when available; otherwise ask for a CSV export or mark the gap. - Every finding needs a URL + observed evidence (status, snippet, header).
- Never invent Lighthouse, CrUX, volume, or position data; use the engine's explicit
data_gap. - Prioritize by impact × effort; do not dump 100 undifferentiated issues.
- Sample-based audit is honest: state sample size, not "full crawl of N pages" unless you crawled them.
- Pair with
on-page-seo-optimizerfor page-level rewrites andseo-monitoringfor tracking.
Anti-patterns
- Auditing from memory without fetching the live site
- Claiming "Core Web Vitals fail" without data
- Mixing content strategy opinions into technical Critical
Files (navin)
-
scripts
-
audit_score.py 2.7 KB
#!/usr/bin/env python3 # Copyright (c) 2026-present Navinspire IA # SPDX-License-Identifier: AGPL-3.0-only """Score SEO audit findings by impact × effort for prioritization. Input JSON: list of objects or {"findings": [...]} with keys: id/title, severity (critical|important|nice|critical|...), impact (1-5), effort (1-5), url (optional) Prints a ranked markdown table and a 0-100 health score. """ from __future__ import annotations import json import sys from pathlib import Path SEVERITY_WEIGHT = { "critical": 5, "blocker": 5, "important": 3, "major": 3, "nice": 1, "nice_to_have": 1, "minor": 1, } def _load(path: Path) -> list[dict]: data = json.loads(path.read_text(encoding="utf-8")) if isinstance(data, dict): data = data.get("findings") or data.get("issues") or [] if not isinstance(data, list): raise SystemExit("JSON must be a list of findings or {findings: [...]}") return [row for row in data if isinstance(row, dict)] def _score(row: dict) -> float: sev = str(row.get("severity", "important")).lower().replace(" ", "_") impact = float(row.get("impact") or SEVERITY_WEIGHT.get(sev, 3)) effort = float(row.get("effort") or 3) effort = max(effort, 0.5) return (impact * SEVERITY_WEIGHT.get(sev, 3)) / effort def main() -> None: if len(sys.argv) < 2: print("Usage: audit_score.py findings.json", file=sys.stderr) raise SystemExit(2) path = Path(sys.argv[1]) findings = _load(path) if not findings: print("No findings.") return ranked = sorted(findings, key=_score, reverse=True) critical = sum( 1 for f in findings if str(f.get("severity", "")).lower() in {"critical", "blocker"} ) # Health: start 100, subtract weighted open issues (cap floor 0). penalty = 0.0 for f in findings: sev = str(f.get("severity", "important")).lower().replace(" ", "_") penalty += SEVERITY_WEIGHT.get(sev, 3) * 4 health = max(0, min(100, int(100 - penalty))) print("# Audit priority score\n") print(f"- Findings: {len(findings)}") print(f"- Critical/blocker: {critical}") print(f"- Health score (heuristic): {health}/100\n") print("| Priority | Title | Severity | Impact | Effort | URL |") print("|----------|-------|----------|--------|--------|-----|") for i, row in enumerate(ranked, 1): title = str(row.get("title") or row.get("id") or row.get("issue") or "finding") sev = str(row.get("severity", "")) impact = row.get("impact", "") effort = row.get("effort", "") url = str(row.get("url") or "") print(f"| {i} | {title} | {sev} | {impact} | {effort} | {url} |") if __name__ == "__main__": main()
-
-
SKILL.md 4.3 KB
--- name: seo-technical-auditor description: Audit technical SEO - indexation, sitemap, robots.txt, Core Web Vitals hints, redirects, canonical tags, and crawl errors. Use when a site underperforms in search or before a relaunch. metadata: {"navin":{"emoji":"🔧","category":"seo"}} --- # SEO Technical Auditor Find and prioritize technical issues that block ranking. Evidence first, checklist second. Operate like a senior technical SEO: grounded fetches, impact × effort triage, no invented CWV scores. ## When to use - Full site technical audit before relaunch or after traffic drops - Indexation / crawlability suspicion - Pre-migration checklist ## When not to use - Pure content strategy with no URL (use `keyword-research` / `seo-content-writer`) - Paid ranking reports without API access (use MCP `search-console` if connected, else `seo-data-provider` or ask for GSC/PSI exports) ## Audit checklist | Area | What to check | How | |------|---------------|-----| | Indexation | noindex, canonical conflicts, `site:` coverage | fetch pages + web_search `site:domain` | | robots.txt | blocked paths, sitemap line, crawl-delay | `web_fetch https://domain/robots.txt` | | Sitemap | valid XML, fresh URLs, sample 404s | fetch `/sitemap.xml` (+ index children) | | Redirects | chains, http→https, www, trailing slash | fetch variants; note status chain | | Meta / head | title, description, robots, canonical, hreflang | sample 5-15 money pages | | Structured data | JSON-LD presence/type | parse `<script type="application/ld+json">` | | Internal links | orphans, deep money pages | sample nav + footer + in-content | | Performance | LCP/CLS/INP hints only | ask for PSI/CrUX URL or note "requires PSI" | | HTTPS | mixed content signals | fetch http upgrade + page assets notes | | Hreflang | reciprocal FR/EN/AR | head tags on language variants | ## Workflow 1. Run `seo` action `pipeline` first for a full audit, or compose `crawl`, `audit`, `schema`, `psi`, `crux`, `score`, and `report`. 2. Treat engine findings and their evidence objects as the source of truth. 3. Use `serp_snapshot` only with DataForSEO or Semrush credentials and retain source/confidence. 4. Preserve every `data_gap`; do not replace missing PSI, CrUX, ranking, position, or volume data with estimates. 5. Add expert interpretation and prioritize findings as Critical / Important / Nice-to-have. 6. The canonical health score comes from `seo` action `score`. For legacy imported findings only, the helper remains available: ```bash python navin/skills/seo-technical-auditor/scripts/audit_score.py findings.json ``` Or from workspace: `python <skill_dir>/scripts/audit_score.py seo/audit-findings.json` 7. Save report under `seo/technical-audit-<domain>-<date>.md` and feed `seo-report-*.html`. ## Finding severity | Severity | Meaning | Examples | |----------|---------|----------| | Critical | Blocks crawl/index or money page | sitewide noindex, sitemap 404, https broken | | Important | Material ranking/UX drag | canonical loops, missing titles, thin money pages | | Nice to have | Polish | missing FAQ schema, minor meta length | ## Report format ```markdown ## Technical SEO Audit - <domain> Date / scope / pages sampled ### Critical (blocks ranking) 1. issue - URL - evidence - fix - effort (S/M/L) ### Important ... ### Nice to have ... ### Quick wins (this week) - ... ### Data gaps - Core Web Vitals: requires PageSpeed Insights / CrUX - Index coverage: prefer MCP `search-console` when connected; else GSC export if site: is inconclusive ``` ## Rules - Prefer live GSC via MCP `search-console` (Settings → MCP) for index coverage, queries, and page performance when available; otherwise ask for a CSV export or mark the gap. - Every finding needs a URL + observed evidence (status, snippet, header). - Never invent Lighthouse, CrUX, volume, or position data; use the engine's explicit `data_gap`. - Prioritize by impact × effort; do not dump 100 undifferentiated issues. - Sample-based audit is honest: state sample size, not "full crawl of N pages" unless you crawled them. - Pair with `on-page-seo-optimizer` for page-level rewrites and `seo-monitoring` for tracking. ## Anti-patterns - Auditing from memory without fetching the live site - Claiming "Core Web Vitals fail" without data - Mixing content strategy opinions into technical Critical
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.