Structured data drift: markup that changed without anyone deciding
A cache is invalidated when its source changes. A block of JSON-LD pasted into somebody's codebase is not. The only thing that can notice is a record of what was handed out.

Structured data drift is JSON-LD that has stopped agreeing with the page it describes, because the page changed and the markup did not. It happens because a generated block is a static copy from the moment it is pasted into a codebase. Rename a post, swap its cover image, change its author, and the pasted script keeps announcing the old values. Nothing errors. Nothing is logged. No build warns. The page simply starts contradicting its own markup, and the first sign is usually a rich result that shows a headline nobody on the team recognises.
A cache gets invalidated when the thing behind it changes, because the cache and its source live in the same system. Pasted markup has no such relationship. The generator produced a block, somebody copied it into a template three weeks ago, and the generator has no reach into that template and never will. There is no callback, no expiry and no version negotiation. The block will keep saying what it said until a human replaces it.
That leaves exactly one way to notice: keep a record of what was handed out, and compare it against what the same data would generate today. Market4 writes that record when generate_structured_data produces a block — the URL, the schema type, the version, the handful of values whose drift is both detectable and consequential, and a fingerprint of the whole block. The comparison is what check_structured_data_drift runs, and it names the fields that no longer agree.
Storing the whole emitted block would double the storage and, worse, create a second copy of the markup that can itself disagree with the generator. Market4 stores the individual facts instead, plus a fingerprint that answers the question "did anything at all change?" in one comparison. For an article block those facts are the headline, the URL, the image, the published date, the modified date, the author, the publisher and the description — the values a reader would notice being wrong.
The fingerprint is taken over the serialized text rather than the object, because the text is what the customer holds. Two objects with the same values in a different key order produce different text, and a comparison that ignored that would report agreement between a block on the page and a block nobody has. Using the same serializer the generator uses means the two halves cannot disagree about what "the block" even is.

Breadcrumb markup is the schema type that visibly changes a search result. It needs at least two rungs, three properties per rung, and a trail the page really shows.

Markup does not persuade an answer engine to quote a page. It removes the guesswork about who wrote the page, when, for whom, and where it sits on the site.
Market4 turns one release note into a changelog page, a blog post, a mail-out and a week of social posts — and then tells you which of them brought anyone back.
| What the finding shows | What it means | What to do |
|---|---|---|
| A named field with two values | The pasted copy says one thing and the data says another | Regenerate and replace the block |
| A field present only in the pasted copy | Something was removed, such as a cover image the page no longer shows | Regenerate and replace the block |
| A field present only in the current data | Something was added since the block was handed out | Regenerate and replace the block |
| A changed fingerprint with no named fields | The block changed outside the tracked facts, or the thing it described is gone | Check whether the page still exists before regenerating |
| The date it was first detected | How long the page has been contradicting itself | Use it to prioritise, not to reassure |
The fourth row is the consequential one. A fingerprint change with an empty field list can mean a property outside the tracked set moved, or it can mean the thing the block described no longer exists — a deleted post, an emptied changelog. That second case usually means markup is still pasted on a page that now answers 404, which is a worse problem than a stale headline and looks identical in a report that only counts findings. It is reported as a whole-block change rather than invented into a field list, because a field-by-field comparison genuinely cannot express it.
Market4 stamps the finding with the date the drift was first seen and leaves it there while the drift persists, rather than overwriting it with the date of the most recent check. The interesting number is not when somebody last looked; it is how long the page has been announcing something untrue. A finding first seen eleven weeks ago and a finding first seen this morning need different responses, and a field that records only the last check makes them look the same.
Detecting drift produces a finding; it does not repair anything, because nothing on the generating side can reach a customer's site. The remedy is always the same two steps: regenerate the block for that page, then replace the pasted copy. Regenerating on its own clears the finding, since the ledger now records a fresh handout — but the page is only actually fixed by the paste. That gap is worth knowing about, because a report that goes quiet after step one is not evidence that step two happened.
This is the same discipline that applies to editing a post body: an operation that replaces a whole document leaves nothing behind to reconcile, so the person doing it has to hold the complete new state. Markup pasted into a template is a whole document in exactly that sense, and half-replacing it produces a block that is neither the old one nor the new one.
That last point catches people out repeatedly, because an address that works fine in an anchor tag behaves differently inside a structured data block — see why a relative URL in JSON-LD fails validation.
Structured data drift is the state where a page's JSON-LD no longer matches the page it is on, because the page changed after the markup was generated. It is not a validation error: the block is still syntactically valid and still describes a real schema type. What it describes is simply out of date, which means the page is asserting something to search engines that a visitor looking at the page would not recognise.
Because the markup is a static copy the moment it is pasted into somebody else's codebase, and the generator has no access to that codebase. This is not a limitation to be engineered away; it is the distribution model. The block is handed over, and after that the only honest thing the generating side can do is keep a record of what it handed over and tell you when that record and the current data have diverged.
It means the block differs from what would be generated now, but none of the tracked facts is responsible. Either a property outside the tracked set changed, or the thing being described has been deleted, which often leaves markup pasted on a page that now returns 404. Check whether the page still exists before regenerating, because regenerating markup for a page that is gone solves nothing.
No. Regenerating produces a new block and clears the drift finding against the record, because a fresh handout has been made. The page itself changes only when the new block replaces the old one in the template or the file where it lives. Treating the cleared finding as the completed fix is how a page ends up carrying stale markup with a clean report next to it.
Often enough to catch it before it has been live for months, which for most sites means a scheduled check rather than an occasional one. Drift is produced by ordinary editorial work, not by incidents, so it does not announce itself. A check that runs on a fixed schedule and reports the date each finding was first seen turns a vague worry into a queue with an obvious order.

Publishing writes to a database and tells search engines about an address. Preflighting is the step that asks the server answering that address whether it serves a page. What to check, which findings block an announcement, and why the check must never fail a publish.