{"slug": "search-engines-saw-4-syllables-the-page-had-199-here-s-the-bug", "title": "Search engines saw 4 syllables. The page had 199. Here's the bug.", "summary": "A developer maintaining a pinyin chart site found that Bing indexed the page as containing only four syllables because the 199-syllable table was rendered client-side, leaving crawlers with an empty table element. The fix pre-renders the data into plain HTML at build time, exposing 374 syllable cells to crawlers while keeping JavaScript for click handlers, and the same treatment was applied to four other pages. The developer also reported a non-idempotent injection script that duplicated rows and a backlinks API that returned an empty list for 19 days despite three live links.", "body_md": "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.\n\nA pinyin chart is a table of roughly 400 syllables. The one I maintain had 199 of them in its data file.\n\nBoth numbers were true. Bing agreed with the first one and disagreed with the second.\n\nThe 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.\n\nEverything 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.\n\nStrip the script tags from the served page and you can read four syllables in its text content. Four.\n\nBing Webmaster Tools, three-month window. One page, 101 impressions, 0 clicks, average position 6.\n\nWe 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.\n\nPre-render the data into the markup at build time. Keep the JavaScript for the click handler, drop it from the rendering job.\n\nThe 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.\n\nSame 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.\n\nThe page in question is [https://thechinesepath.com/pinyin-chart](https://thechinesepath.com/pinyin-chart) if you want to check the markup yourself.\n\nThe 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.\n\nThe 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.\n\nThe 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.\n\nThe 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.\n\nAn 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.\"\n\nIf 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.", "url": "https://wpnews.pro/news/search-engines-saw-4-syllables-the-page-had-199-here-s-the-bug", "canonical_source": "https://dev.to/superfire/search-engines-saw-4-syllables-the-page-had-199-heres-the-bug-59a4", "published_at": "2026-10-17 04:47:51+00:00", "updated_at": "2026-10-17 05:00:17.419689+00:00", "lang": "en", "topics": ["generative-engine-optimization", "ai-crawlers", "structured-data", "developer-tools"], "entities": ["Bing", "Bing Webmaster Tools", "thechinesepath.com", "DEV"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/search-engines-saw-4-syllables-the-page-had-199-here-s-the-bug", "markdown": "https://wpnews.pro/news/search-engines-saw-4-syllables-the-page-had-199-here-s-the-bug.md", "text": "https://wpnews.pro/news/search-engines-saw-4-syllables-the-page-had-199-here-s-the-bug.txt", "jsonld": "https://wpnews.pro/news/search-engines-saw-4-syllables-the-page-had-199-here-s-the-bug.jsonld"}}