Here is a story that plays out on a lot of sites. The schema markup was fine. It validated, the rich results showed, an audit gave it a clean bill. Then, some weeks or months later, someone notices the rich results are gone, or an AI assistant describes the business using facts that are nowhere on the current site, and a check shows the JSON-LD has been missing from every page for a while. Nobody edited the schema. Nobody got an error. The markup just quietly stopped being there, and nothing said so.
This is the failure mode that makes structured data different from almost everything else on a site. When a page's layout breaks, you see it. When a form breaks, someone complains. When the schema breaks, the page looks identical, the build is green, and the only signal is a slow drift in reports that most people do not check daily. Because schema is template-driven, it also breaks everywhere at once, so there is no "some pages are still fine" to tip you off, and the effect (rich results fading, an AI assistant repeating stale facts) shows up long after the change that caused it.
The companion piece is about stopping the break before it ships, by wiring schema checks into a build pipeline, and it goes deep on why the failure is so easy to miss. This post is about the case where there is no pipeline, or the break got through anyway: what actually removes schema when you change something, and the ways to find out it happened without waiting for Search Console to tell you months later.
What actually removes or breaks schema when you deploy
The important thing about this list: almost none of these are changes to your schema. They are changes to something else that had a side effect on your markup. That is why they slip through.
Something took over, or got switched off
An SEO plugin update re-enables its own schema. You had Yoast or Rank Math for meta tags and sitemaps, with its schema feature deliberately turned off because another tool owns that. An update resets the setting, or adds schema output where there was none, and now every page has two Organization nodes and two Article blocks fighting each other. This is the most common version, and it is covered in full in duplicate schema from two sources.
A new plugin brings its own schema, on by default. Someone installs a plugin for reviews, or events, or FAQs, and it ships structured data nobody asked for. Now there is a third source.
A theme switch drops the schema the old theme was emitting. Plenty of themes output their own Organization, breadcrumb, and article markup. Switch themes and that output goes with the old theme, and if nothing else was providing it, the site now has none.
A half-finished migration. Moving from one schema tool to another, and for the whole window where the old one is off and the new one is not fully configured, pages ship with partial markup or none.
A performance layer ate it
JavaScript optimizers defer or rewrite the script. Tools that concatenate, minify, or delay JavaScript can catch a script that injects your JSON-LD and push its execution past the point where a crawler reads the page, or mangle it. Cloudflare's Rocket Loader is the one named most often: it rewrites script handling for speed, and there are reports of it causing "unparsable structured data" warnings. Where your schema is injected by a script rather than printed as a static block, this is a real risk. The fix is to mark the script so the optimizer leaves it alone (Cloudflare's is a data-cfasync="false" attribute) or to turn the feature off for the affected pages.
An HTML minifier corrupts the block. Aggressive HTML minification can strip whitespace inside the JSON in a way that breaks it, or collapse a </script> that appears inside a string value.
A CDN or edge HTML transform. Some edge configurations rewrite HTML in flight (injecting tags, rewriting URLs, stripping comments) and can disturb a JSON-LD block as a side effect.
A consent or tag layer blocked it
Schema delivered through a tag manager. If your JSON-LD is injected by Google Tag Manager rather than rendered by the site, it only exists if that tag fires, and fires fast enough for the crawler. A consent banner that holds non-essential tags until the visitor clicks "accept" can mean a crawler, which clicks nothing, never sees the schema at all.
A consent tool that blocks scripts by category. GDPR and consent-mode tools that block "non-essential" scripts before consent can catch a schema injector along with the analytics and marketing tags, depending on how it is categorized.
The render moved
A section went client-side. A template gets refactored and the part that held the schema now renders in the browser instead of on the server. The markup is still "in the code", it just is not in the HTML the server sends. This is one of the documented reasons schema stops showing, and it is easy to introduce in a routine refactor.
An A/B test or edge redirect serves a variant. A testing tool or a personalization layer serves some visitors, or some crawlers, a version of the template that was built without the markup.
The block was in a spot that got refactored away. Hand-added JSON-LD often lives in a specific template part, the header include, a footer file, a hook that fires at a particular point. A redesign rebuilds the header, or someone swaps the hook the markup was attached to, or a "clean up the page head" optimization plugin removes <script> tags it does not recognize from the head. The output function is still defined, nothing calls it any more.
The data behind it dried up
A field the schema read got renamed or removed. The markup pulls the author, or the price, or a set of sameAs links from custom fields. Someone renames the field in a content model change, and the schema property it fed is now empty, or the whole block fails to build.
An image the markup points at moved. The logo or image URL now returns a 404 after a media reorganization, so the property is present but points at nothing.
An entity got deleted. The author account, or a linked organization, is removed, and now every article that referenced it by @id has a reference pointing at nothing. A reference that resolves to nothing is treated as worse than the property being absent.
It is still there, but now it is lying
A category worth naming even though the block did not disappear. The price changed and the markup did not. A sale ended. The review count on the page is 240 and the AggregateRating still says 88. The schema is present and valid, it just no longer matches the page, which is a policy problem and a trust problem rather than a missing-markup one. The mismatch cases are covered in common schema errors.
How to find out, ranked by effort
Have something re-crawl and tell you
The lowest-effort option is a tool that re-reads your site on a schedule and alerts you when the structured data situation changes, so you are not the monitoring system.
This is what AI Schema Gen does for a connected site on a paid plan: it re-crawls the whole site about once a week, compares the result against the last one, and emails you when your AI readiness score drops past a threshold you set. The alert names what moved, and a schema regression shows up in it directly, in the form of a line like "12 more pages now have no schema at all (12 of 40)". A deploy that strips markup from a template does not sit unnoticed until someone thinks to check, it lands in your inbox after the next crawl. Re-running an audit by hand triggers the same comparison, so checking a fix also re-checks for regressions.
Search Console is the other automated signal, and it is free. A drop in valid items, or an error spike, in the Rich Results and Enhancement reports is a template-level break. The catch is speed: it moves at the pace of Google recrawling you, which can be weeks, and it only covers the types Google shows a rich result for, so a Service or a plain Organization block vanishing does not register there at all. Treat it as a backstop, not the primary alarm. Reading those reports and working the validate-fix cycle is its own topic, covered in Search Console schema errors.
Run a scheduled check of your own
If you want a signal faster than Search Console and do not want to depend on a tool, a small scheduled job does most of it. Not in your build, against production, on a timer.
The shape: pick one representative URL per template, fetch the raw HTML (not a rendered browser view), pull every application/ld+json block out of it, and assert three things. That each block parses as JSON. That the page carries the @type it should (a product page has a Product, a post has an Article). And, optionally, that the block is roughly the size it was last time, which catches the block getting smaller as well as vanishing. Fail the check and it pings you.
The companion CI/CD post linked above carries a compact version of that extraction script; the only change for monitoring is to point it at live URLs and run it from a scheduler (a cron job, a scheduled GitHub Action, an uptime monitor that can check response content) instead of from a pull request. Keep the list of URLs short and representative, one per template, not a full-site crawl, so the check stays fast and cheap enough to run often.
Keep a golden copy and diff it
A step up from "is it present" is "did it change". Save a known-good copy of the extracted, normalized JSON-LD for each template. On a schedule, fetch the live pages, extract again, and diff against the saved copy. Any difference, a property that disappeared, a value that emptied, a whole block gone, shows up as a diff you can review. This is the version that catches slow erosion: a block that loses one property per quarter never trips a presence check but is clearly wrong after a year.
Two details make this work in practice. Normalize before you diff, sort keys, drop the values that are meant to change (the dateModified, a price, a stock status), so the diff shows structural change rather than every routine content edit. And review the diff like a code review: a deliberate change gets the golden copy updated, an unexplained one gets investigated. The saved copies live alongside your code or in a shared doc, so a change to them is visible and dated.
The manual habit that costs two minutes
Not everything needs automating. The single most valuable manual check is a post-deploy spot check, done deliberately after the changes most likely to cause this:
- After any plugin update, especially an SEO plugin.
- After installing any new plugin.
- After a theme change or a theme update.
- After changing anything in a performance, caching, or optimization plugin or a CDN's speed settings.
- After a consent tool or tag manager change.
The check itself: open one page per template, view the page source (the raw source, not the browser's element inspector, which shows the page after scripts have run and will hide exactly this problem), and confirm the JSON-LD block is there and looks complete. Loading the page with JavaScript disabled is a fast way to see whether the markup depends on a script running, if it vanishes with JavaScript off, a crawler may not be seeing it either.
What to actually watch for
Calibration matters, because an alert that fires on noise gets ignored within a week.
Presence, parse, and type. Is there a block, does it parse, does it carry the type the page should have. These are the checks worth alerting on hard.
Block size, loosely. A representative block dropping to a third of its previous size is a strong signal something stopped populating, even if it still parses.
Not exact values. A dateModified that advanced, or a stock status that flipped to out of stock, is the site working, not a regression. Alert on a property going empty or a block going missing, not on a value being different from last time.
Count at the site level. The number of pages with no schema at all, tracked over time, is the cleanest single number. When it jumps, a template broke.
Pick who gets told. A schema regression alert that goes to a shared inbox nobody owns is the same as no alert. It needs a named person or a channel someone watches.
Common mistakes
Checking the inspector instead of the source. The browser's element inspector shows the DOM after JavaScript has run. A schema block that only exists after a script runs looks fine there and is invisible to a crawler. View source, every time.
Only ever checking the homepage. The homepage is usually the one page someone set up carefully. A template break shows up on posts, product pages, and category pages first. Check one of each.
Treating a passing validator as ongoing proof. A page that validated once can lose its markup next week. Validation is a point-in-time check, not a monitor.
Assuming "we didn't touch the schema" means the schema is fine. Almost every case in the catalogue above was caused by a change to something else. "We didn't touch it" is not evidence.
No baseline. If you have never recorded what good looks like for each template, you cannot tell whether today's output is complete or quietly missing three properties. Save a golden copy while it is known to be right.
Alerting on everything. An alert on every value change trains everyone to ignore the alert. Alert on disappearance and on emptying, not on ordinary content updates.
How to check and fix
A practical setup, in order of return on effort:
- Record a baseline now. For each template, save the current extracted JSON-LD somewhere in version control or a doc. This is the reference everything else compares against.
- Turn on an automated re-crawl. Either a tool that re-audits your connected site and alerts on regressions, or Search Console's Rich Results and Enhancement reports checked on a real schedule, or both.
- Add a scheduled presence check for your highest-value templates if you want a faster signal: fetch raw HTML, extract
application/ld+json, assert it parses and carries the right type. - Make the post-deploy spot check a habit after plugin, theme, performance, and tag changes specifically. View source, one page per template, JavaScript off as a second pass.
- When an alert fires, find the deploy, not the property. The markup is usually a symptom. Ask what shipped around when the number moved, a plugin update, a theme change, a performance setting, and check there first.
Frequently Asked Questions
AI Schema Gen re-crawls your connected site about once a week, compares each run against the last, and emails you when your AI readiness score drops, naming the pages that lost schema. It is the difference between finding out from an alert and finding out from a client. Run a free check at aischemagen.com to see where your site stands now.
Is your site ready for AI?
Get a free readiness score in under a minute. No signup, no card.
Run the free check