Google retired the Structured Data Testing Tool. X killed its Card Validator. Facebook's debugger is behind a login. So in 2026 there is no fast way to catch a busted <title> or a missing og:image before it ships to production. You find out when the page is live and the LinkedIn share renders as a grey box.
I kept shipping that exact bug, so I put the check in CI. It's a zero-dependency GitHub Action.
What it does
It lints the <head> of a page — a local HTML file or a live URL — and exits non-zero when the SEO and social-share tags are broken or missing, so the build goes red.
- uses: atlashey-collab/seo-meta-action@v1
with:
target: index.html # a file path OR a https:// URL
fail-on-warning: false # set true to also fail on warnings
It checks the tags that actually move rankings and share previews:
-
<title>— present, non-empty, ~30-60 chars, exactly one - meta description — present, ~120-160 chars, no duplicates
- exactly one
<h1> - absolute
<link rel="canonical"> - viewport, charset,
<html lang> - accidental
robots: noindex(the silent traffic killer) - Open Graph:
og:title,og:description,og:image,og:url,og:type twitter:card
Errors fail the job by default. Warnings only fail it when you flip fail-on-warning: true, so you can adopt it gradually instead of turning your whole repo red on day one.
Two design choices that mattered
No dependencies. It's a single Python 3 file parsed with the stdlib html.parser. No pip install, nothing to pin, nothing to get a CVE next quarter. You can also run it locally:
python3 validate_meta.py page.html
python3 validate_meta.py https://example.com/ --fail-on-warning
Opinionated length windows. Title 30-60 and description 120-160 are the windows Google renders before it truncates in desktop SERPs. The linter warns outside them instead of erroring, because a 62-char title isn't broken — it's just getting clipped, and you should know.
It immediately caught my own bug
The first thing I did was point it at my own site. It flagged a tools page with a 73-char title (truncated in search), a 186-char description (truncated), and — embarrassingly — a missing og:image and twitter:card. Four real issues I'd shipped and never noticed. Two-minute fix, but I'd never have caught them by eye.
That's the whole pitch: the boring tags are the ones nobody re-checks after the first commit, and they're exactly the ones that quietly cost you clicks.
It's MIT-licensed. Repo, full check list, and the local CLI are here: https://github.com/atlashey-collab/seo-meta-action
If you bake it into a pipeline and hit an edge case it mis-flags, open an issue — I want the defaults to be genuinely correct, not just opinionated.
Top comments (0)