Skip to content
Browse all guides

Issue #201 · standard

Issue 201

What is this issue?

This issue checks whether a page that presents itself as a comparison actually contains a table.

Pages titled "X vs Y", "Comparing X and Y" or "X alternatives" make a promise: the reader wants attributes lined up side by side. A <table> delivers that in a form both people and answer engines can read directly. Prose describing the same differences requires the reader — and the model — to reconstruct the grid themselves.

A passing implementation puts the compared attributes in a table. A failing one describes the comparison only in paragraphs.

Example: "Postgres vs MySQL" with a table of features down the left and one column per database passes. The same page as six paragraphs of "Postgres does this, whereas MySQL does that" fails.

Why does it matter?

Tables are quotable; prose comparisons are not. An answer engine asked "what is the difference between X and Y" can lift a table row wholesale. To answer from prose it has to infer the structure, and it frequently declines to try.

Comparison queries are high-intent. Someone searching "X vs Y" is choosing. Being the source an engine cites for that comparison is worth more than being one of ten blue links.

A table is the honest format for the content. If the page genuinely compares attributes, a grid is the shape of the information. Prose is the shape only when the comparison is narrative.

It exposes gaps in the comparison itself. Building the table surfaces the attributes covered for one product and skipped for the other — which readers notice as bias.

How to fix it

  1. List the attributes you actually compare. Price, performance, licensing, support, limits — whatever the page discusses.

  2. Build a real <table>. One row per attribute, one column per option, with a proper <thead> and <th> headers. Do not fake it with CSS-styled <div>s: an engine reading the markup sees no table, and neither does a screen reader.

  3. Fill every cell. A blank cell reads as "unknown". If an option genuinely does not have the attribute, say "Not supported" rather than leaving it empty.

  4. Keep the prose. The table is not a replacement for your analysis — it is the summary the analysis supports. Keep the paragraphs that explain why the differences matter.

  5. Consider a summary row. "Best for" as a final row gives an engine a one-line recommendation to quote.

Note on scope: this check only runs on pages whose own title or <h1> declares a comparison. It never fires on ordinary content pages.

Examples

Failing

<title>Postgres vs MySQL: which should you choose?</title>
<h1>Postgres vs MySQL</h1>
<p>Postgres offers stronger support for complex queries, while MySQL has
historically been faster for simple reads…</p>
<p>On licensing, Postgres uses the PostgreSQL License, whereas MySQL…</p>

The comparison is real, but there is no structure to lift.

Passing

<title>Postgres vs MySQL: which should you choose?</title>
<h1>Postgres vs MySQL</h1>
<table>
  <thead>
    <tr><th>Feature</th><th>PostgreSQL</th><th>MySQL</th></tr>
  </thead>
  <tbody>
    <tr><td>Complex queries</td><td>Excellent</td><td>Good</td></tr>
    <tr><td>License</td><td>PostgreSQL License</td><td>GPL / commercial</td></tr>
    <tr><td>Best for</td><td>Analytical workloads</td><td>Simple read-heavy apps</td></tr>
  </tbody>
</table>
<p>The licensing difference matters most if you…</p>

Not evaluated

<title>About us</title>
<h1>About us</h1>

No comparison intent, so the check does not run.

How PixyScan detects this

PixyScan detects this from the HTML your server returns, without executing JavaScript.

  1. Intent gate. The page's <title> and <h1> are read. The check proceeds only if either matches a comparison pattern: vs, vs., versus, compare/comparison/comparing, or alternative/alternatives.

  2. Substance gate. The page must have at least 150 words of body text, so stubs and navigation pages are never evaluated.

  3. Table detection. PixyScan looks for at least one <table> element anywhere in the body.

  4. Reporting. If the page declares a comparison, has real content, and contains no <table>, the issue is raised once for the page, carrying the title that triggered the gate.

Why the gate matters: without it, this check would ask every page on your site for a table. The intent gate means a page can only fail if it has already told us it is a comparison.

Limitation: tables rendered by JavaScript after page load are not visible to PixyScan. A table built client-side will be reported as missing, and will also be invisible to the answer engines this check is about.

References