Skip to content

I Built an SEO Checker That Only Measures What Can Be Measured

by Lucas Almeida 4 min read

Every SEO tool hands you a score. “Your content is 73/100.” The problem is what sits inside that number: the title’s character count, which is objective, added to “keyword density”, which is folklore, added to “readability”, which is a formula built in 1948 for English prose. Three incomparable things collapse into one number, and now you do not know what to fix.

I wrote a checker that does the opposite: thirteen objective items, the threshold shown for each, and no score at all. It is a single PHP file, runs on the command line, has no dependencies and works on any site — not just WordPress.

What it checks

Item Criterion
title present, 30–60 characters; above 70 is an error (Google truncates)
meta description present, 120–158 characters
H1 exactly one, 20–80 characters
H2 at least two
hierarchy no level skipping (H2 straight to H4)
canonical present and absolute
Open Graph og:title, og:description and og:image
images at least 90% carrying alt text
word count 300 minimum, 600 desirable
FAQ if the section exists, three questions or more
JSON-LD present and valid JSON
hreflang present and self-referencing
links internal and external — no external link raises a warning

The thresholds live in a constant at the top of the file. If you disagree with one, edit it — that is the point of keeping criteria visible instead of buried under a score.

How to use it

php dr-seo-check.php https://example.com/post/
php dr-seo-check.php page.html
php dr-seo-check.php https://example.com/post/ --json

Output is a list, one item per line:

  ok    title         50 caracteres
  ok    description   158 caracteres
  ok    h1            71 caracteres
  ok    h2            12 subtítulos
 aviso  imagens       82% com alt — 2 sem texto alternativo
  ok    palavras      977
  ok    faq           4 perguntas
  ok    json-ld       Organization, Article, BreadcrumbList, FAQPage
  ok    hreflang      pt-BR, en-US, x-default
  ok    links         53 internos, 9 externos

12 ok · 1 avisos · 0 erros

That report is real — it is a post on this site. So is the warning: the script found two images with no alt text on a page I considered finished. That is what it is for.

The --json mode exists for automation: run it across every post before publishing and fail the build on errors. The script exits with code 1 when it finds an error and 0 when it does not, which is what a pipeline expects.

What it deliberately does not check

This list matters as much as the other one:

  • Keyword density. There is no ideal percentage. Google moved past it more than a decade ago, and optimizing for it produces worse writing.
  • Readability. The formulas in use (Flesch and its descendants) were calibrated for 1940s English by counting syllables. Applied elsewhere, they measure very little.
  • Backlinks and authority. Important, and not on-page. Different tool, different job.
  • An aggregate score. Adding “title is 55 characters” to “has JSON-LD” and producing one number throws away the part you needed.

Why the command line

Because the useful check is the one that runs before you publish, not the dashboard you open afterwards. With a local script you can check a draft saved to a file, without uploading anything, without an account and without a query limit.

It needs PHP 7.4 or newer with the dom and json extensions, both standard. To read https addresses, PHP needs either openssl or curl; if both are missing the script says so and suggests the workaround — save the page with curl -s URL -o page.html and run it against the file.

Download

dr-seo-check (PHP) — download it and rename from .php.txt to .php. It is hosted with a double extension because WordPress blocks .php uploads, for good security reasons.

Free to use, commercially included. If you improve a check, write in — the good version of a tool like this is the one many people have used.

Frequently asked questions

Does it work on non-WordPress sites?

Yes. It reads the HTML the page serves, so it works on any site or local file.

Do I need to install any libraries?

No. Just PHP with dom and json, which are standard. No Composer, no external package.

Can I change the thresholds?

You can and should, if you disagree. They sit in a constant at the top of the file precisely so they can be edited.

Why no 0-to-100 score?

Because a score mixes measurement with opinion and hides both. Thirteen items with declared thresholds tell you what to fix; a number does not.

At DigitalRadar, we publish the tools we use internally. Stay on the radar.

Lucas Almeida
DigitalRadar Newsroom

Desenvolvedor e fundador da Elion Estúdio, Lucas Almeida é especialista em tecnologias emergentes, games e análise de mercado. Com experiência em SEO e growth marketing, foca em conteúdo aprofundado que conecta o universo da tecnologia com o dia a dia das pessoas.

Reported from the sources cited and verified before publishing. See our Editorial Policy.

Leave a comment

Your email address will not be published. Required fields are marked *