DataBA-D-2026-03
Structured-data census 2026 (JSON-LD / Microdata / RDFa, four sectors)
One row per domain for 2,000 domains across four documented frames — universities, news, e-commerce, and U.S. federal government (500 each) — recording the structured-data signals found in each homepage's raw, server-delivered HTML: JSON-LD presence and block counts, the top-level schema.org types declared, per-type presence flags, and Microdata/RDFa presence.
Collection window: 2026-07-10 (news, e-commerce, government homepages); universities reuse 2026-07-09 homepage bytes · License: CC-BY-4.0 · Published with BA-D-2026-03: Structured data on the homepage: a JSON-LD census of 2,000 domains across four sectors
Schema
| Column | Type | Description |
|---|---|---|
| domain | string | The registrable domain (eTLD+1) that was fetched, as listed in the sector frame; lowercased, computed with the Public Suffix List. The (sector, domain) pair matches the crawler-access-2026 dataset row-for-row. |
| sector | string (enum) | The frame the domain belongs to: universities, news, ecommerce, or government. Frames are disjoint; 2,000 rows, 2,000 distinct domains. |
| country | string (ISO 3166-1 alpha-2) or empty | Country code carried by the frame source. Empty where the source supplies none (e.g. gTLD e-commerce domains, whose country is not inferable from the ccTLD). |
| http_status | integer or empty | HTTP status of the homepage (GET /) response, read from the stored response headers. Empty when the fetch produced no response (fetch_error is set). |
| fetch_error | string (enum) or empty | Transport-level failure class when no HTTP response was received: dns, timeout, tls, or other. Empty when a response was received (http_status is populated). |
| analyzable | boolean | true when the stored response is HTTP 200 with a non-empty body — the rule that governs whether the structured-data fields below are populated. false rows (non-200, empty body, or fetch_error) carry fetch status only. |
| page_bytes | integer | Byte length of the stored response body. On a non-analyzable domain this is the bytes of whatever was received (0 when there was no response, or e.g. the bytes of a 403 challenge page). |
| has_jsonld | boolean or empty | true when the raw HTML carries at least one <script> block whose lower-cased type attribute contains 'ld+json' (HTML character references in the attribute are decoded, so 'application/ld+json' counts). A block-presence test; it does not require the block to be valid JSON. Empty when the domain is non-analyzable. JSON-LD injected by client-side JavaScript is not present in the raw HTML and is not counted. |
| block_count | integer or empty | Number of JSON-LD <script> blocks found in the raw HTML. 0 on an analyzable homepage with no JSON-LD; empty when non-analyzable. |
| invalid_block_count | integer or empty | Number of those blocks whose inner text does not parse with a standard JSON parser as-is, with no repair (e.g. a CMS that HTML-escaped the quotes inside the script). A deliberate lower bound on validity — the state a raw JSON-LD consumer encounters. Empty when non-analyzable. |
| distinct_types | string (semicolon-separated) or empty | The sorted set of normalized top-level @type values declared across all valid JSON-LD blocks on the homepage, joined by ';'. Normalization strips a schema.org URL or compact-IRI prefix and preserves case (https://schema.org/Organization -> Organization). Only top-level and @graph-level nodes are counted, not types nested inside another entity; each type appears once per domain. Empty when non-analyzable, and also empty on an analyzable homepage that declares no JSON-LD types. |
| has_microdata | boolean or empty | true when an itemscope attribute appears on any start tag in the raw HTML (Microdata presence). Presence only — no item is extracted, no itemtype parsed, no validity judged. Empty when non-analyzable. |
| has_rdfa | boolean or empty | true when a typeof attribute appears on any start tag in the raw HTML (RDFa presence). Presence only. Empty when non-analyzable. |
| has_searchaction_sitelinks | boolean or empty | The one deep-scan flag: true when a SearchAction @type appears anywhere in a parsed JSON-LD block (the Google sitelinks-searchbox construct, always nested under WebSite.potentialAction, never at top level). Empty when non-analyzable. |
| has_potential_action | boolean or empty | true when a potentialAction key appears anywhere in a parsed JSON-LD block. A superset context for has_searchaction_sitelinks. Empty when non-analyzable. |
| has_organization | boolean or empty | true when 'Organization' is among the normalized top-level types. Exact normalized-name match; a subtype (e.g. Corporation, NewsMediaOrganization) does not set it. Same convention for every has_* type flag below. Empty when non-analyzable. |
| has_website | boolean or empty | true when 'WebSite' is a normalized top-level type. |
| has_webpage | boolean or empty | true when 'WebPage' is a normalized top-level type. |
| has_breadcrumblist | boolean or empty | true when 'BreadcrumbList' is a normalized top-level type. |
| has_article_or_newsarticle | boolean or empty | true when 'Article' OR 'NewsArticle' is a normalized top-level type. A subtype such as BlogPosting does not set it. |
| has_product | boolean or empty | true when 'Product' is a normalized top-level type. Product markup is typically on product detail pages, not the homepage this census reads. |
| has_offer | boolean or empty | true when 'Offer' is a normalized top-level type (an Offer nested inside a Product is not counted unless it is also top-level). |
| has_faqpage | boolean or empty | true when 'FAQPage' is a normalized top-level type. |
| has_collegeoruniversity | boolean or empty | true when 'CollegeOrUniversity' is a normalized top-level type (a university's self-declaration of kind). |
| has_governmentorganization | boolean or empty | true when 'GovernmentOrganization' is a normalized top-level type. |
| has_localbusiness | boolean or empty | true when 'LocalBusiness' is a normalized top-level type. A subtype such as Store does not set it. |
| final_url | string or empty | The final URL after redirects for the homepage request. Empty when there was no response. |
| content_type | string or empty | The Content-Type response header of the homepage, read from the stored headers. |
| analyzed_at | string (ISO 8601 timestamp) | UTC timestamp at which the structured-data analysis row was produced. Note this is the analysis time, not the homepage fetch time; the fetch windows are 2026-07-09 (universities) and 2026-07-10 (the other three sectors), stated in collectionWindow. |
Known limitations
- Frame, not population. Each sector is a fully enumerated top-500 frame from a specific public source (College Scorecard + Hipolabs; palewire news-homepages; UT1 shopping blacklist; CISA federal .gov registry), ordered by traffic rank (enrollment for the U.S. universities). Figures are exact counts of these frames, not estimates for 'all universities', 'all news sites', or any sector at large. The frames are identical to the crawler-access-2026 dataset.
- Raw HTML only. Every structured-data signal is read from the server-delivered HTML before any JavaScript executes — the bytes a non-rendering crawler receives. JSON-LD, Microdata, or RDFa injected by client-side script (tag manager, hydration payload, setAttribute/dangerouslySetInnerHTML) is invisible by design. has_jsonld=false means 'no JSON-LD in the raw HTML', not 'the site has no JSON-LD'; the undercount direction is known and one-sided. The size of the raw-versus-rendered gap is measured separately in BA-D-2026-05.
- Two collection windows. University homepage bytes are reused unchanged from the 2026-07-09 crawler census; news, e-commerce, and government homepages were fetched 2026-07-10. A cross-sector comparison that places the university column beside the other three compares a 2026-07-09 snapshot to a 2026-07-10 one. Homepages change without notice; treat the data as perishable.
- Homepage only, and deployment only. One page per domain (the homepage) is read, and only the presence of markup is recorded — not its quality. The dataset does not assess entity consistency across a site's pages or languages, does not diff marked-up facts against the visible text, and does not validate markup against any schema.org shape beyond recording whether each JSON-LD block parses as JSON. These are exactly the BL-2 criteria (BA-C-1) the census does not test, so deployment is an upper bound on BL-2 attainment, not a placement at it.
- Validity is a deliberate lower bound. invalid_block_count counts blocks that fail a standard JSON parse as-is; the census does not entity-decode-then-retry, because a raw JSON-LD consumer does not. A block that would parse after un-escaping is still counted invalid here.
- Microdata and RDFa are presence-only. has_microdata and has_rdfa record only whether an itemscope / typeof attribute appears anywhere in the raw HTML. No item is extracted, no itemtype/vocab parsed, no validity judged — coarse 'is any of this syntax present' signals, recorded for completeness of the structured-data landscape.
- Undeterminable is present as rows with empty structured-data fields. Non-analyzable domains (non-200, empty body, or a transport failure — a 403 challenge page, a DNS failure) carry empty has_jsonld / distinct_types / has_* fields; their structured-data state could not be read and must not be counted as 'has none'. Non-response is heavy in two frames (e-commerce 267 of 500 analyzable, government 329 of 500).
- The dataset's measurements (structured-data signals) are independently collected facts keyed by domain. The frame membership lists derive from upstream sources with their own licenses (UT1 shopping list CC BY-SA; palewire news-homepages open source; official U.S. government data), credited in the parent census's references.
FAQ
- Why are some structured-data columns empty?
- The row is non-analyzable — the homepage request returned a non-200 status, an empty body, or a transport error (DNS, timeout, TLS), so no HTML could be read. Those rows are kept as a first-class 'undeterminable' result but their has_jsonld, distinct_types, block counts, and has_* fields are left empty rather than guessed. Only analyzable rows (HTTP 200 with a body) carry populated structured-data fields.
- What does has_jsonld = false mean, exactly?
- No JSON-LD <script> block was present in the raw, server-delivered HTML. It is not a claim that the site has no JSON-LD: markup injected by client-side JavaScript (a tag manager, a React hydration payload, a setAttribute call) is invisible to this measurement by design, because the research question is what a non-rendering crawler can read. The direction of the resulting undercount is known and one-sided.
- Does a JSON-LD row mean the site is more visible in AI assistants?
- No. This dataset records deployment — whether markup is present in the homepage HTML — and nothing about consumption or visibility. The documented state, reviewed in BA-W-2026-03, is that schema.org markup is consumed by traditional search (for understanding and rich results) but is a documented negative for AI features: Google's AI-features documentation states no special structured data is needed for AI Overviews or AI Mode, and OpenAI's crawler documentation is silent on structured data. Presence here is not evidence of AI visibility.
- How is distinct_types delimited and deduplicated?
- It is a ';'-separated (semicolon) sorted set of the normalized top-level @type values a domain declares across all its valid JSON-LD blocks. Each type appears at most once per domain, and only top-level or @graph-level nodes are counted — a type nested deep inside another entity is not listed. No schema.org type name contains a semicolon or comma, so the delimiter is unambiguous.
- Can I compare sectors directly?
- The measurement method is identical across sectors, so the columns mean the same thing everywhere. But the four frames are built from different sources and orderings, and the university column was collected one day earlier (2026-07-09) than the other three (2026-07-10). Compare method-to-method over each frame's stated analyzable denominator (universities 429, news 413, e-commerce 267, government 329), not as sector-wide rates over 500.
- What is the license, and how should this be cited?
- The dataset is released under CC-BY-4.0. Cite the parent census BA-D-2026-03 and this datasheet, and state the collection windows (2026-07-09 for universities, 2026-07-10 for the other three sectors), since the data is a near-single-day snapshot.
Changelog
- 2026 — Initial release.
How to cite
Barkhausen AI (2026). Structured-data census 2026 (JSON-LD / Microdata / RDFa, four sectors) (dataset). https://barkhausen.ai/data/structured-data-2026/
BibTeX
@techreport{BA-D-2026-03,
author = {{Barkhausen AI}},
title = {Structured-data census 2026 (JSON-LD / Microdata / RDFa, four sectors) (dataset)},
institution = {Barkhausen AI},
year = {2026},
url = {https://barkhausen.ai/data/structured-data-2026/}
}Published under the Creative Commons Attribution 4.0 International (CC-BY-4.0).