← All posts

Schema Drift: When Your Markup Claims Things Your Page Doesn't

{ } JSON-LD claims Rating: ★ 4.9 Price: $19 MISMATCH schema ≠ page visible page content Rating: ★★★ 3.2 Price: $149 Google may demote or ignore schema with visible mismatches

A product page at a mid-size retailer was ranking well and showing a clean price-drop rich result in Google Shopping. Then the price changed. The merchandising team updated the database, the displayed price changed, but the JSON-LD block in the template — which had been hardcoded by the developer who built the product detail page — still claimed the old price. Four weeks later, Google’s structured data quality algorithms noticed the discrepancy. The rich result dropped. Two weeks after that, Google Search Console surfaced a manual action notice for “structured data that misrepresents page content.”

This is schema drift, and it is more common than the audits most teams run would suggest.

Google’s Policy and Why It Exists

Google’s structured data guidelines are explicit: markup must represent content that is visible to users. The policy is not a technicality — it exists because structured data is a high-trust signal that feeds rich results, knowledge panels, and increasingly AI answer engines. When a site can claim a 4.9 star rating in schema without showing any reviews on the page, or claim a price lower than the displayed price to win price-comparison placements, structured data becomes a spam vector. Google treats it accordingly.

The relevant enforcement mechanisms are two-tiered. Rich-result suppression is automatic — algorithms detect property values that don’t match visible content and suppress the rich feature without human review. This happens quietly; you notice it in Search Console’s rich-result report and in click-through rate data, not in a notification. Manual actions for structured data spam are human-reviewed and more severe. They appear in the Manual Actions section of Search Console, affect the entire property or specific URL groups, and require a reconsideration request to resolve. The manual action threshold is generally repeated or egregious drift — a templated 4.9 rating with zero on-page reviews across ten thousand product pages will get there faster than a price discrepancy on one SKU.

How Schema Drift Happens

Understanding the failure modes helps you design audits that catch them before Google does.

Hardcoded template values are the most common cause. A developer builds a product template, writes the JSON-LD block, and sets "aggregateRating": {"ratingValue": "4.8", "reviewCount": "127"} from an example or a current snapshot. The code ships. Months later, reviews accumulate or the product gets relaunched, but no one updated the schema template because there was no process to do so.

Caching skew is the second major cause. A price changes in the database. The rendered page pulls from a CDN cache that hasn’t been invalidated yet. The JSON-LD block, generated server-side at request time, reflects the new price — but the HTML the user sees is cached and shows the old price. The schema is now technically current but contradicts the visible page. The inverse also happens: the template cache updates but the schema generation relies on a slower data pipeline.

CMS plugin divergence creates drift on WordPress and similar platforms. An SEO plugin generates schema from custom fields. A theme update changes how prices or ratings display visually. The two systems are not coupled, so they diverge quietly.

Aggregation source disagreements happen with ratings and reviews. The aggregateRating in schema is pulled from one data source — maybe a third-party review aggregator — while the stars visible on the page come from a different data source with different tallying. They display the same number for years, then a data pipeline change causes them to diverge.

Content decay drives drift on pages that once had the on-page evidence to support schema claims and no longer do. An FAQPage type works fine when there are ten questions on the page. A redesign consolidates the FAQ into an accordion that the CMS now manages differently, and the schema continues claiming ten QA pairs that don’t render in a way Google’s parser recognizes as visible content.

The High-Risk Schema Types

Not all schema types drift equally. The types most likely to produce reconciliation failures are the ones whose property values change frequently or are sourced from external systems.

Product with offers is the highest-risk type in most e-commerce contexts. price, priceCurrency, and availability (InStock, OutOfStock, PreOrder) change frequently and are often managed in separate systems from the schema template. The priceValidUntil property is particularly neglected — a sale price with a priceValidUntil date in the past will show stale schema data indefinitely unless the template handles expiry.

AggregateRating is high-risk across any site with user-generated reviews. The specific properties that drift most often are ratingValue (the aggregate score), reviewCount (total reviews), and bestRating/worstRating (the scale). Any of these mismatching the on-page display is a policy violation. The worst case is aggregateRating markup on a page with no visible reviews at all — a product page where reviews are loaded client-side and the schema is in the server-rendered HTML but the reviews themselves fail to render for bot user-agents.

Review and FAQPage have similar visibility requirements. FAQPage schema that claims questions and answers not present in the visible DOM — either because they’re in a collapsed state that bots don’t parse, or because the FAQ section was removed during a redesign — is a clear drift case. Google’s rich-result documentation for FAQPage explicitly states that the Q&A content must be visible on the page.

Event with startDate, endDate, and location drifts when events are rescheduled or cancelled. A cancelled event that still shows as EventStatus: EventScheduled in schema is both a user-trust problem and a policy violation.

