Skip to content
Back to skills

Seo

ASecurity

Technical SEO, content quality/E-E-A-T, schema markup, sitemap, image SEO, and AI-search (GEO/AEO) analysis for any URL or page content. Use when the user says "SEO", "SEO audit", "technical SEO", "Core Web Vitals", "schema markup", "structured data", "JSON-LD", "sitemap", "robots.txt", "E-E-A-T", "content quality", "alt text", "image SEO", "AI Overviews", "GEO", "AEO", "llms.txt", "AI citations", or asks to audit/optimize a page or site for search engines.

  • 6 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 27, 2026
ai-agentsjavascriptpythonrustgojavabashdebuggingapisecurityperformance

Works with

  • claude web
  • cli
  • api

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned September 27, 2026

npx -y skills add xrhstosmour/macsify --skill seo --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Seo?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Seo
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/xrhstosmour-seo/badge)](https://www.skillsdirectory.com/skills/xrhstosmour-seo)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: seo
description: >
  Technical SEO, content quality/E-E-A-T, schema markup, sitemap, image SEO,
  and AI-search (GEO/AEO) analysis for any URL or page content. Use when the
  user says "SEO", "SEO audit", "technical SEO", "Core Web Vitals", "schema
  markup", "structured data", "JSON-LD", "sitemap", "robots.txt", "E-E-A-T",
  "content quality", "alt text", "image SEO", "AI Overviews", "GEO", "AEO",
  "llms.txt", "AI citations", or asks to audit/optimize a page or site for
  search engines.
---

# SEO Analysis

Search behavior changes faster than this file does, and nothing re-checks it. Treat
the thresholds, crawler tokens, schema type status, and platform claims below as
unverified: confirm anything load-bearing against the live source before reporting
it as current.

## When to use

- The user gives a URL and asks for an SEO audit, health check, or "what's
  wrong with this page for SEO".
- The user asks about a specific slice: technical SEO, schema/structured
  data, content quality/E-E-A-T, sitemap, image optimization, or AI-search
  visibility (GEO/AEO/AI Overviews).
- The user pastes HTML, a sitemap, or robots.txt and wants it checked.

Not for keyword research, paid ad campaigns, or backlink acquisition — this
skill covers on-site and technical factors only (see "Backlinks" for why
off-site link data is out of scope).

## Fetching & tooling

No dedicated runtime is installed for this skill — use what's already
available:

- **WebFetch** for a first read of a page: rendered-to-markdown content,
  general structure, obvious issues.
- **`curl`** (via Bash) when byte-exact data matters and WebFetch's
  model-summarized output would lose it: response headers (`curl -sI`),
  `robots.txt`, `sitemap.xml`, raw HTML for schema extraction.
- **`scripts/check_schema.py`** and **`scripts/check_sitemap.py`** (this
  skill's directory) for structured validation that plain-text inspection
  gets wrong in practice (JSON-LD parsing, sitemap XML caps). Both read
  already-fetched content from a file or stdin and make no network calls of
  their own:

  ```bash
  curl -s "$URL" -o /tmp/page.html
  python3 "$SKILL_DIR/scripts/check_schema.py" /tmp/page.html

  curl -s "$URL/sitemap.xml" -o /tmp/sitemap.xml
  python3 "$SKILL_DIR/scripts/check_sitemap.py" /tmp/sitemap.xml
  ```

  (Replace `$SKILL_DIR` with this skill's actual directory path.)

- **Core Web Vitals**: call the public PageSpeed Insights API directly —
  works without a key at low volume, or with a key via the `GOOGLE_API_KEY`
  env var if the user has one:

  ```bash
  curl -s "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=$URL&category=performance${GOOGLE_API_KEY:+&key=$GOOGLE_API_KEY}"
  ```

  If this fails or is rate-limited, say so plainly rather than guessing at
  scores — see the error-handling table.

**No headless browser is available.** For JavaScript-heavy/SPA pages, fetched
HTML may not reflect what a user actually sees. Heuristic: if `<body>` is
mostly empty apart from a root `<div>` and heavy `<script>` bundles, flag the
page as likely client-side rendered and note that findings on visible content
are unreliable until the user provides rendered HTML or a screenshot.

## Technical SEO

Check in this order — an upstream defect here invalidates content/schema work
downstream:

1. **Crawlability**: `robots.txt` exists and isn't blocking important paths;
   XML sitemap declared and reachable; no accidental `noindex`; important
   pages reachable within ~3 clicks of the homepage.
2. **Indexability**: canonical tags are self-referencing and don't conflict
   with `noindex`; watch for near-duplicate/parameter-URL content and
   `www` vs non-`www` inconsistency.
3. **Security**: HTTPS enforced with a valid cert, no mixed content; security
   headers present (`Content-Security-Policy`, `Strict-Transport-Security`,
   `X-Content-Type-Options`, `Referrer-Policy`). Treat these as good hygiene,
   not high-impact ranking signals — HTTPS itself affects well under 1% of
   queries as a direct signal.
4. **URL structure**: descriptive, hyphenated, no unnecessary query params;
   redirect chains no more than one hop; flag URLs over ~100 characters.
5. **Mobile / page experience**: viewport meta tag, responsive layout, touch
   targets ≥48px, no horizontal scroll. Mobile-first indexing is the default
   — check that mobile content, meta tags, and structured data match desktop
   (parity gaps are the real risk, not simple exclusion from the index).
6. **Core Web Vitals** — current thresholds:

   | Metric | Good | Needs Improvement | Poor |
   |---|---|---|---|
   | LCP (Largest Contentful Paint) | ≤2.5s | 2.5–4.0s | >4.0s |
   | INP (Interaction to Next Paint) | ≤200ms | 200–500ms | >500ms |
   | CLS (Cumulative Layout Shift) | ≤0.1 | 0.1–0.25 | >0.25 |

   INP replaced FID in 2024 — never reference FID. Evaluation uses the 75th
   percentile of real-user (CrUX field) data; lab tools like Lighthouse are
   useful for debugging *why*, not for the score Google actually uses.
7. **Structured data**: see the Schema section below.
8. **JavaScript rendering**: check whether critical content, canonical tags,
   `noindex`, and structured data are present in the *raw* server-rendered
   HTML, not only injected by JS. Google may use either version if they
   conflict, and does not render JS at all on non-200 responses — so
   time-sensitive markup (Product/Offer especially) belongs in the initial
   HTML.
9. **IndexNow**: note whether the site pings IndexNow (Bing/Yandex support
   it; Google doesn't) — a cheap win for faster non-Google indexing.

**AI crawlers vs. search crawlers in `robots.txt`** — these are separate
concerns and get conflated constantly:

| Token | Owner | Purpose | Obeys robots.txt |
|---|---|---|---|
| `Googlebot` | Google | Search indexing | yes |
| `Google-Extended` | Google | Gemini/AI training (not search) | yes |
| `GPTBot` | OpenAI | Model training | yes |
| `ChatGPT-User` | OpenAI | Live browsing on a user's behalf | no (user-triggered) |
| `ClaudeBot` | Anthropic | Model training / Claude web features | yes |
| `PerplexityBot` | Perplexity | Search index + training | yes |
| `CCBot` | Common Crawl | Open dataset | yes |

Blocking `Google-Extended` stops Gemini training use but has **no effect** on
Search indexing or AI Overviews (those run on `Googlebot`). User-triggered
fetchers (`ChatGPT-User`, and similarly Google's agentic-browsing fetchers)
ignore `robots.txt` by design — they can only be gated server-side.

## Content quality & E-E-A-T

Before scoring, run Google's own **Who / How / Why** test from its
helpful-content guidance:

| Question | Look for |
|---|---|
| **Who** created it? | Visible byline, author bio, credentials — non-negotiable for YMYL (health, finance, legal, civic) topics. |
| **How** was it made? | Original research, first-hand evidence, disclosed process — especially where AI assistance is plausible. |
| **Why** does it exist? | To help the reader, not to farm search clicks or hit a word-count target. |

If all three come back weak, flag the page as at risk under Google's
helpfulness/core-ranking signals regardless of any other score.

**E-E-A-T** (Experience, Expertise, Authoritativeness, Trustworthiness).
Google states only that Trust is "the most important member of the family"
and publishes no numeric weights — use this internal scoring split rather
than an even 25/25/25/25, since an even split contradicts that stated
hierarchy:

| Pillar | Weight | Signals |
|---|---|---|
| Experience | 20 | First-hand detail, original photos/data, specific anecdotes that couldn't be fabricated. |
| Expertise | 25 | Author credentials, technical accuracy, sourced claims. |
| Authoritativeness | 25 | External citations, industry recognition, consistent publication history. |
| Trustworthiness | 30 | Contact info, HTTPS, privacy policy, transparent authorship, no deceptive patterns. |

AI-generated content is not penalized for being AI-generated — it's
penalized for being generic, unsourced, or repetitive across pages. Judge on
those markers, not on authorship method.

**Quality gates** (treat word counts as topical-coverage floors, not ranking
targets — Google has confirmed word count itself isn't a ranking factor):

| Element | Guidance |
|---|---|
| Title tag | 30–60 characters, primary keyword near the front, unique per page |
| Meta description | 120–160 characters, includes a reason to click |
| Homepage | ~500+ words covering the value proposition |
| Service/feature page | ~800+ words |
| Blog post | ~1,500+ words for genuinely in-depth topics |
| Image alt text | 10–125 characters, describes the image, never "image.jpg" or keyword-stuffed |
| Internal links | 3–10 per page depending on length, descriptive anchor text, no orphan pages |
| Freshness | Publish date visible; flag fast-moving topics untouched for 12+ months |

## Schema / structured data

1. Detect existing markup: JSON-LD (`<script type="application/ld+json">`)
   preferred, then Microdata, then RDFa. Always recommend migrating to
   JSON-LD if another format is found.
2. Validate: `@context` is `https://schema.org`, `@type` is a real
   non-deprecated type, required properties present, URLs absolute, dates
   ISO-8601, no placeholder text left in. Use `scripts/check_schema.py` on
   the raw HTML for this rather than eyeballing it.
3. Check against current type status:

   | Status | Types |
   |---|---|
   | Active — recommend freely | Organization, LocalBusiness, Product, Offer, Service, Article/BlogPosting/NewsArticle, Review, AggregateRating, BreadcrumbList, WebSite, WebPage, Person, VideoObject, ImageObject, Event, JobPosting, Course, QAPage |
   | No Google rich result, not harmful | FAQPage — Google restricted FAQ rich results to a small set of authoritative sites in August 2023; keep existing markup as info-level, don't add new FAQPage expecting a SERP benefit. For genuine user Q&A, use QAPage instead. |
   | Deprecated — never recommend | HowTo, SpecialAnnouncement, ClaimReview, VehicleListing |

4. Generate JSON-LD only with truthful data; mark anything the user must fill
   in with an obvious placeholder like `"[Company Name]"`.

Minimal templates to adapt:

```json
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "[Company Name]",
  "url": "[Website URL]",
  "logo": "[Logo URL]",
  "sameAs": ["[Social profile URLs]"]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "[Title]",
  "author": { "@type": "Person", "name": "[Author Name]" },
  "datePublished": "[YYYY-MM-DD]",
  "dateModified": "[YYYY-MM-DD]",
  "image": "[Image URL]"
}
```

## Sitemap

1. Discover: check `robots.txt` for a `Sitemap:` line first, then fall back
   to common paths (`/sitemap.xml`, `/sitemap_index.xml`) if the declared one
   is missing or stale. Don't report "no sitemap" until both have failed.
2. Fetch it and run `scripts/check_sitemap.py` against the saved file to
   validate structure rather than eyeballing raw XML.
3. Rules the script and your review should both apply:
   - Hard cap: 50,000 URLs **or** 50MB uncompressed per file, whichever hits
     first — split with a sitemap index above that.
   - News sitemaps: 1,000 entries max, articles from the last 2 days only.
   - `<lastmod>` must be valid ISO-8601 and reflect a real content change —
     Google ignores it if values look uniform or newer than the actual
     content.
   - `<priority>` and `<changefreq>` are both ignored by Google — flag as
     informational only, not worth fixing urgently.
   - Every URL should be canonical, indexable, HTTPS, and return 200 — no
     redirected or noindexed URLs belong in the sitemap.

## Images

| Check | Guidance |
|---|---|
| Alt text | Present on every non-decorative `<img>`, 10–125 chars, describes the image |
| File size | Thumbnails <50KB, content images <100KB, hero/banner <200KB (targets; flag at 2-3x these as critical) |
| Format | WebP/AVIF preferred, JPEG fallback via `<picture>`, SVG for icons/logos |
| Responsive | `srcset`/`sizes` present for images shown at varying widths |
| Lazy loading | `loading="lazy"` on below-fold images only — never on the LCP/hero image, it delays paint |

## GEO / AI-search optimization (AI Overviews, AI Mode, ChatGPT, Perplexity)

Google's own position: optimizing for generative AI search **is still SEO**,
not a separate discipline — AEO/GEO are rebranded labels for the same
fundamentals (quotability, structure, freshness, entity clarity) applied to
AI-search surfaces. Frame findings that way rather than as a new toolkit.

- **Citability**: aim for self-contained 100–170 word answer blocks that
  state a fact or definition up front ("X is...") rather than burying the
  answer at the end of a paragraph. Front-load the most citable content —
  a large share of AI citations come from early in the page.
- **Structure**: clean H1→H2→H3 hierarchy, question-phrased headings, short
  paragraphs, tables for comparative data. Structure is a bigger lever here
  than for classic SEO because extraction (not just ranking) depends on it.
- **Authority/brand**: byline with credentials, visible publish/update
  dates, citations to primary sources. Recency matters more here than in
  classic search — content untouched for 6+ months loses citation
  eligibility faster than it loses rankings.
- **AI crawler access**: see the robots.txt table in Technical SEO. Decide
  deliberately whether to allow training crawlers (`GPTBot`, `Google-
  Extended`) vs. search/citation crawlers (`ChatGPT-User`, `PerplexityBot`)
  — blocking one doesn't block the other.
- **`llms.txt`**: be honest about this. Google has stated explicitly that
  Google Search, including its AI features, ignores `llms.txt` entirely — it
  neither helps nor hurts Google visibility. It's harmless to add for other
  AI crawlers that do read it, but never sell it as a Google ranking or
  citation lever.
- **Server-side rendering**: AI crawlers generally don't execute JavaScript.
  Critical content and schema need to be in the raw HTML, same requirement
  as classic technical SEO above.

## Local SEO basics

For local/location-based businesses, without any Maps/GBP API access:

- **Google Business Profile** signals dominate local-pack ranking — primary
  category accuracy, keyword-appropriate business title, verified status,
  and NAP (Name/Address/Phone) consistency across the web are the highest-
  leverage items an audit can flag from the outside.
- **Reviews**: recency and velocity matter more than raw volume — a listing
  with no new reviews in three weeks tends to lose local-pack visibility
  even with a strong historical review count.
- **On-page**: dedicated, unique location pages (not city-name-swapped
  templates) with genuine local information — see the doorway-page risk
  note under Content quality.

This is deliberately shallow — real local SEO work (GBP audits, citation
building, review management) needs GBP dashboard or paid-API access this
skill doesn't have.

## Backlinks

Be upfront about this limitation rather than faking an analysis: there is no
reliable, free, no-signup source of backlink data. Public options either
need a paid API key (Ahrefs, SEMrush, DataForSEO — all out of scope here) or
a free-tier signup (Moz, Bing Webmaster Tools) that this skill doesn't
integrate with. If the user has exported backlink data from a tool they
already use (Search Console, Ahrefs, Moz), analyze that directly instead —
don't attempt to reconstruct a backlink profile from scratch.

## Audit synthesis

For a full audit (multiple sections above), don't just concatenate findings —
walk through four phases before writing the action plan:

1. **Observe**: collect findings per section above without prioritizing yet.
2. **Analyze**: find the highest-leverage constraint — often one technical
   defect (non-indexable, broken canonical, missing HTTPS) that gates
   everything downstream. That goes first regardless of how "interesting"
   other findings are. Connect findings across sections that reinforce each
   other (e.g. a missing Product schema plus thin product-page content are
   one recommendation, not two).
3. **Validate**: pressure-test each recommendation against user experience,
   the site's existing voice, and whether the team can realistically ship it
   — a recommendation with no realistic execution path isn't done yet.
4. **Act**: produce the artifact (report, generated schema, action plan) —
   don't stop at analysis. Note what a follow-up check should look for.

## Output format

```
### SEO Health: <pass | warn | fail>

The overall verdict is the worst category status below, nothing more. Don't compute
a numeric score, there is no defined formula for one and an invented number reads as
measured when it isn't.

| Category | Status | Notes |
|---|---|---|
| Technical | pass/warn/fail | ... |
| Content / E-E-A-T | pass/warn/fail | ... |
| Schema | pass/warn/fail | ... |
| Sitemap | pass/warn/fail | ... |
| Images | pass/warn/fail | ... |
| AI-search (GEO) | pass/warn/fail | ... |

### Critical (fix immediately)
### High (fix within a week)
### Medium (fix within a month)
### Low / backlog
```

For a narrow question (just schema, just sitemap, etc.), skip the table and answer
directly — don't force an overall verdict onto a single-category ask.

## Error handling

| Scenario | Action |
|---|---|
| URL unreachable | Report the exact error/status code. Don't guess at content. |
| `robots.txt`/sitemap missing | Try common fallback paths before reporting "not found". |
| Paywalled/gated content (401/402/403, login wall) | Analyze only what's publicly visible (meta tags, headers); say what's out of reach. |
| CWV/PageSpeed data unavailable | Say so plainly (common for low-traffic sites); Lighthouse lab data is a fallback proxy, not a substitute, for the field-data score. |
| Likely JS-rendered/SPA content | Flag the rendering limitation per the heuristic above rather than reporting on content that may not reflect what users see. |
| No backlink data source available | Say so directly; offer to analyze data the user provides instead. |

Files in this skill

  • SKILL.md17.9 KB
  • scripts/check_schema.py5.1 KB
  • scripts/check_sitemap.py4.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.