A Playwright-based QA toolkit for redirect validation, feed testing, and full SEO auditing. The SEO audit runs ~25 checks per URL and outputs an Excel workbook, an HTML report, and a flat issues CSV.
npm install
npx playwright installThe main audit. Point it at any site by dropping a CSV in the input/ folder.
Create or copy a CSV file into the input/ folder. The file must have a url column as the header:
url
https://www.yoursite.com/
https://www.yoursite.com/about/
https://www.yoursite.com/contact/
- One URL per row
- Must be absolute URLs starting with
https:// - Lines starting with
#are ignored (use for comments) - A second
namecolumn is optional — shown as a label in the report
Example — using a dated folder for traceability:
input/
2026-05-27/
final_live_urls.csv ← source file
urls.csv ← what the test actually reads
Copy your source file to urls.csv before running:
cp input/2026-05-27/final_live_urls.csv input/urls.csvnpm run seo:csvThis runs the Playwright test, then automatically generates all three reports. Typical time: ~7 minutes for 950 URLs.
To adjust concurrency (default 8 — lower if the server rate-limits):
SEO_CONCURRENCY=4 npm run seo:csv # slower, gentler on the server
SEO_CONCURRENCY=12 npm run seo:csv # faster, higher server loadAll reports are written to test-results/:
| File | Description |
|---|---|
seo-audit-report.xlsx |
Main deliverable — 6-sheet Excel workbook |
seo-csv-report.html |
Self-contained HTML report, open in any browser |
seo-csv-issues.csv |
Flat CSV of all fails and warnings for spreadsheet use |
| Sheet | Contents |
|---|---|
| Executive Summary | Stats overview and category breakdown |
| Fails | Every hard-fail check with URL, message and value |
| Warnings | Every warning-level check |
| Page Summary | Per-URL pass / fail / warn counts with status |
| Internal Links | Broken (404/5xx) and redirecting internal links per page |
| Action List | Prioritised fix list auto-generated from audit findings |
| Category | Checks |
|---|---|
| security | HTTPS |
| http | Status code (200 expected) |
| redirects | Whether the URL itself redirects (sitemap URLs should be canonical) |
| performance | Response time ≤ 3000ms |
| title | Presence, length 10–70 chars |
| description | Presence, length 50–160 chars |
| canonical | Presence, single tag, absolute URL, self-referencing |
| robots | No noindex in meta robots or X-Robots-Tag header |
| headings | Exactly 1 × H1, at least 1 × H2 |
| open-graph | og:title, og:description, og:url, og:type present; og:image (warn) |
| structured-data | JSON-LD block present (warn) |
| technical | Viewport meta, charset meta, lang attribute on <html> |
| accessibility | Images with missing alt attributes (warn) |
| international | Hreflang tags (informational if present) |
| links | Internal links checked for broken (404/5xx) and redirecting (3xx) |
If you already have a test-results/seo-csv-report.json from a previous run:
npm run report:seo-csv # regenerate HTML + issues CSV
npm run report:seo-excel # regenerate Excel workbooknpm run test:redirects # validate redirect rules from data/redirects.csv
npm run test:seo # single-URL SEO checks (non-CSV mode)
npm run test:feeds # live vs staging feed comparison
npm run test:report # open the Playwright HTML report in browser403 / blocked responses The site's CDN (e.g. Cloudflare) may be rate-limiting or bot-blocking the test runner. Options:
- Lower concurrency:
SEO_CONCURRENCY=4 - Ask the site's developer to whitelist the test machine's public IP at the CDN level
- Run from a different network
Large sites taking too long
Increase concurrency carefully: SEO_CONCURRENCY=12. Each page also checks up to 5 internal links sequentially, so total time scales with unique uncached links found.
Reports not generating
Run the audit first — the report scripts require test-results/seo-csv-report.json to exist:
npm run test:seo-csv # generate the JSON
npm run report:seo-excel # then generate Excel

