Structured data has three separate gates, not one: syntactically valid, eligible for a Google rich result type, and actually selected for display. Passing the Rich Results Test only confirms the first two. Google's own documentation states plainly that marking up a page "enables a feature to be present" — it does not guarantee it appears.
Key takeaways
- Valid, eligible and displayed are three different claims. Every debugging guide checks the first one and stops.
- Content-schema mismatch silently kills eligibility. If the JSON-LD states something the visible page doesn't, Google can and does ignore it.
- Reused @id entities are what make an author identity resolvable across a whole site instead of existing as disconnected fragments per page.
- Adding schema types you don't need is a genuine risk, not a free bet — Google's spam policies cover structured data that doesn't reflect the page.
- The Schema.org validator and the Rich Results Test check different things. One tests vocabulary conformance, the other tests Google-specific eligibility. Neither tests display.
The three gates, and where most debugging stops
Open the Rich Results Test, paste a URL, get a green checkmark, assume the job is done. That checkmark answers one question: is this markup structured the way Google's parser expects. It says nothing about whether Google will actually spend a rich result slot on your page for a given query — that's a separate, per-query decision made by a layout algorithm weighing content quality, page authority, and what else is competing for that result.
| Check | Answers | Doesn't answer |
|---|---|---|
| Schema.org validator | Does this JSON-LD conform to schema.org's vocabulary? | Whether Google recognizes or uses any of it |
| Rich Results Test | Is this markup eligible for a specific Google rich result type? | Whether it will ever be selected for display |
| Search Console URL Inspection | What Google actually parsed the last time it crawled this URL | Whether the item is winning any impressions |
| Live SERP | Whether it's currently showing | Why it isn't, if it's not |
The reasons valid markup still doesn't show
Content-schema mismatch
The JSON-LD says the article has an author, a publish date, and a rating. The visible page shows none of those. Google's structured data guidelines are explicit that markup has to reflect content actually present and visible to a user on the page — not content that's true, just not shown. This is one of the most common reasons a technically valid item quietly stops being eligible: the parser sees the claim, the renderer can't verify it against the DOM, and the item drops out.
Quality gates unrelated to the markup itself
Thin content, aggressive ad density, or a page Google's quality systems otherwise distrust can suppress a rich result even when the structured data is flawless. This is the part most JSON-LD debugging guides skip entirely, because it has nothing to do with the markup — the schema was never the bottleneck.
Indexing lag
A change to your JSON-LD doesn't take effect the moment you deploy it. Google needs to recrawl and reprocess the page, which for a low-authority or infrequently-crawled URL can take days to weeks. Request indexing through Search Console after a structured-data change rather than assuming the old result is a current failure.
The wrong schema type for what Google actually shows
Not every valid schema.org type maps to a Google rich result. You can mark up something correctly per the vocabulary and simply be outside the list of types Google currently renders specially — valid schema, no display path, because there was never one to begin with for that type.
A worked example: this page's own @graph
Rather than a hypothetical, here's what's actually in the <head> of this page right now — view source and check. It's a single JSON-LD block with an @graph array containing four linked nodes instead of four separate script tags, which is the part most implementations get wrong first.
| Node type | Purpose | What links to it |
|---|---|---|
| Person | The author entity, one fixed @id reused on every page site-wide | Referenced by author and publisher below |
| TechArticle | This page's own content, dates, and section | Points to the Person via @id, not a duplicated object |
| BreadcrumbList | The Home → Visibility → this-page path | Referenced by the article's breadcrumb property |
| FAQPage | The four questions answered below, verbatim | Standalone, targets the FAQ rich result independently |
The detail that actually matters: the Person node's @id — https://badridutta.com/#person — is identical across every page on this site that credits this author, not a fresh object per page. That's what lets Google resolve "Badri Dutta" as one entity across a dozen pages instead of a dozen disconnected name mentions, and it's a one-line decision that's easy to get wrong the first time you build a multi-page @graph.
How to actually debug it
- Check the Schema.org validator first. If this fails, nothing downstream matters yet — fix the vocabulary conformance.
- Then the Rich Results Test. Confirms Google-specific eligibility, which is a narrower, different check than vocabulary validity.
- Then Search Console's URL Inspection tool, not your browser's dev console — this shows what Google actually parsed on its last crawl, which can lag your live markup.
- Compare the markup's claims against the rendered page. Every property in the JSON-LD should be verifiable by looking at the visible content — if it isn't, that's the eligibility leak, not a Google bug.
- If all four pass and nothing displays, the markup was never the constraint — it's a display decision made per-query, and no amount of additional schema fixes that.