CommunityRedacción y edicióngithub.com

ssheleg/seo-aeo-audit

Evidence-first website audit for search AND answer engines. Ten tracks from crawl access to AI citation mechanics; every finding carries an observation, every recommendation an evidence tier. Output is a prioritized change plan plus a link-building brief with keyword CSV — not a score.

¿Qué es seo-aeo-audit?

seo-aeo-audit is a Claude Code agent skill that evidence-first website audit for search AND answer engines. Ten tracks from crawl access to AI citation mechanics; every finding carries an observation, every recommendation an evidence tier. Output is a prioritized change plan plus a link-building brief with keyword CSV — not a score.

Compatible conClaude Code~Codex CLI~CursorGemini CLI
npx skills add ssheleg/seo-aeo-audit

Installed? Explore more Redacción y edición skills: steipete/notion, affaan-m/seo, affaan-m/brand-voice · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

seo-aeo-audit — audit search + answer-engine visibility, then ship a plan

One job: look at a real site, prove what is wrong with evidence, and hand back a prioritized plan of changes that covers classic search (Google, Yandex, Bing) and answer engines (AI Overviews / AI Mode, ChatGPT, Perplexity, Claude, Copilot, Gemini, Alice AI).

Not this skill's job: writing the content, building the pages, buying links. It ends at a verified diagnosis and an executable plan.

Non-negotiables

  1. Evidence or silence. Every finding carries: what you observed, where (URL, file:line, report name), the observed value, and the date. Never report a finding you did not verify on this site. "Best practice says" is not evidence.
  2. Label the evidence tier of every recommendation (see references/evidence-tiers.md): CONFIRMED (documented by the engine or reproduced on this site) · STUDY (published multi-site data) · FIELD (single-case report) · HYPOTHESIS. Never let a HYPOTHESIS out-rank a CONFIRMED blocker.
  3. Diagnose before prescribing. No fix goes in the plan until its cause is located. "Add schema" is not a diagnosis.
  4. Refuse the myth list. See "Myth guard" below — recommending those wastes the client's budget and is a defect, not a nicety.
  5. Never recommend deceptive tactics. Cloaking, fabricated consensus networks, review manipulation, competitor takedown abuse and click-signal spoofing stay out of the plan. They appear in this skill only in references/threats-and-defense.md, as things to detect and defend against.
  6. State what you could not check. A missing GSC login is a gap in the report, not a silent omission.
  7. Never blend measured with assumed. When one deliverable carries both — a link-building CSV always does — a source column separates them and the volume cells of an unmeasured row stay blank, not zero. A 0 reads as "measured, no demand"; blank reads as "nobody has checked". The distinction matters most in work someone else executes on a budget.
  8. Know each instrument's blind spot, and say it in the output. Rules 1 and 7 govern what you write; they do not see a tool that blends or omits before you ever look. Two arrive constantly. A static fetch cannot see JSON-LD that the CMS injects with JavaScript, so "no schema found" is a false finding on any Yoast/RankMath/AIOSEO site — scripts/page_audit.py prints the caveat next to every schema inventory, and absence is only reportable after a rendering check. GA4 with consent-mode modelling returns observed and estimated behaviour inside one number — see references/measurement.md J1 for the three activation conditions, the visible indicator, and the observed-only fallback. The rule generalizes: before an instrument's silence becomes a finding, establish that the instrument could have seen the thing at all.

Step 0 — Detect mode, never ask twice

Inspect first, then act. In order:

  1. Read docs/seo/ (or the path the user names). If a previous audit exists, this run is a re-audit: diff against it and lead with what changed.
  2. Establish what you can reach: the live site, a staging URL, robots.txt, sitemap.xml, Search Console / Bing Webmaster / analytics access, a crawl export (Screaming Frog, Sitebulb), server logs, any MCP tools connected (Ahrefs, GSC, analytics, a crawler MCP, or the Prowl MCP for bulk competitive and demand data without a per-vendor seat). Test the access, do not assume it. A connected server is not a working one: API tiers gate endpoints, and tokens carry narrower scopes than the dashboard suggests. Probe the one call each source is there for before you plan around it, and record what came back — "connected but returns Insufficient plan" is a finding the next audit needs.
  3. Pick the scope with the user only if the answer changes the work: whole site, one template/section, one question ("why did traffic drop in May"), or a link-building extraction — targets, keywords and anchors for a contractor. That one is a deliverable rather than a diagnosis: read references/linkbuilding.md when it is the ask. It works with or without Search Console.
  4. Report status in three lines — inputs available, inputs missing, scope — then start. Suggest exactly one next action at the end of every run.

scripts/preflight.py performs the automatable half of step 2 rather than scripts/preflight.py runs the automatable half of this step and reports which independent gate a failure hit — Search Console, the GSC API and PageSpeed all answer 403 for different reasons. Read references/preflight.md for exactly what it probes and what it leaves to you (Bing/Yandex, analytics, server logs, crawl exports and every MCP tool). A green preflight is not a covered step.

