We Rebuilt Our Own Site So AI Search Could Read It. Here's What Was Broken.

Nikhai Jaysen · September 11, 2026

Our blog had schema markup on every post. Crawlers were seeing none of it. The bug is common, invisible in every browser test, and worth checking on your own site today.

We sell AI-optimised websites, so it is uncomfortable to report that our own blog had a structured data bug across all forty-nine posts. It is also the most useful thing we can write this month, because the bug is common, it is invisible in every check most people run, and it may well be on your site right now.

What we thought was true

Our blog template included BlogPosting schema. Headline, author, publisher, dates, image, keywords — properly formed, and visible in the browser inspector on any post.

Everything looked correct. Open a post, inspect the page, find the ld+json block. Done.

What was actually true

The schema was defined inside the page component, which meant the framework injected it when the page mounted in a browser. Our site pre-renders each route to static HTML, and that pre-rendering step wrote the title, description, canonical, and social tags — but not the structured data, because the structured data was never part of the HTML. It only came into existence once JavaScript ran.

The consequence: a crawler reading the file we serve found no BlogPosting at all. Across all forty-nine posts, the count was zero. Breadcrumb markup was also zero, because it did not exist anywhere.

This is the nasty class of bug where every check you would normally run passes. The browser shows it. The page looks right. Only fetching the raw response reveals it, and almost nobody does that on their own site.

Two more things we found while fixing it

Once we started reading the raw HTML rather than the rendered page, two more problems surfaced immediately.

The dates were not valid dates

The schema was passing our display string — the same text shown to readers, in the format September 11, 2026 — straight into datePublished. Schema.org expects ISO 8601. A human-readable date there is invalid, and an invalid date in a required field can invalidate the item.

The fix is a one-line conversion, with one trap worth flagging. The obvious approach of parsing the date and calling toISOString is wrong for any timezone ahead of UTC. Parsing a date-only string gives local midnight, and converting that to UTC rolls it back to the previous day — so every post silently publishes one day early. We read the components back through the local accessors instead, and verified all forty-nine converted dates against their display dates before shipping.

Every page shared one social image

Each post has its own image, and every page was serving the same site-wide default in its og:image tag. The pre-renderer rewrote several meta tags but had no rule for that one, so the post-specific image never made it into the HTML.

The practical effect was that every link anyone shared, from any post, looked identical.

What we changed

We moved structured data generation out of the page component and into the pre-renderer, so it is written into the head of the static HTML that crawlers actually receive. One source rather than two that can disagree.

The output now carries BlogPosting on every post, BreadcrumbList on every nested route, and FAQPage wherever a page has a question-and-answer section. We also added the per-page social image rewrite, and converted the dates properly.

The counts moved from zero of forty-nine to forty-nine of forty-nine on article markup, and from one shared social image to forty-nine distinct ones.

The FAQ change was structural, not cosmetic

Adding FAQPage markup meant deciding where the questions live. Writing them as HTML inside the article body would have been quicker, but then the schema would need a second copy of the same text, and two copies drift.

So questions moved into structured data on the post itself, and one definition now feeds three outputs: the visible FAQ section, the markdown version of the page we serve to agents, and the FAQPage schema. The first post we built this way was the customer success automation piece. That is worth doing early, because retrofitting it across a large archive is considerably more annoying than building it in.

Check yours in about a minute

This is worth doing on your own site before you finish reading anything else about it.

Fetch the raw HTML of a page rather than viewing it — curl, or view-source in the browser. Search the response for ld+json. If it is not there but it appears in your inspector, your structured data is client-side and the crawlers reading your pages are not seeing it.

Then check any date fields for ISO format, and open a page's og:image value to confirm it is that page's image rather than a site default.

The honest part

We do not yet know what this is worth. It shipped this month, and anyone who tells you they can attribute a ranking or citation change to a schema fix within weeks is guessing.

What we can say is that the previous state was definitively broken: crawlers received nothing, which is not a grey area. Fixing a zero is worth doing regardless of what the curve looks like afterwards, and we will write up the numbers when there are enough of them to mean something.

We build AI-optimised websites and audit existing ones for exactly this class of problem — the things that pass every visual check and fail the only reader that matters. Get in touch if you would like us to look at yours.

Frequently Asked Questions

Why does client-side structured data often not work?

Because many crawlers and most AI answer engines read the HTML the server returns and do not execute JavaScript, or execute it inconsistently. Schema injected by a framework after the page mounts in a browser is simply absent from the document those fetchers see.

How do you check whether your structured data is actually visible?

Fetch the raw HTML rather than viewing the page. Use curl or view-source and search for the ld+json block. If it appears in your browser's inspector but not in the raw response, it is being added client-side and crawlers are not getting it.

Does datePublished have to be in a specific format?

Yes. Schema.org expects ISO 8601, so 2026-09-11 rather than a display string like September 11, 2026. A human-readable date in that field is treated as invalid, which can invalidate the whole item even though the page looks correct.

What is the difference between SEO and optimising for AI search?

They overlap heavily in fundamentals, but AI answer engines lean harder on being able to parse a page cleanly without rendering it, and on content structured as direct question-and-answer. Clean server-rendered markup and explicit FAQ sections matter more than they did for classical ranking alone.