Meta Data Audit
Audit the title tags and meta descriptions of a website and produce an actionable SEO report.
When to use this skill
Use this skill when the user asks to:
- Audit or analyze title tags and meta descriptions on a website
- Find pages with missing, duplicate, or multiple titles or meta descriptions
- Find titles or descriptions that are too long (truncated in SERPs) or too short (wasted snippet space)
- Identify generic, boilerplate, or keyword-stuffed metadata
- Improve click-through rates from search by tightening SERP snippets
Inputs to collect
Before starting, confirm with the user:
- Site URL or local files — a live site root URL (e.g.,
https://example.com), a sitemap URL, a list of URLs, or a local folder of HTML files. - Scope — full site, a specific section (e.g.,
/blog/), or a list of URLs. - Crawl limits — max pages (default 500) for live crawls.
- Brand suffix — the brand pattern appended to titles (e.g.,
| Acme Co), if any, so brand-only and duplicate-after-brand titles can be detected accurately.
Workflow
Step 1: Gather the page set and extract metadata
- If a sitemap is available (
/sitemap.xml), fetch it to get the canonical page list. - Otherwise, crawl from the homepage following only same-host links.
- For local HTML folders, enumerate all
.htmlfiles.
Use scripts/extract_metadata.py to fetch pages and collect every title tag and meta description into a JSON inventory:
python3 scripts/extract_metadata.py https://example.com --max-pages 500 --output metadata_inventory.json
For every page, the inventory records: every <title> and <meta name="description"> value (including duplicates), the first <h1>, canonical URL, meta robots, and og:title/og:description for comparison.
If you've already crawled the site once into a shared page cache (e.g. as part of a full SEO audit), skip the crawl and extract from it instead — same inventory, no extra network:
python3 scripts/fetch_pages.py https://example.com --output page_cache.json # crawl once
python3 scripts/extract_metadata.py --from-cache page_cache.json --output metadata_inventory.json
Step 2: Run the audit checks
Use scripts/audit_metadata.py to run all audit checks against the inventory:
python3 scripts/audit_metadata.py metadata_inventory.json --output audit_report.json
Add --brand-suffix "| Acme Co" to strip the brand pattern before duplicate detection and to flag brand-only titles. Noindexed pages are excluded from duplicate checks by default.
Step 3: Evaluate the audit checks
Evaluate each check defined in references/audit-checks.md. The core checks are:
| Check | Severity |
|---|---|
| Missing or empty title tag | High |
| Missing or empty meta description | High |
| Duplicate titles across pages | High |
| Duplicate meta descriptions across pages | High |
| Multiple title tags or meta descriptions on one page | Medium |
| Title too long (> 60 characters, likely truncated) | Medium |
| Title too short (< 30 characters, wasted space) | Medium |
| Description too long (> 160 characters, likely truncated) | Medium |
| Description too short (< 70 characters, wasted space) | Medium |
| Generic or boilerplate titles ("Home", "Untitled", brand-only) | Medium |
| Description duplicates the title | Low |
| Keyword stuffing in the title | Low |
| Title/H1 mismatch | Informational |
Step 4: Produce the report
Write a report following the structure in references/report-template.md:
- Summary — pages crawled, titles and descriptions found, issue counts by severity
- Length distribution — how titles and descriptions spread across short/good/long bands
- Issues — one section per failing check, listing the page, the current value, and a specific fix
- Prioritized action list — ordered by severity and estimated impact
Step 5: Recommend fixes
For each issue, give a concrete, copy-pasteable recommendation. When drafting replacement titles and descriptions:
- Keep titles near 60 characters and descriptions near 155 characters
- Lead with the page's primary topic; put the brand suffix last
- Base every value on the visible page content; never invent facts, prices, or claims
- Write descriptions that summarize the page and give searchers a reason to click, without keyword stuffing
Example recommendations:
- Add a title to
/services/seo-audit:SEO Audit Services For B2B SaaS | Acme Co - Shorten the 87-character title on
/blog/post-1to lead with the primary topic - Differentiate the duplicate description shared by
/locations/bostonand/locations/cambridgewith location-specific copy
Optional: export the report
As a Word document (.docx)
If the user wants the report as a .docx (for example, to share with stakeholders or attach to a ticket), save the Markdown report to a file and convert it:
python3 scripts/md_to_docx.py report.md --output report.docx
scripts/md_to_docx.py uses only the Python standard library (no pip install) and renders headings, tables, lists, links, bold/italic, and code blocks. Offer this whenever a user asks for a Word doc, a .docx, or a shareable/downloadable report.
As a CSV of findings (.csv)
If the user wants the raw findings as a spreadsheet (for filtering, sorting, or triage in Sheets or Excel), convert the audit's audit_report.json directly:
python3 scripts/findings_to_csv.py audit_report.json --output findings.csv
scripts/findings_to_csv.py is also standard-library only. It writes one row per finding, with check and severity columns prepended and list fields (e.g. the pages sharing a duplicate value) joined with ; . Unlike the .docx, which reformats the written report, the CSV is a direct dump of the structured findings — offer it whenever a user wants the data itself, a spreadsheet, or to slice findings by check or severity.
Resources
scripts/md_to_docx.py— convert the Markdown report into a Word (.docx) document (standard library only)scripts/findings_to_csv.py— flatten the audit findings JSON into a CSV, one row per finding (standard library only)references/audit-checks.md— full definitions, thresholds, and rationale for every audit checkreferences/report-template.md— report output structurescripts/extract_metadata.py— crawl a site and build the title/description inventoryscripts/audit_metadata.py— run audit checks against a metadata inventory JSON file