Labsco
seranking logo

seo-hreflang

โ˜… 84

by seranking ยท part of seranking/seo-skills

> Example output: [examples/seo-hreflang-airbnb-com-20260514/HREFLANG-REPORT.md](../../examples/seo-hreflang-airbnb-com-20260514/HREFLANG-REPORT.md) # Hreflang Audit Adapted from `AgriciDaniel/claude-seo`'s `seo-hreflang` skill (MIT). Concept and validation rules originate there; this implementation is rebuilt against our backend (SE Ranking MCP + Firecrawl + WebFetch + Google APIs via `seo-goog

FreeQuick setup
๐Ÿงฉ One of 7 skills in the seranking/seo-skills package โ€” works on its own, and pairs well with its siblings.

This is the playbook your agent receives when the skill activates โ€” you don't need to read it to use the skill, but it's here to audit before installing.

Example output: examples/seo-hreflang-airbnb-com-20260514/HREFLANG-REPORT.md

Hreflang Audit

Adapted from AgriciDaniel/claude-seo's seo-hreflang skill (MIT). Concept and validation rules originate there; this implementation is rebuilt against our backend (SE Ranking MCP + Firecrawl + WebFetch + Google APIs via seo-google).

Validate hreflang implementations on a multi-language or multi-region site. Surface SE Ranking audit-level hreflang issues, parse a sample of pages for the actual <link rel="alternate" hreflang="โ€ฆ"> tags they emit, cross-check the sitemap, and produce one of three verdicts โ€” PASS, NEEDS-FIX, or BROKEN โ€” with a top-fixes table anchored in objective signals.

