olragon

Why did a page with no title score 100 for SEO?

🌱 seedlingplanted #seo#testing#lessons

Written for Anyone writing a scorer, linter, checker or monitor, and anyone trusting a green number they've never seen go red.

I work on an SEO checker, and until late October I believed the number it printed. Now I believe it less, and this note is why.

I re-measured the numbers below on November 2, running the old code from the commit right before the fix, on the rule set as it was then.

Tiếng Việt: Vì sao trang chẳng có title vẫn được 100 điểm SEO?.

What happened

The tool has 325 rules, each looking at one thing: is there a title, is there a viewport, where's robots.txt. Rules sit in groups, groups have weights, and it all adds up to the biggest number on the report. People look at that number first, and often at nothing else.

On October 29 an agent was checking a sentence on a help page, one that said how the tool scores. Instead of trusting the sentence, it failed every Google meta rule. No title, no viewport. The total stayed at 100.

The code behind it is short enough to skim right past:

const w = CATEGORY_WEIGHTS[cat.category] ?? 0;
if (w > 0) {
  weightedSum += cat.score * w;
  totalWeight += w;
}

The weight table says meta-tags. The rule files say meta. The names don't match, so ?? 0 quietly gives a weight of zero and the if skips the whole group. No error, no log line. That line had been sitting there since June.

How bad was it

I took the old code and ran it again, changing only which rules pass or fail:

trytotal
old code, all 325 rules pass100
old code, the 105 forgotten rules all fail100
fixed code, those same 105 fail61

More than a third of the rules never touched the biggest number. That includes meta 27 rules, onpage 16, robots-txt 10, crawl 10, mobile 9, sitemap 8. Exactly the things people think of first when they think of SEO.

Try it here. These eight rules are cut down from the real set, with the real groups and weights. Untick one and that rule fails.

  • meta has a title tag
  • meta has a viewport
  • onpage has an H1
  • robots-txt has robots.txt
  • sitemap has a sitemap
  • technical returns the right status code
  • content the article is long enough
  • security uses HTTPS

Why did no one notice for months? Because the number still looked reasonable. Real pages rarely pass every remaining group, so it said 84, or 73, not 100. A wrong number that looks plausible is much harder to catch than an absurd one. After the fix a carefully built page of mine went from 84 to 90, and a page with no description, no H1 and images without alt went from 73 to 69. The gap between good and weak finally widened the right way.

Same disease, many shapes

This wasn't the only case. Those same two weeks held 26 scoring fixes, and reading them back in one go I saw different shapes, one disease.

A rule reads a place nobody writes to. The API scan put robots.txt and sitemap under a key no rule reads. So all 8 site-file rules saw "no file", and the robots.txt rule failed on every site. The command-line version passed them all. Same rules, two answers.

A parameter declared with care that nobody reads. Three Bing rules spelled out also_check_header, which sounds very responsible. The engine never read that key. A page blocking indexing through a header still passed.

A measurement that never measured. The share image's size read -1, because the image API only has real numbers after metadata(). Every image said "couldn't measure", so the size checks never ran once.

A regex aimed at the whole page. The soft-404 rule looked for 404 anywhere in the HTML. The tool's own help page about soft 404s failed the soft-404 rule, and a correct 404 page failed too.

A rule asking the wrong page. Missing Product schema cost points on every page that sells nothing. Articles were fined for not being products.

Each sounds like its own story. But all five share one thing: the rule's result has nothing to do with what it claims to check, and nothing in the system shouts.

How I check now

The old tests checked each rule: feed in a page with no title, the rule reports it. Rule correct, test green, total still 100. No test asked the question in the middle: does that result reach the final number at all.

The new test goes the other way: fail a whole group, then demand that the total drops.

for (const cat of categories) {
  const total = scoreResults(rules.map((rule) => ({
    rule, passed: rule.category !== cat,
  }))).total;
  expect(total).toBeLessThan(100);
}

And one more: every group name in a rule file must find a weight, so a new name you forgot to declare goes red at once instead of quietly becoming zero. And when an agent edits a rule now, it has to try it on a real 404 and on the page it's aimed at before committing. The soft-404 rule above is where that came from.

The question I took away is short: have you ever seen this check go red? A linter, a monitoring alert, a test, a score: if it has never been red, I don't know that it works. Always green might be good. It might also be a wire that was never connected.

The number I almost copied wrong

Writing this note, I nearly made the very same mistake. The fix commit, the doc and even a comment in the test all say 156 of 325 rules. A nice number, written in three places, and I was about to copy it.

Then I counted again from the rule files at the commit before the fix. It came to 105. The table inside that same doc only adds up to 108. The fix is right; only the number telling its story is wrong, and I don't know where it came from. A number written in three places is still a number nobody recounted.

What I still don't know

  • Those five shapes are the five I've met. There are surely others, and the new test only catches wiring faults, not a rule whose idea is wrong.
  • Weights of 25% for technical and 20% for meta tags are my opinion, not Google's. The score now reflects the rules. Whether the rules reflect ranking, I have no decent way to measure yet.
  • I don't know if a big number like this should be printed at all. People like it, and being so tidy is exactly how the bugs hid for so long.

Have you had a check stay green for years, then found out it never ran? Write me a letter below.

Write papa dragon a letter

If this note stirred something, write to me here. A letter reaches only me and never shows up on the page by itself. If one is lovely and you allow it, I may quote it under the note, without your name.

What the garden keeps from a letter

Works from a terminal too: curl -d 'msg=…' olragon.com/garden/score-100-en/letter