# Claude Code plugin: ${CLAUDE_PLUGIN_ROOT} expands inside skill content.
SKILL_DIR="${CLAUDE_PLUGIN_ROOT}/skills/seo-aeo-audit"
# Any other channel: the base directory the harness names when it loads this
# skill — the directory this SKILL.md sits in. Confirm before relying on it:
ls "$SKILL_DIR/scripts/preflight.py"

No such file or directory here is not a missing feature and not a reason to proceed quietly. It means the six instruments are unreachable, so every check they would have made drops to the bottom rung of the evidence ladder — and a finding's rung caps its tier. Say so in the three-line status; an audit that silently becomes a manual one has changed what its conclusions are worth (non-negotiable #6).

python3 "$SKILL_DIR/scripts/preflight.py" --site sc-domain:example.com --origin https://example.com

Access rules: read-only by default. Never submit forms, request indexing, disavow links, or change a live property without explicit approval in this session; those are outward-facing actions.

Step 1 — Baseline before opinions

Record, with dates, so every later claim can be measured against it:

  • organic clicks / impressions / avg position per country and device, 12 months (GSC + Bing), and the drop or plateau window if there is one;
  • indexed vs published URL counts per template (site: is a smell test, GSC Pages report is the number);
  • top-20 revenue or conversion pages and their current positions;
  • AI-surface baseline: run the brand and category prompt set from references/aeo-geo.md against each engine you can reach, and record answers verbatim;
  • which AI crawlers actually fetch the site (server logs; forward-confirmed reverse DNS to filter spoofers) and which AI referrers appear in analytics;
  • the update timeline: date-align every change in the curve against references/algorithm-updates.md before forming any hypothesis about a cause.

When there is no first-party access at all, say so in the three-line status and fall back to what a third-party index can establish: what the domain ranks for today, how large its link profile is against a sized competitive set, and whether its target phrases carry measurable demand (references/prowl-mcp.md). That baseline is capped at STUDY and cannot answer "why is this page not indexed" — but it is enough to tell a cold start from a decline, and those need opposite plans.

If the site claims a traffic drop, first separate reporting failure from ranking failure: a frozen GSC report pins clicks at one date while a real hit keeps producing fresh declining points. Cross-check GA4 sessions, server logs and an independent rank tracker before diagnosing an algorithmic cause.

Step 2 — The ten tracks

Run every track that is in scope. Each has its own reference file with the concrete checks, the 2026-current gotchas, and the evidence to capture.

#TrackAnswersReference
AAccess & indexation economicsCan bots fetch, render and afford this? Where is crawl budget burned?technical-checks.md
BCanonicalization & duplicationWhich URL is canonical, and does the engine agree — hreflang included?technical-checks.md
CArchitecture & link equityDo money pages get authority, depth and crawl frequency?architecture-and-equity.md
DIntent & SERP fitDoes each page match the SERP, and do pages cannibalise?intent-and-content.md + onpage-checks.md
EContent valueA reason to rank that AI cannot replicate?intent-and-content.md + ranking-model.md
FExtractability & AEO/GEOCan an answer engine retrieve, read and quote it?aeo-geo.md
GEntity & brand consensusDo models know the brand, consistently, and name it?entity-and-brand.md
HExperience, conversion & attributionTask completed here or bounced back? Converted, and measured?experience-signals.md + demand-and-conversion.md
IRisk & threatsPenalties, hijacks, injections, takedowns.threats-and-defense.md
JMeasurementWill anyone be able to tell if the plan worked?measurement.md

Discover is not one of the ten tracks, and it is not part of track A. It has its own ranking pass, its own gate (two metatags, without which no card renders at all) and its own freshness curve, so a site where Discover is a material traffic source needs references/discover.md run as an eleventh pass — and a site where it is not can skip it entirely. Check the GSC Discover report before deciding: the reference shipped reachable only from the list at the bottom of this file, which meant an agent working the tracks in order never opened it.

Before any decline diagnosis, run the date-alignment and update-response protocol in references/algorithm-updates.md — "a core update hit us" is not a finding, and half the documented GSC outages coincided with rollouts.

Each track has two halves: the diagnostic work (what is wrong and why) and a mechanical sweep for completeness — technical-checks.md §A3 for tracks A/B and onpage-checks.md for D/E. Run the diagnosis first; the sweep afterwards catches the boring failures, and only sweep items with an observable impact get promoted into the findings table.

Order matters. A track-A blocker (site not fetchable, noindex in the pre-render source, manual action) makes every other finding moot — a manual action is a binary multiplier: nothing you improve counts until it is lifted. Work A → B → C before spending time on F/G.

Evidence ladder — the full routing lives in references/tooling.md; it is ordered by evidence strength, not convenience: server logs → Search Console / Bing / Yandex → full crawl → field performance data → third-party indices → manual fetch and DevTools. Use the highest rung you can actually reach for each check, and state in the report which rung a finding rests on. A public-only audit with no property access is valid work, but its indexation and query findings are inferences, not observations, and get tiered accordingly.

The six bundled scriptspreflight.py, gsc_pull.py, page_audit.py, url_inspection.py, sitemap_audit.py, psi_pull.py — collect the mechanical half of every track. Read references/scripts.md for invocation, flags, quotas and the per-script limits.