Process

  1. Validate target & preflight. See skills/seo-firecrawl/references/preflight.md for the canonical 3-stage preflight (credit balance, Firecrawl availability, Google APIs). Skill-specific notes:

    • Normalise domain (strip protocol, trailing slash) before continuing.
    • Estimated SE Ranking cost for this skill: ~5โ€“10 SE Ranking credits for re-using an existing audit (up to ~3 Firecrawl credits for the per-URL inventory).
    • Firecrawl: optional with WebFetch fallback, ~6 Firecrawl credits if available (hard cap). When available, step 4 (per-URL hreflang inventory) runs on homepage + 5 representative pages with formats: ["rawHtml"]. Without Firecrawl, step 4 falls back to WebFetch โ€” coverage is degraded because WebFetch returns markdown only and silently strips <link rel="alternate"> tags from <head>. Pass --no-firecrawl to force WebFetch even when Firecrawl is available.
    • Google APIs: tier 1 (GSC) unlocks step 6 (GSC verification of hreflang-targeted alternates). See skills/seo-google/references/cross-skill-integration.md for the full enrichment contract.
  2. Find or refresh the audit DATA_listAudits โ†’ DATA_getAuditStatus

    • List audits for the domain. If a recent audit exists (<30 days), use it.
    • If older than 30 days, run DATA_recheckAudit and wait for done.
    • If none exists, ask the user before creating one with DATA_createStandardAudit โ€” it consumes credits.
  3. Pull SE Ranking's hreflang findings DATA_getAuditReport + DATA_getAuditPagesByIssue

    • SE Ranking's audit catches hreflang errors directly โ€” surface them first as ground truth.
    • From DATA_getAuditReport, extract every issue with code or category matching hreflang (typical codes: hreflang_no_return_tag, hreflang_invalid_lang_code, hreflang_conflict, hreflang_missing_x_default, hreflang_canonical_mismatch, hreflang_no_self_reference).
    • For each significant hreflang issue (count โ‰ฅ 1), call DATA_getAuditPagesByIssue to enumerate the affected URLs.
    • Persist to 01-audit-hreflang-issues.md and feed into hreflang-issues.csv.
  4. Per-URL hreflang tag inventory mcp__firecrawl-mcp__firecrawl_scrape (preferred) / WebFetch (fallback)

    • Sample selection: homepage + up to 5 representative pages from DATA_getDomainPages (sort by traffic descending; bias toward pages on different language paths if the URL structure exposes them โ€” /en/, /fr/, /de/, etc.).
    • Firecrawl path (1 credit per URL, ~6 total): call firecrawl_scrape(url=..., formats=["rawHtml"]). Pin rawHtml โ€” the default html post-processing strips <link rel="alternate"> on many sites. Parse every <link rel="alternate" hreflang="โ€ฆ" href="โ€ฆ"> from the <head>. Capture: source URL, hreflang attribute, href, and whether it's self-referencing.
    • WebFetch fallback (no Firecrawl): try fetching each URL and extracting hreflang from the markdown response. WebFetch frequently returns markdown that has stripped <head> link tags, so this path will under-report. Note in HREFLANG-REPORT.md: Per-URL inventory: degraded coverage โ€” Firecrawl not installed; some hreflang tags may be missed.
    • Apply validation rules (see references/validation-rules.md for the full list):
      • Self-referencing tag: the page's own URL must appear in its own hreflang set.
      • Return tags: every alternate link must reciprocate. If page A lists B as fr, page B must list A as en (or whichever).
      • x-default: at least one alternate per set must use hreflang="x-default".
      • Language-region code validation: every value must be a valid ISO 639-1 language (optionally followed by - and an ISO 3166-1 Alpha-2 region). Common errors caught: eng (use en), jp (use ja), en-uk (use en-GB), es-LA (no such ISO region).
      • Conflict detection: the same hreflang value (e.g. de-DE) appearing on multiple distinct URLs is a conflict โ€” Google ignores conflicting sets.
      • Canonical alignment: if the page has <link rel="canonical">, it must match the page's own URL (or its self-referencing hreflang URL). Hreflang on a non-canonical page is silently ignored by Google.
      • Protocol consistency: all URLs in a set must share the same scheme (HTTPS preferred).
    • Persist to 02-per-url-hreflang.md and append findings to hreflang-issues.csv.
  5. Sitemap-level hreflang (defer to seo-sitemap where appropriate)

    • If the user's domain uses sitemap-based hreflang (<xhtml:link rel="alternate" โ€ฆ> inside the sitemap), this skill checks structure and consistency only. Full sitemap analysis (orphans, missing pages, broken entries) is seo-sitemap's job โ€” recommend it explicitly if a sitemap-vs-audit diff is in scope.
    • Fetch the sitemap. Try https://{domain}/sitemap.xml; if 404, fetch /robots.txt and find Sitemap: directives. For sitemap-of-sitemaps, recursively fetch each child.
    • Validate hreflang within the sitemap:
      • Does the sitemap use the xmlns:xhtml="http://www.w3.org/1999/xhtml" namespace? Required for hreflang in sitemaps.
      • Does each <url> entry that has hreflang alternates include itself in the alternate set (self-reference)?
      • Does every alternate listed in one <url> entry reciprocate as its own <url> entry with the same alternate set (return tags)?
      • Are language-region codes valid (apply same rules as step 4)?
    • Cross-check against per-URL inventory (step 4): if a sample URL's HTML lists 4 hreflang alternates but the sitemap entry for that URL lists 6, that mismatch is a conflict โ€” Google may pick either, and inconsistency degrades the signal.
    • Persist to 03-sitemap-hreflang.md and append findings to hreflang-issues.csv.
  6. GSC verification of hreflang-targeted alternates (only if google-api.json is present, tier โ‰ฅ 1)

    • For each unique domain that appears as an href target in the hreflang sets (e.g. example.com, example.de, example.fr), confirm GSC verification: python3 scripts/gsc_query.py --property "{property}" --json (a status-only check; just confirm the property responds without PROPERTY_NOT_VERIFIED).
    • Why this matters: Google explicitly recommends verifying every domain that participates in a cross-domain hreflang setup. If example.de is listed as an alternate but isn't verified in this account, the hreflang signal is weakened and you can't see how Google interprets it.
    • Surface in HREFLANG-REPORT.md as a section "## GSC verification of hreflang targets" with one row per target domain: verified / not verified / not configured.
    • If property not verified for a target domain: list it as a fix at Medium severity ("Verify {domain} in Google Search Console โ€” required for cross-domain hreflang trust").
    • See skills/seo-google/references/cross-skill-integration.md ยง "Trigger pattern" for the failure-mode contract.
  7. Synthesise verdict

    • Apply the verdict heuristic (see Tips) to produce PASS, NEEDS-FIX, or BROKEN.
    • Sort hreflang-issues.csv by severity descending, then count descending.
    • Write HREFLANG-REPORT.md with the top-fixes table (top 10) and the verdict.

Output format

Create a folder seo-hreflang-{target-slug}-{YYYYMMDD}/ with:

seo-hreflang-{target-slug}-{YYYYMMDD}/
โ”œโ”€โ”€ 01-audit-hreflang-issues.md   (SE Ranking audit findings filtered to hreflang)
โ”œโ”€โ”€ 02-per-url-hreflang.md         (per-URL <link rel="alternate"> inventory + validation findings)
โ”œโ”€โ”€ 03-sitemap-hreflang.md         (sitemap-level hreflang validation; defer details to seo-sitemap)
โ”œโ”€โ”€ evidence/
โ”‚   โ”œโ”€โ”€ homepage-rawhtml.html      (raw HTML from Firecrawl, for the homepage sample)
โ”‚   โ”œโ”€โ”€ sample-{n}-rawhtml.html    (raw HTML for each sampled URL)
โ”‚   โ””โ”€โ”€ sitemap.xml                (raw fetched sitemap)
โ”œโ”€โ”€ hreflang-issues.csv            (load-bearing: URL, issue code, severity, fix)
โ””โ”€โ”€ HREFLANG-REPORT.md             (PRIMARY: verdict + top fixes table)

HREFLANG-REPORT.md follows this shape:

# Hreflang Audit: {domain}

> Audit date {YYYY-MM-DD} ยท Sample size: {n} URLs ยท Languages detected: {comma-separated list}

