skip to content

A product page's JSON-LD passes the schema.org validator without errors, but weeks later Google Search still shows no product rich result for those pages. How would you investigate?

level: seniorimportance: should knowfreq 42%

answer

  1. valid is not the same as eligible
  2. test the live URL, not a snippet
  3. fetch the raw HTML the server sends
  4. does the page actually show it
  5. eligibility, never a guarantee

basics

~20 s

Valid schema.org is not the same as eligible: check the markup against the specific rich-result feature's required properties with Google's Rich Results Test on the live URL, confirm the crawler sees the block in the delivered HTML, and verify the data matches visible page content.

solid answer

~50 s

Split "valid" from "eligible". A generic schema.org validator only checks syntax and vocabulary; each search feature has its own required properties, so run the live URL through Google's Rich Results Test, which reports per-feature errors and warnings. Then check what the crawler actually receives: fetch the page as the server sends it and confirm the `application/ld+json` block is in that HTML rather than being injected later by client-side code. Compare the asserted values with what a user can see — a price or a rating that appears nowhere on the page is a policy violation, not a formatting issue. Look at Search Console's enhancement reports and any manual-action notice for the property. And accept the framing: structured data makes a page *eligible* for a rich result, it does not entitle it to one, so a correct implementation can still show a plain result.

code

bash · 7 lines
bash
# Does the delivered HTML already contain the block, before any JS runs?
curl -s https://example.com/products/mug \
  | grep -c 'application/ld+json'

# Extract it to check the JSON actually parses as delivered
curl -s https://example.com/products/mug \
  | sed -n '/application\/ld+json/,/<\/script>/p'

go deeper

for a junior

Know the distinction to state first: passing a schema.org validator only proves the markup is well formed, and a search feature has its own required properties on top of that.

for a middle

Explain the checks in order — feature-specific test on the live URL, confirm the block is in the server-rendered HTML, confirm the values match the visible page — and name what each rules out.

for a senior

Demonstrate production triage: read Search Console enhancement and manual-action reports, prove what the crawler received rather than what the browser shows, and separate a delivery bug from a policy violation from a feature that simply was not granted.

for a principal

Set the organisation's expectation that structured data buys eligibility, not traffic, and decide how much engineering the chase is worth before a team spends a quarter adding properties for a feature that may be retired.

## Separate the four things that can be wrong When structured data "does nothing", exactly one of four layers is usually at fault: the markup is not valid, it is valid but not *eligible*, it is eligible but the crawler never saw it, or everything is fine and the feature simply was not granted. Diagnose in that order. ## 1. Valid is not the same as eligible The schema.org validator answers a vocabulary question: are these real types and properties, and is the JSON parseable? A search feature asks a stricter question: does this node carry the properties *that feature* requires. A `Product` with only `name` is perfectly valid schema.org and useless for a product result — the merchant-listing feature wants an `offers` node with `price` and `priceCurrency`, an image, and so on. So run the **live URL** through Google's Rich Results Test rather than pasting a snippet. It reports which features the page is detected for, and lists errors (blocking) and warnings (recommended properties whose absence degrades but does not disqualify). A page with zero detected items and a clean schema.org validation is the classic signature of this layer. ## 2. Does the crawler receive the block at all? Request the page the way a crawler does — a plain HTTP fetch, no JavaScript — and search the response body for `application/ld+json`. If the block is absent, it is being injected at runtime by client-side code. Google does render JavaScript, but rendering happens in a separate, deferred pass, and other consumers may never run scripts at all. Server-render the block; it is inert data, so there is no reason for it to depend on hydration. Other delivery-layer causes worth ruling out: the page is not indexed at all, the block is inside a fragment loaded on interaction (behind a tab or a "show details" toggle rendered only on click), or a build step minified the HTML in a way that broke the JSON. Also check the JSON is genuinely parseable in the delivered form. Escaping bugs — an unescaped closing script sequence in a product title, an ampersand written as a character reference and therefore left literal, a smart quote from the CMS — kill the whole block silently while the page renders normally. ## 3. Does the data describe what the user sees? Search engines require structured data to represent content that is present and visible on the page. Assertions the page does not support are a policy problem, and the outcome is not "no rich result" but potentially a manual action against the site. Look for the usual drift: - a rating or review count that appears nowhere in the UI; - a price the JSON-LD took from the list price while the page shows a promotional one; - `availability` hardcoded to `https://schema.org/InStock` on a template used for sold-out items; - FAQ content marked up but hidden behind an accordion that never renders its answers into the DOM; - markup describing the whole catalogue on a category page as if it were one product. This is where the JSON-LD tradeoff bites: because the block is a second copy of the facts, only discipline keeps it true. The structural fix is to serialize it from the same object that renders the visible content, not to audit it by hand. ## 4. Eligible is not guaranteed, and features change Even a perfect implementation only becomes *eligible*. Whether a given result is shown is a per-query, per-page decision, and search engines have narrowed or retired features over time — FAQ rich results, for example, were restricted to a narrow class of authoritative sites, so pages that once showed them stopped. If the feature you are chasing no longer exists for sites like yours, no amount of markup will bring it back. ## Where to look for evidence **Search Console** is the instrument, not the browser. Its enhancement reports list detected item types with counts of valid, warning and error items, so you can see whether the pages are recognised at scale rather than one URL at a time. "Unparsable structured data" is its own report and is where escaping bugs surface. Manual actions appear under their own section. And a URL inspection tells you whether the page is indexed and what the rendered HTML contained. Give it time, too: indexing and re-processing take days to weeks, so a change made last night explains nothing. ## What a strong answer sounds like The weak answer adds more properties and hopes. The strong answer is a triage: prove the feature's requirements are met with the feature-specific test, prove the crawler receives the block by fetching the raw HTML, prove the data matches the page, then say plainly that eligibility is not a guarantee and set the team's expectation accordingly.

  • The block is injected by client-side code after hydration. Is that fatal?
    Not fatal, but fragile. Google renders JavaScript in a deferred second pass, so the data may be picked up late or inconsistently, and other consumers do not run scripts at all. Since a JSON-LD block is inert text with no runtime dependency, there is no benefit to deferring it — emit it in the server response.
  • Search Console reports warnings rather than errors on these pages. Does that block the rich result?
    Warnings flag recommended properties whose absence does not disqualify the page, so the feature can still appear — usually in a less complete form. Errors are the blocking category. Fix errors first, then treat warnings as quality work: filling in an image, a brand, or a review count often decides whether your listing looks better than a competitor's.
  • How would you stop this class of bug from recurring after you fix it?
    Make the structured data a tested artifact. Serialize it from the same object the page renders, assert in a test that key templates emit a parseable block with the feature's required properties present, and watch the Search Console enhancement report for a step change in error counts after a deploy. Hand-auditing pages does not scale past a handful of templates.

saying these in an interview costs you the question

  • Assumes valid schema.org guarantees a rich result
  • Tests a pasted snippet instead of the live URL
  • Adds more properties without reading the feature requirements
  • Ignores that the block is injected client-side
  • Marks up data that appears nowhere on the page

context