Four traps that decide whether a finding is real:

  • page_audit.py's schema inventory reads server-rendered HTML only. Where a CMS injects JSON-LD with JavaScript, an empty inventory is not evidence of absent markup (non-negotiable #8).
  • --format json emits an array, one object per page, even for one URL: index data[0].
  • A response cut off by --max-bytes drops every count-based finding rather than publishing a fragment as a measurement.
  • Every emitted finding carries an evidence tier as well as a severity, and only the tier enters the triage formula. Severity is how loud a finding is; the tier is what backs it. url_inspection.py asks the index rather than inferring from a fetch, which is the only way a finding reaches CONFIRMED — at a quota of 2000/day and 600/minute per property, so sample one URL per template plus the pages a finding is actually about.

Step 3 — Triage

Score every finding, then sort. Do not present an unranked list.

priority = (impact × confidence) / effort
  • impact 1–5: revenue pages blocked = 5; a template-wide leak = 4; a single informational page = 1. Estimate in traffic or revenue terms where the baseline allows it.
  • confidence: CONFIRMED 1.0 · STUDY 0.7 · FIELD 0.4 · HYPOTHESIS 0.2.
  • effort 1–5 in engineering days, counting release process, not just the edit.

Group the output into four buckets, in this order:

  1. Blockers — indexation, penalties, hijacks, revenue pages unreachable.
  2. Leaks — crawl budget, equity, cannibalization, read-budget waste.
  3. Gains — intent fit, information gain, extractability, entity consensus.
  4. Experiments — anything below CONFIRMED that deserves a split test rather than a rollout. Design them per references/experiments.md; never roll a HYPOTHESIS sitewide.

Step 4 — Deliverables

Write these files, seeded from the skeletons in references/deliverable-templates.md. Never overwrite an existing audit or plan silently — write a new dated file, or ask first:

  • docs/seo/audit-<YYYY-MM-DD>.md — findings. Per finding: Issue · Impact · Evidence · Evidence rung · Cause · Fix · Effort · Evidence tier · Verification. The rung is which source the observation came from, and it caps the tier (references/tooling.md).

  • docs/seo/plan-<YYYY-MM-DD>.md — the change plan. Per change: exact target (path/file:line, template name, or URL pattern), the change itself, why (mechanism + evidence tier), the expected effect and by when, how to verify, and how to roll it back.

  • docs/seo/experiments.md — the running experiment record, one row per test, appended rather than dated because it outlives any single audit. Required as soon as the plan has an Experiments bucket, which anything below CONFIRMED puts there.

Executive summary rules: 5 bullets maximum, the top three blockers, the expected size of the prize, and the one thing that must happen first. Write for a technically literate non-specialist; expand jargon on first use.

Step 5 — Verify, then follow up

  • State the verification method per change before it ships (GSC Pages report moves from X to Y; the URL Inspection live test shows the canonical accepted; the log shows Googlebot fetching /_next/static/; the prompt set names the brand in N of 10 answers).
  • Set the check-back window honestly: indexing 2–8 weeks, canonical group splits up to 2 weeks after the fix, core-update effects a quarter, AI training effects months. Say when you cannot promise a date.
  • On re-audit, diff against the previous report and mark each earlier finding fixed / partially fixed / unchanged / regressed, with fresh evidence.

Myth guard — do not put these in a plan

The fourteen most-requested of the 32 refuted claims. Each is refuted by 2026 evidence; the full list, with the counter-evidence and the working alternative for each, is in references/myths.md — read it before answering a tactic question that is not on this short list.

  • llms.txt as a ranking or citation lever · Markdown mirrors of HTML pages as a GEO tactic · "chunk your content for the retriever" · rewriting text specifically "for AI" · schema volume as an AI-citation lever · FAQPage markup for rich results (retired by Google) · AMP for ranking advantage · updating the publish date as a freshness signal · "just add more pages" · disavowing on a third-party toxicity score · buying an "AI visibility" number as a single KPI · self-promotional "best [category]" listicles as an AEO play · scaled AI content as a growth strategy · Disallow-ing tracking-parameter URLs to protect crawl budget (technical-checks.md A2 owns the mechanism).

When the user asks for one of these, say plainly what the evidence shows, offer the nearest thing that does work, and move on.

References

Skills relacionados

steipete/notion

Notion CLI/API for pages, Markdown content, data sources, files, comments, search, Workers, and raw API calls.

community

affaan-m/seo

Audit, plan, and implement SEO improvements across technical SEO, on-page optimization, structured data, Core Web Vitals, and content strategy. Use when the user wants better search visibility, SEO remediation, schema markup, sitemap/robots work, or keyword mapping.

community

affaan-m/brand-voice

Build a source-derived writing style profile from real posts, essays, launch notes, docs, or site copy, then reuse that profile across content, outreach, and social workflows. Use when the user wants voice consistency without generic AI writing tropes.

community

affaan-m/crosspost

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

community

affaan-m/x-api

X/Twitter API integration for posting tweets, threads, reading timelines, search, and analytics. Covers OAuth auth patterns, rate limits, and platform-native content posting. Use when the user wants to interact with X programmatically.

community

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

community