# Search engines saw 4 syllables. The page had 199. Here's the bug.

> Source: <https://dev.to/superfire/search-engines-saw-4-syllables-the-page-had-199-heres-the-bug-59a4>
> Published: 2026-10-17 04:47:51+00:00

This article was created with the help of AI and reviewed line by line by the author. Every number below was verified against the running site.

A pinyin chart is a table of roughly 400 syllables. The one I maintain had 199 of them in its data file.

Both numbers were true. Bing agreed with the first one and disagreed with the second.

The page rendered its table at runtime. The HTML that a crawler fetched contained an empty table element: a `table` tag with the class `pc-grid` and nothing between its tags.

Everything below that point (19 initials, 199 syllables, the four-tone grid) lived inside a JavaScript object called `SIMPLE`. The code was correct. It just did not exist in the document.

Strip the script tags from the served page and you can read four syllables in its text content. Four.

Bing Webmaster Tools, three-month window. One page, 101 impressions, 0 clicks, average position 6.

We had assumed this was a copy problem for weeks. Title, description, the promise in the H1, all of it fine. A page sitting at position 6 for its main query with zero clicks out of 101 impressions usually means one thing: the searcher arrives expecting a chart, finds an empty box while the script boots, and leaves before it paints.

Pre-render the data into the markup at build time. Keep the JavaScript for the click handler, drop it from the rendering job.

The build step walks the same data structure the client script would have walked, and writes each syllable into a table cell as plain HTML. The served document now exposes 374 syllable cells to a crawler, and the page still plays audio on click because the JavaScript never went anywhere.

Same treatment on four more pages in one pass (tone comparison, name generator, stroke order rules, number hand gestures). One rule held throughout: if the content is the point of the page, it cannot live behind a script tag.

The page in question is [https://thechinesepath.com/pinyin-chart](https://thechinesepath.com/pinyin-chart) if you want to check the markup yourself.

The obvious version of that script was not idempotent. It ran over five pages, the name generator threw on a missing anchor, and the first four files were already on disk. Re-running wrote them again. One data table ended up with five copies of a row where it should have had three.

The rule became: dry-run every page first, and if any single one fails, write nothing. Mark what you injected with a token you own, never with something you count in the output, since counting injected markup to decide whether it was injected cannot work.

The same project reported "zero backlinks" for nineteen days. The tool returned an empty list every time, so zero went into the notes and stayed there.

The backlinks existed the whole time. Three links from a DEV post, all live, none of them nofollow. A different endpoint in the same API (one returning an anchor count per URL instead of a list) showed them immediately.

An empty list is not an empty set. Before writing any number into your notes, check whether your tool is reporting "nothing found" or "nothing searched."

If you serve a static site and a chunk of your content is generated client-side, run this check today: fetch your own page, strip the script tags, count what is left. If the number is small, you already know why your rankings look flat.
