BlogFindings
Schema markup validator: 117 of 612 home pages with JSON-LD carried a defect, and on 7 not one block parsed
Lantad requested the home page of all 1,419 hostnames in this repository's committed corpus on 21 September 2026 and read the raw bytes with no JavaScript executed. 1,072 answered HTTP 200 with HTML, and 612 of those carried at least one JSON-LD block, 1,143 blocks between them. 117 of the 612 carried a defect, 16 blocks never parsed as JSON, and on 7 sites not one block on the page did.
So this run validated rather than counted. Every JSON-LD block on every reachable corpus home page went through four gates in order: does it parse, does it carry a context that resolves, does its type exist in the schema.org vocabulary, and does the entity hold the properties that type is supposed to hold. The first three gates involve nobody's opinion. The fourth involves whose rules you apply, and that turns out to be the most useful thing this measurement has to say.
In short
- Of the 612 corpus home pages carrying JSON-LD when Lantad read them on 21 September 2026, 117 carried at least one defect a schema markup validator can name, and 35 of those need no judgement at all because the JSON, the context or the type simply does not resolve.
- 16 of the 1,143 JSON-LD blocks did not parse as JSON, and on 7 sites, among them agoda.com, danskebank.dk, ns.nl and langhamhotels.com, no block on the page parsed, so the structured data those pages publish reaches nothing.
- Nine sites declared a type absent from the schema.org vocabulary at release 30.1, dated 2026-09-16, including four that wrote Website where schema.org defines WebSite and two that wrote organization in lower case.
- 30 of the 612 sites shipped an HTML character reference inside a parsed JSON-LD string value, so company names arrived carrying a literal ampersand entity, which JSON-LD 1.1 section 7.2 says will remain escaped after processing.
- Defect rates split by how a page is built rather than by how large the organisation is: 29 of 52 Wix and Squarespace sites and 17 of 35 WordPress sites carried one, against none of 27 single page app startups, none of 10 Framer sites and none of 8 documentation sites.
| Stage | Sites | What happened |
|---|---|---|
| Hostnames asked | 1,419 | The committed corpus, an editorial frame rather than a random draw |
| Never returned a status | 34 | 19 failed DNS resolution, 13 timed out or aborted, 2 failed in the client |
| Refused this crawler | 217 | Answered HTTP 403 to LantadBot |
| Answered some other status | 96 | 50 of 503, 24 of 429, 9 of 202, 4 of 404, and 9 others |
| Answered 200 with HTML | 1,072 | The reachable set |
| Carried no JSON-LD | 460 | Nothing on the page to validate |
| Carried JSON-LD | 612 | 1,143 blocks, the denominator for everything below |
| Carried at least one defect | 117 | 19.1 percent of the sites that published markup |
What does a schema markup validator actually check?
A validator is four different checks wearing one name, and they do not carry equal authority. Separating them is the difference between a report a developer can act on and a list of complaints.
The first check is the JSON grammar. RFC 8259, the JSON specification published in December 2017, says that within a string all Unicode characters may be placed inside the quotation marks "except for the characters that MUST be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F)". Its grammar defines exactly nine escape sequences and no production for comments at all. A block that breaks either rule is not slightly wrong. It is not JSON, and every consumer that meets it gets nothing from it.
The second check is the JSON-LD document itself. The JSON-LD 1.1 specification, a W3C Recommendation dated 16 July 2020, defines how a context maps the keys in a document onto an actual vocabulary. Without a context that resolves, the token Organization is a string rather than a type, because nothing in the document says which Organization is meant.
The third check is the vocabulary. schema.org publishes a dated release, and the current one when this scan ran was release 30.1, dated 2026-09-16 and described as adding vocabulary for EU Digital Product Passports and common eCommerce product data. A type either appears in that release or it does not, and the answer is a fact rather than a preference.
The fourth check is requirements: which properties a type has to carry before the markup says anything useful. That one has no single answer, and this post keeps it separate from the other three for exactly that reason. Lantad's own table, an input to the score the methodology describes, is a scoring decision rather than a standard, and Google's guidance is a different rule again, aimed at rich results rather than at meaning. The vocabulary underneath the whole argument is set out under structured data.
Flow: JSON-LD block in raw HTML to Gate 1: parses as JSON; Gate 1: parses as JSON (parses) to Gate 2: context resolves; Gate 1: parses as JSON (fails) to 16 blocks failed to parse; Gate 2: context resolves (resolves) to Gate 3: type in schema.org 30.1; Gate 2: context resolves (does not) to 4 sites: context wrong or absent; Gate 3: type in schema.org 30.1 (exists) to Gate 4: required properties; Gate 3: type in schema.org 30.1 (does not) to 14 sites: no type, or unknown type; Gate 4: required properties (complete) to No defect named; Gate 4: required properties (incomplete) to 60 sites: a property missing.
The 16 blocks that never parsed, and the 7 sites where nothing did
16 of the 1,143 blocks failed JSON.parse outright. That is 1.4 percent, which sounds survivable until you ask which sites they sat on. On 7 of the 16 affected sites there was no second block to fall back on, so agoda.com, danskebank.dk, ns.nl, langhamhotels.com, bokksu.com, trinityschoolofmedicine.org and unrivaledsportsco.com published structured data on 21 September 2026 that no consumer could read. To a machine those pages are indistinguishable from the 460 that carried no markup at all.
The causes divide into six shapes and none of them is exotic. Five blocks carried a raw line feed inside a string literal, which RFC 8259 forbids: westashevillefamilydentistry.com ends its own name with one, and fullsteamcrossfit.com writes a week of opening hours as a single string with a newline between each day, which is the same property this blog found only 2 of 172 home pages carried in a machine readable form. Four blocks carried a JavaScript comment, which JSON has no syntax for. Two of those four are template placeholders that reached production intact, bokksu.com shipping "telephone": "Service Phone Number" followed by a comment reading "Please fill in the service phone number".
Three blocks held two objects with no array around them, so the parser reached the end of the first value and found more text waiting. Two were empty script elements containing nothing at all. One, langhamhotels.com, wrote a property with no value, "latitude": followed directly by a comma. One, hku.hk, used the escape \x27 for an apostrophe, which is valid in JavaScript source and is not among the nine escapes JSON defines.
A milder version of the same thing sits just past the parser. Three blocks on two sites, nordlayer.com and nab.com.au, parse correctly and contain an empty array, so the markup is well formed and holds nothing. Those are not parse failures and they are counted separately, but the outcome for a reader is identical.
What unites all of them is that none is a subtle modelling error. Each is the kind of thing a parser rejects in under a millisecond, and each survived to production because nothing in the publishing path ever ran a parser over the output. That is the same failure mode counted when 232 of 1,059 robots.txt files carried a defect: a text file assembled by a template and never read back by the thing that has to read it. Seeing the raw bytes a crawler receives, rather than the rendered page, is the whole point of looking at what a bot is sent.
JSON.parse on each ld+json block
- trinityschoolofmedicine.org block begins /* SCHEMA CODE */ comment
- bokksu.com "telephone": "Service Phone Number", // Please fill in... comment
- websiteportland.com "telephone": "+1-207-228-1121", // main practice phone comment
- ns.nl block begins //<![CDATA[ comment
- westashevillefamilydentistry.com "name": "West Asheville Family Dentistry\n" control char
- fullsteamcrossfit.com "openingHours": "Sunday: 8:30 AM - 11 AM\nMonday: ..." control char
- unrivaledsportsco.com, elevatedestateplanning.law, icmr.gov.in newline in a string control char
- danskebank.dk, unifonic.com, downtownnotarytoronto.com second object, no array trailing text
- langhamhotels.com "latitude": , missing value
- hku.hk "the territory\x27s oldest institute" bad escape
- agoda.com, erstegroup.com <script type="application/ld+json"></script> empty
Types and contexts that do not resolve to anything
A block can parse perfectly and still say nothing, because the words in it have to resolve against a vocabulary before they mean a type. Two gates cover that, and 14 sites failed one of them.
Nine sites declared an @type absent from schema.org at release 30.1. Four wrote Website, where the schema.org type is WebSite with a capital S, among them japantimes.co.jp, kayak.com, ssense.com and webnames.ca. The japantimes.co.jp case is the instructive one, because the node is otherwise complete and carefully built: an @id ending in #organization, a name of The Japan Times, a logo, and four sameAs profiles. One capital letter is the whole difference between an identified publisher and an unrecognised string, which is what entity confidence exists to describe.
Two sites wrote organization in lower case, misa.vn and plaid.com, and germany.travel wrote webPage. JSON-LD is case sensitive and schema.org answers HTTP 404 for all three spellings, checked directly on 21 September 2026. The last two unknown types are plausible words the vocabulary has never contained: pressmodernmassage.com declares MassageTherapist and plannedparenthood.org declares NonprofitOrganization, both 404 at schema.org, though NGO resolves.
Five more sites carry an entity with no type at all. Two of those, elastic.co and ubs.com, use the key "type" rather than "@type", which reduces a whole page of markup to an untyped bag of properties. On elastic.co the page's only block is four keys long, and the type declaration is the one key that does not count. That syntax level detail decides the outcome more often than the modelling does, which this blog found before when the syntax a page chose decided its schema score.
Contexts were healthier. Of 1,396 block roots, 1,014 used "https://schema.org" and 291 used "http://schema.org", both of which resolve, with 70 and 15 more using those forms with a trailing slash. Three used "http://www.schema.org", a hostname schema.org does not serve its vocabulary from, and one block carried no @context at all. The www form appears on evolvehealing.net, cancer.org and spain.info, and evolvehealing.net is worth a note: six of its seven blocks are fine, and the seventh, the one declaring the Organization, is the one with the wrong host.
| Declared type | Sites | Named examples | What schema.org defines |
|---|---|---|---|
| Website | 4 | japantimes.co.jp, kayak.com, ssense.com, webnames.ca | WebSite, with a capital S |
| organization | 2 | misa.vn, plaid.com | Organization, capitalised |
| webPage | 1 | germany.travel | WebPage, capitalised |
| MassageTherapist | 1 | pressmodernmassage.com | No such type at any release |
| NonprofitOrganization | 1 | plannedparenthood.org | NGO resolves, this spelling does not |
The ampersand that survives: 30 sites shipped an entity reference inside a value
This is the defect class a JSON parser cannot catch, because the block is valid JSON and the value is a valid string. It is just the wrong string.
A script element is raw text. The HTML Standard's element taxonomy, at html.spec.whatwg.org/multipage/syntax.html, lists six kinds of element and puts script and style among the raw text elements, separately from textarea and title, which it calls escapable raw text elements. The difference that second name carries is the whole issue: a character reference inside a raw text element is not decoded, so an ampersand entity written inside a JSON-LD block stays five characters long all the way into the parsed value. JSON-LD 1.1 says as much in section 7.2, which lists the five escapes an author may need and then notes that "the content will remain escaped after processing through the JSON-LD API".
30 of the 612 sites, 34 blocks in total, published a value in that state. Most are company names with an ampersand in them, which is how the class became visible at all: a barbershop whose schema name is Cuts & Bruises, a masonry firm arriving as B&D Associates, LLC, and a tax practice as Robert Hall & Associates. Apostrophes behave the same way, so nasa.gov carries America's space agency inside its description and inserm.fr opens its own description with L'Institut national. mskcc.org has a ranking from U.S. News & World Report inside the text of an entity.
Two cases go past cosmetic. unilag.edu.ng escapes a fragment of HTML into a description, which begins <p> Join Kes, so the value is markup pretending to be prose. And where the entity lands inside a URL rather than a name, the URL breaks: ten sites publish an image, map or page address whose query string still carries the entity, one of them reading ?s=96&d=mm&r=g, which is not the address anybody meant to give.
None of this stops a page being indexed and none of it shows in a browser, which is precisely why it persists. It matters for the same reason the prose and the markup have to agree, which this blog measured when it found one page in five carried a date in its schema marks: the value in the markup is the machine readable claim about the entity, and a claim that a company is called B&D Associates is a claim about a company that does not exist. Which syntax carries the claim matters less than whether the claim survives, as the split between JSON-LD, microdata and RDFa showed on the same corpus, and both feed the same AI visibility question.
| Site | Property | Value as delivered |
|---|---|---|
| cutsandbruisesbarbershop.com | name | Cuts & Bruises |
| bdmasonry.net | name | B&D Associates, LLC |
| roberthalltaxes.com | name | Robert Hall & Associates |
| nasa.gov | description | ... from America's space agency |
| inserm.fr | description | L'Institut national ... |
| mskcc.org | text | ... by U.S. News & World Report |
| unilag.edu.ng | description | <p> Join Kes ... |
| appalshop.org | url | ...?s=96&d=mm&r=g |
Required properties, and whose rule decides they are required
60 of the 612 sites failed the fourth gate, which makes it the largest defect class and the one to treat most carefully. A missing property is only a defect relative to a table of requirements, and there is no single table.
Lantad's is small and explicit. SCHEMA_REQUIREMENTS in core/src/schema.ts asks an Organization for a name and a url, a Product for a name, an Article for a headline, an FAQPage for a mainEntity and a BreadcrumbList for an itemListElement, with LocalBusiness and Corporation checked against the Organization row. That is a scoring decision this scanner made, not a standard anybody published, so calling a missing url a defect is an assertion about what identification takes rather than a finding about the web.
Google publishes a different rule for a different purpose. Its structured data general guidelines, last updated 2026-07-10 UTC, put it under completeness: "Specify all required properties listed in the documentation for your specific rich result type", and warn that items missing required properties are not eligible for rich results. That rule is scoped per rich result type and says nothing about types with no rich result attached, which is most of what this corpus publishes.
With that caveat stated, the shape of the 84 failures is consistent. 78 of them are Organization nodes: 40 carrying neither a name nor a url, 25 with a name and no url, 13 with a url and no name. Four are BreadcrumbList nodes with no itemListElement, which is an empty breadcrumb, and two are Articles without a headline.
The near misses show intent, which is what makes them worth naming. 20 blocks carry a legalName and no name anywhere in the document, a site that has told a machine its registered company name in a property most consumers will not read. gentrydentistry.com is the clean example: its Organization node carries a legalName, a full address, an email, a telephone and five sameAs links, and neither of the two properties Lantad asks for. bohobodysugaring.ca goes the other way and publishes "address": "" on a LocalBusiness, an empty string where the address should be. That is the same near-miss pattern found when 103 of 385 pages with JSON-LD named no organization, 27 of which were one property short.
How much any of this moves a citation is a separate question this measurement does not answer, and the honest reading elsewhere is that markup is one input among several: one audit put structured data third among the factors it tested. A single home page is also a thin sample of a site's templates, which is what checking more than one URL is for.
Which kinds of site published markup that does not validate
The corpus is stratified, so the 117 can be attributed, and the pattern is the one this blog keeps meeting: the publishing tool decides, and the site owner never sees the decision being made.
29 of the 52 Wix and Squarespace sites that published JSON-LD carried a defect, 55.8 percent, and 17 of 35 WordPress sites did, 48.6 percent. Those two strata are small business sites where the markup comes from a theme or a plugin and the operator has no view of the output. They are also where the hand written block appears, which is where the template comments and the raw newlines live: four of the sixteen parse failures sit in those two strata alone, against two in Webflow and three in travel.
At the other end, three strata recorded no defect at all: none of the 27 single page app startups, none of the 10 Framer sites and none of the 8 documentation sites that published JSON-LD. The pattern is not that those teams are more careful. It is that their markup is serialised by a build step from a data structure, so a trailing comma or an unescaped newline cannot survive the serialiser, and the type string is written once in a component rather than retyped per page. That is the same platform effect this blog found when 141 of 382 home pages carried no structured data at all, and when none of 69 Wix robots.txt files named an AI crawler: the default decides, and the default is invisible.
Three limits belong here rather than in a footnote. 217 hostnames refused this crawler with HTTP 403 and 34 never resolved, so 251 sites are absent from every figure above and they are not absent at random. Nothing here was rendered, because JavaScript was never executed, so markup injected after load was not seen, and a client injected block is a different thing from one in the raw HTML, which is why this blog has measured that hydration JSON scores the same as no text. A validator reading the first response reads what a crawler that does not render receives, the condition several of the crawlers in the directory publish for themselves.
One thing this scan deliberately did not count as a defect: a relative value in a url property, which 14 sites publish. The JSON-LD specification resolves a relative reference against the base IRI of the document, so "url": "/" is legitimate even though it reads like an error. Counting it would have added those 14 sites to the headline, and would have been a validator applying its own preference as a rule, which is exactly what the four gates above exist to separate. On that note, and to be plain about it: there is no standalone schema markup validator among the free tools on this site, and this post is not a soft launch of one.
| Stratum | With a defect | Published JSON-LD | Rate |
|---|---|---|---|
| Wix and Squarespace | 29 | 52 | 55.8% |
| WordPress | 17 | 35 | 48.6% |
| Finance | 12 | 54 | 22.2% |
| Healthcare | 9 | 42 | 21.4% |
| SaaS | 16 | 88 | 18.2% |
| Media and local | 5 | 28 | 17.9% |
| Travel | 7 | 39 | 17.9% |
| Government | 5 | 29 | 17.2% |
| News | 6 | 54 | 11.1% |
| Webflow | 2 | 21 | 9.5% |
| Education | 3 | 32 | 9.4% |
| Bubble, no-code | 1 | 12 | 8.3% |
| Ecommerce | 3 | 40 | 7.5% |
| Shopify storefronts | 1 | 15 | 6.7% |
| SaaS marketing sites | 1 | 26 | 3.8% |
| Framer | 0 | 10 | 0.0% |
| Single page app startups | 0 | 27 | 0.0% |
| Static documentation | 0 | 8 | 0.0% |
Lantad
Published .
Counting structured data is easy, and this blog has done it several times. Counting whether the structured data works is a different measurement, and it is the one that decides whether any of the counting mattered. A page can carry three JSON-LD blocks, pass every survey of adoption, and hand a consumer nothing at all, because the bytes between the script tags are not valid JSON, or because the type on the node is a word no vocabulary defines.
Common questions
What does a schema markup validator check first?
Whether the block is JSON at all. On this corpus that gate caught 16 of 1,143 blocks on 21 September 2026, and on seven sites it caught every block the page had, so the markup reached no consumer. Only after a block parses is there anything to say about its context, its type or its properties.
Does invalid JSON-LD stop an AI answer engine citing a page?
Nothing measured here says so, and this post does not claim it. What the measurement establishes is narrower and still worth acting on: a block that fails to parse conveys nothing to any consumer that reads it, so whatever the markup was meant to add is not being added. How much weight answer engines place on structured data in the first place is a separate question.
Why check against a schema.org release number rather than just schema.org?
Because the vocabulary changes. Release 30.1, dated 2026-09-16, added terms that did not exist a week earlier, so a type unknown today can be defined tomorrow and a validator that does not state its release is making an undated claim. All nine unknown types found here are misspellings or words the vocabulary has never held, each checked one at a time, so none of them is a release lag.
How many home pages carried structured data at all?
612 of the 1,072 corpus home pages that answered HTTP 200 with HTML on 21 September 2026, which is 57.1 percent, and they carried 1,143 blocks between them. 376 of the 612 published a single block, 114 published two and 14 published six or more.
See what AI can read on your site
Run a free scan and get a graded report of exactly what AI crawlers can and cannot read, with ranked fixes.