Guides · 4 min read · Updated 2026-09-08
Structured data validation: required properties, rich-result eligibility, and the errors that cost you the snippet
Schema.org markup only earns rich results when it's valid, complete and consistent with the page. The types that matter, their required and recommended properties, the errors that disqualify them, and how to validate every page at once.
Structured data is machine-readable markup that describes what a page is: a product with a price, an article with an author and date, a recipe with cooking time, an FAQ. Search engines use it to show rich results: star ratings, prices, breadcrumbs, event dates. The markup only helps if it’s valid, has the properties Google requires for that result type, and matches the visible page. A missing required property fails silently: no error on the page, just no rich result, and no explanation of why the competitor has one.
The three formats
JSON-LD in a <script type="application/ld+json"> block is what Google recommends and what nearly everyone should use. It’s separate from the HTML, easy to template, and easy to validate. Microdata attributes on HTML elements (itemscope, itemprop) work but tangle markup with content. RDFa is rare outside government and academic sites. Truelint parses all three and reports the format per page; mixing formats on one page is a source of duplicated or contradictory items.
What “valid” means, in layers
- It parses. JSON-LD with a trailing comma or an unescaped quote is silently ignored. Truelint reports parse errors per page; on a site where the markup is templated, one parse error usually means every page of that type is broken.
- It has a recognised type.
@type: Product, not@type: productor a made-up name. - It has the required properties for the rich result. Google’s requirements are stricter than schema.org’s; schema.org makes almost everything optional, Google requires specific fields per result type.
- It has the recommended properties. Missing recommended fields don’t disqualify the result, but Google says they improve eligibility and display.
- It matches the page. Prices, ratings and names in the markup must be visible on the page. Markup for content that isn’t there is a policy violation and a manual-action risk.
Required properties for the types that matter
| Type | Required for rich results | Recommended |
|---|---|---|
| Product | name, plus offers (with price, priceCurrency) or review or aggregateRating |
image, description, sku, brand, availability |
| Article / NewsArticle / BlogPosting | headline, image, datePublished |
author (with name), dateModified, publisher |
| BreadcrumbList | itemListElement with position, name, item for each |
— |
| FAQPage | mainEntity of Questions, each with name and acceptedAnswer.text |
— |
| Recipe | name, image |
author, prepTime, cookTime, recipeIngredient, recipeInstructions, aggregateRating |
| Event | name, startDate, location |
endDate, offers, performer, organizer, image |
| Organization | name, url |
logo, sameAs, contactPoint |
| LocalBusiness | name, address |
telephone, openingHours, geo, priceRange |
| VideoObject | name, thumbnailUrl, uploadDate |
description, duration, contentUrl |
| JobPosting | title, description, datePosted, hiringOrganization, jobLocation |
baseSalary, validThrough, employmentType |
| Review | itemReviewed, reviewRating, author |
datePublished, reviewBody |
Truelint checks 35 types against required and recommended properties and marks each item as rich-result eligible or not, with the missing properties named.
The errors, in order of how often we see them
Required property missing. Product without offers; Article without image; FAQPage questions without answers. The most common and the most costly.
Wrong value type. A price of "$19.99" (should be 19.99 with priceCurrency: "USD"); a datePublished as March 3 (should be ISO 8601); a ratingValue outside the declared bestRating.
Blank values. Templates that emit "author": {"name": ""} when the field is unset. Blank is worse than absent because it’s syntactically present and semantically empty; Truelint flags blank required and recommended values specifically.
Markup that contradicts the page. A rating in the markup with no visible reviews; a price that differs from the displayed one; FAQPage markup on a page with no visible FAQ. This is the one that draws manual actions.
Duplicate or conflicting items. Two Organization objects with different names on one page, usually one from the theme and one from a plugin.
Self-serving reviews. Review and aggregateRating on your own Organization or LocalBusiness are no longer shown by Google.
Deprecated or invented types. @type: "WebPage" on everything adds nothing; @type: "SEOPage" is not a type.
Schema on the wrong pages. Product markup on a category listing; Article on a contact page.
Validating a whole site
Google’s Rich Results Test validates one URL at a time and shows what Google would display. That’s the right tool for checking one template. For a site, you need to validate every page and group the results by type and error, which is what a crawl does.
Truelint’s Structured Data tab lists each page’s items with format, type, errors, warnings and eligibility, and its filters isolate parse errors, missing required properties, missing recommended properties, and ineligible items. The Issues pane groups the same findings by rule with fix guidance. Because markup is templated, fixing one page type’s template fixes hundreds of pages; the crawl tells you which templates.
A working process
- Decide which rich results you’re targeting per template. Not every page needs markup; every page that could show a rich result should have complete markup for exactly one type.
- Implement in JSON-LD, templated from the same data the page displays, so they can’t disagree.
- Validate one page of each type in the Rich Results Test.
- Crawl the site and check that every page of that type is eligible and error-free.
- Watch Search Console’s enhancement reports for the next month; they show what Google actually recognised.
- Re-crawl after any template change.