Recipe with cookTime, prepTime, and recipeYield drifts when recipe authors update their content but forget the schema. A recipe that was reformulated to serve four but the schema still claims eight servings is a minor mismatch but still detectable.

Detection: Diffing Schema Against the Rendered DOM

The core detection method is property-level reconciliation: extract a schema property value, find the corresponding visible text in the rendered DOM, and compare them. This sounds straightforward, but the implementation has edge cases that matter.

Price comparison requires normalizing currency formatting. "29.99" in schema needs to match against "$29.99", "$29.99 USD", "29.99 €", and other display formats. Fuzzy numeric matching with currency normalization is more reliable than string equality.

Rating comparison requires handling display rounding. A schema ratingValue of 4.73 might display as 4.7 or even 5 stars with an icon representation. The comparison needs to account for rounding conventions, not just character-level equality.

Review count comparison is often complicated by lazy loading. Review counts are frequently rendered by JavaScript after initial page load. If the raw HTML shows zero reviews and the schema claims 847, the question is whether the rendered DOM shows 847. If the JavaScript loads reviews from an API and the rendered DOM shows a review count, the comparison should use the rendered value. VisibilityIQ reconciles schema values against the rendered DOM text, not the raw HTML, so this pattern is handled correctly — but it illustrates why render parity matters for schema validation as much as for content.

FAQPage answer reconciliation is more complex because the comparison isn’t numeric. You’re checking that the visible text contains a recognizable version of the schema answer. Exact match is too strict; fuzzy text similarity with a threshold works better and tolerates minor HTML formatting differences.

The Rendering Dimension

A class of schema drift problems is actually a rendering problem: the schema is correct, but the content it describes is only visible after JavaScript execution. Google can render pages, but bot user-agents that don’t execute JavaScript — and AI crawlers that increasingly fall into this category — see only the raw HTML. If your product price is in the server-rendered HTML and the reviews section loads via a client-side API call, Googlebot may render the page and see both, but GPTBot or a monitoring crawler running against the raw response will see a price in schema with no visible reviews to confirm the rating.

This is the intersection of schema drift and render parity. The corrective action is usually moving critical schema properties to match what’s in the server-rendered HTML, or ensuring the client-side content is accessible without JavaScript for the property values claimed in schema.

Catching It Before Google Does

An effective schema drift audit runs on the same cadence as content changes, not on a quarterly SEO audit schedule. The checks that matter most are:

Comparing offers.price against the displayed price for every product SKU in the crawl, flagged when the numeric values differ by more than rounding. Checking aggregateRating.reviewCount against the visible review count in the rendered DOM. Verifying aggregateRating.ratingValue rounds to the same display value as the visible star rating. Checking FAQPage acceptedAnswer.text values against the visible Q&A text. Checking Event.startDate and Event.endDate against the visible event dates. Checking Article.datePublished and Article.dateModified against visible publication and update dates.

VisibilityIQ extracts every JSON-LD block, enumerates properties by type, and cross-references each value against the rendered DOM text, flagging mismatches with the specific property path, the schema value, and the visible text it found. The result is a diff-style report rather than a pass/fail — you see exactly what the markup claims versus what the page shows.

The connection to content decay is worth noting. Pages that decay — losing reviews, having events expire, having product lines discontinued — are disproportionately likely to develop schema drift because the schema update cadence rarely matches the content update cadence. Monitoring both in the same audit pipeline means schema drift surfaces when content changes, not months later when a manual action notice arrives.

Schema that accurately reflects visible page content is not a nice-to-have. It is the baseline for trust with Google’s structured data systems. Drift that goes undetected is drift that compounds — more pages affected, more properties mismatched, more signal to the quality algorithms that the markup is not trustworthy. Catching it is a matter of diffing schema against the structured data you’ve deployed against what the page actually shows.

Frequently asked questions

What does Google mean when it says structured data must represent visible page content?
Google's structured data policy requires that schema properties reflect what a user can actually see on the page. If your Product schema claims a price of $29.99 but the page displays $49.99, or your AggregateRating says 4.8 stars but there are no visible reviews, the markup is misleading. Google can suppress rich results or issue a manual action for structured data that contradicts page content.
How common is schema drift on e-commerce sites?
Very common. Price and availability are the most frequent drifters because they change frequently and the schema template often updates on a different cadence than the displayed content. Sites that cache rendered pages or use CDNs without cache-busting on inventory changes are especially vulnerable to showing stale schema values while the page displays current ones.
Can schema drift cause a manual action, not just rich-result loss?
Yes. Google's documentation specifically lists 'structured data that is not representative of the main content of the page' as a basis for manual actions in the structured data spam policies. Rich-result loss is the typical first consequence, but persistent or egregious drift — particularly inflated review counts or fabricated ratings — can escalate to a site-level manual action.