Our services

If you can think it, we can make it brainsoft.

Structured data that actually earns rich results in Google

Written By: BrainSoft In SEO

Most sites I audit already have some JSON-LD. Usually it is an Organization block someone pasted from a template, a few properties that do not match anything on the page, and no idea whether Google ever used it. The markup validates, nothing breaks, and nothing changes in the search results either. That is the normal outcome when structured data is treated as decoration.

Structured data earns rich results only when it describes something Google already renders and matches what a human sees on the page. Below I go through the types worth implementing, how to validate them properly, and the mistakes that silently disqualify a page.

Pick types Google actually renders

Google publishes a fixed list of rich result features, and each one maps to a schema.org type. If your type is not on that list, you are writing metadata for other consumers, which is fine, but do not expect a visual change. The ones that reliably produce something visible for a typical business site:

  • Article and NewsArticle for blog posts and news, feeding the top stories and article cards.
  • Product with offers, price, availability and reviews for ecommerce detail pages.
  • BreadcrumbList for the trail under the URL in the result.
  • FAQPage for question-and-answer blocks, though eligibility is now limited to authoritative government and health sites.
  • LocalBusiness for physical locations, which ties into the business panel.
  • Event, Recipe, JobPosting, VideoObject and Course when those are literally what the page is about.

Notice what is missing: Organization, WebSite and Person rarely produce a rich result on their own. They are still worth having, because they feed knowledge panels and sitelinks search boxes, but they are not the thing that changes a snippet. If you only have time for one block, make it match the page type.

Write JSON-LD that matches the rendered page

Google's guidance is consistent: the structured data must describe the visible content. A Product block with a price that no longer appears on the page is worse than no block at all, because it can trigger a manual action for spammy structured data. The same applies to review counts, ratings and availability.

For a blog post, the minimum useful block looks like this. Note that datePublished and author are the fields that most often get dropped and most often matter.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "Structured data that earns rich results",
  "datePublished": "2024-11-04",
  "dateModified": "2024-11-18",
  "author": { "@type": "Person", "name": "Jane Doe" },
  "publisher": { "@type": "Organization", "name": "BrainSoft" },
  "mainEntityOfPage": "https://example.com/blog/post"
}
</script>

Keep the block in the <head> or at the end of the body. Both work. What does not work is injecting it with a tag manager after the page has rendered, because Google's crawler may not execute that path reliably. Server-render it with the rest of the page.

If your CMS cannot emit JSON-LD, that is a build problem, not a content problem. We do this kind of templating work as part of our services, usually by adding a small serializer to the page model rather than hand-writing blocks per post.

Validate before you ship, then check the report

Two tools catch almost everything. The Schema Markup Validator checks the JSON against schema.org, and the Rich Results Test tells you whether Google recognises the type as eligible for a feature. They answer different questions, so run both.

A quick local check before either of those: parse the block in Node and confirm the fields you expect are present.

const blocks = [...html.matchAll(/<script type="application\/ld\+json">([\s\S]*?)<\/script>/g)];
for (const [, raw] of blocks) {
  const data = JSON.parse(raw);
  console.log(data['@type'], data.headline ?? data.name);
}

Then watch the Enhancements reports in Search Console. They lag by days, and they are the only place that tells you Google found an error on a real URL. A common pattern I see: the Article block is fine on the canonical URL and broken on paginated or AMP variants, so the report shows errors on pages nobody looks at.

The mistakes that quietly kill eligibility

  • Marking up content that is hidden behind a login or a tab Google cannot see.
  • Self-serving reviews on your own Organization or LocalBusiness block. Google ignores those and may flag them.
  • Duplicate or conflicting blocks for the same entity on one page, often from a plugin plus a theme.
  • Prices and stock that come from a cached layer and drift from the rendered page.
  • FAQPage markup on commercial pages where the questions are marketing copy rather than real questions.

None of this is exotic. It is the same discipline you apply to any other user-facing output: one source of truth, rendered once, verified after deploy. If you want a second pair of eyes on an existing implementation, get in touch and we will run through it with you.

Frequently asked questions

Does adding JSON-LD guarantee a rich result?

No. Valid markup makes a page eligible, and Google decides per query whether to show the feature. Many rich results only appear for a fraction of impressions, and some types are limited to certain sites.

Should I use Microdata or RDFa instead of JSON-LD?

JSON-LD is what Google recommends and the easiest to keep in sync with a template. Microdata and RDFa still work, but they couple the markup to your HTML structure, which makes refactors riskier.

How long until structured data shows up in search?

Recrawling usually takes days, and the Enhancements report can lag a week or more behind that. Treat it as a slow feedback loop and verify the markup itself before you deploy rather than waiting on the report.


#SEO