## Verdict: {PASS | NEEDS-FIX | BROKEN}

Reasoning: {1โ€“2 sentences anchored in concrete numbers from the data}.

## Summary

| Source | Findings | Severity breakdown |
|---|---|---|
| SE Ranking audit | {n} | Critical: {n} ยท High: {n} ยท Medium: {n} ยท Low: {n} |
| Per-URL HTML inventory | {n} | โ€ฆ |
| Sitemap | {n} | โ€ฆ |

## Top fixes (impact-ranked)

| # | URL | Issue | Severity | Fix |
|---|---|---|---|---|
| 1 | {URL} | {issue code} | {severity} | {one-line fix} |
| 2 | โ€ฆ | โ€ฆ | โ€ฆ | โ€ฆ |
| ... up to 10 |

## Languages detected

| Language | URL count | Self-ref OK | Return tags OK | x-default OK |
|---|---|---|---|---|
| en-US | {n} | โœ“ / โœ— {count} | โœ“ / โœ— | โœ“ / โœ— |
| de-DE | {n} | โ€ฆ | โ€ฆ | โ€ฆ |
| ... |

## Per-URL inventory ({n} URLs sampled)

| URL | Alternates | Self-ref | x-default | Notable issues |
|---|---|---|---|---|
| {URL} | {n} | โœ“/โœ— | โœ“/โœ— | {short text} |
| ... |

## Sitemap-level hreflang

- xhtml namespace declared: {โœ“/โœ—}
- URLs with hreflang alternates: {n}
- Self-reference within sitemap: {โœ“ all / โœ— {count} missing}
- Return tags within sitemap: {โœ“ all / โœ— {count} missing}
- Per-URL HTML vs sitemap consistency: {โœ“ all match / โœ— {count} mismatched}
- Full sitemap-vs-audit analysis: see `seo-sitemap` (orphans, broken entries, lastmod).

## GSC verification of hreflang targets

| Domain | Verified | Notes |
|---|---|---|
| {domain1} | โœ“ / โœ— | {note if unverified} |
| ... |

(Or: `GSC verification: not configured (run bash extensions/google/install.sh)`.)

## Coverage notes

- Per-URL inventory tool: {Firecrawl rawHtml | WebFetch fallback (degraded โ€” some hreflang tags may be missed)}.
- Pages sampled: homepage + {n} representative pages (selection: top traffic from `DATA_getDomainPages`).

## Apply

- Walk `hreflang-issues.csv` row-by-row; each row is one specific change (URL + issue + fix).
- After applying changes, re-run `seo-technical-audit` to refresh SE Ranking's findings, then re-run this skill to verify.

hreflang-issues.csv columns: url,issue_code,severity,fix,source where source is one of audit | html | sitemap | gsc.

Tips

  • Respect SE Ranking Data API rate limit: 10 req/sec.
  • Reuse existing audits when possible โ€” creating a new audit is by far the most expensive operation in this skill.
  • Verdict heuristic:
    • PASS: zero Critical findings; โ‰ค 2 High findings; sample URLs all have self-reference, x-default, and reciprocal return tags; all language-region codes valid; canonical aligns with self-ref hreflang.
    • NEEDS-FIX: any High finding; or > 5 Medium findings; or any one of (missing x-default, missing return tags on > 25% of sampled pages, language-region code error, sitemap-vs-HTML mismatch).
    • BROKEN: any Critical finding; or hreflang attempted but no self-reference on the homepage; or canonical pointing elsewhere on a page that nonetheless emits hreflang (entire set is ignored by Google); or > 50% of sampled URLs missing return tags.
  • Anchor every claim in HREFLANG-REPORT.md to a row in hreflang-issues.csv. If a stakeholder questions the verdict, walk them through the CSV.
  • For sites with > 50 language variants per page, the per-URL HTML implementation bloats the <head> โ€” recommend the sitemap-based implementation instead. Don't generate code; the deliverable is diagnostic, not code-gen.
  • The skill does not assess cultural adaptation, content parity, or locale formatting. Those are translation/QA concerns; they're orthogonal to whether hreflang itself is technically correct. If the user wants those, point them at the translation team โ€” this skill answers "is the technical hreflang signal working?", not "is the localised content good?".
  • For cross-domain hreflang (e.g. example.com โ†” example.de), step 6's GSC check is the highest-value enrichment โ€” verifying both domains is Google's explicit recommendation.
  • Common false-positive guard: if a sampled page legitimately has no internationalization (e.g. a single-region site), zero hreflang tags is correct, not an issue. The skill detects this by checking whether any sampled page emits hreflang; if none do, the verdict is PASS with note "No hreflang implementation detected โ€” single-language site."
  • Pair with seo-sitemap for the sitemap-vs-audit diff; pair with seo-technical-audit for full technical health. This skill is narrow: hreflang correctness only.
  • See references/validation-rules.md for the full per-issue rule table (severity, detection logic, suggested fix).