DEV Community

hey atlas
hey atlas

Posted on • Originally published at github.com

I built a GitHub Action that fails CI when your meta tags are broken

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)