ModelRefs / Structured Data for Technical Content: What JSON-LD Does

Structured Data for Technical Content: What JSON-LD Does

What Google and Bing actually say about JSON-LD and AI answers, which schema types fit technical articles, a checker script, and what it found on this site.

What structured data is

Structured data is machine-readable markup that describes a page. The format Google recommends is JSON-LD, a block of JSON inside a script tag that names the page type and its properties.

The type might be an article, a FAQ or a breadcrumb trail, and the properties are things like headline, author and dates.

It does not change what a human sees, but it gives a crawler an explicit statement of what the page is, so the crawler does not have to infer it from layout.

What the engines actually say

The useful question is not whether schema is good, but what each engine has actually said about schema and AI answers. Here is what could be verified.

EngineWhat it saysStrength of the source
Google (AI Overviews, AI Mode)No additional technical requirements, and no special markup or machine-readable files needed. A page must be indexed and eligible to show in Search with a snippet.Google's own documentation
Google (general structured data)Markup must be a true representation of the page content, JSON-LD is recommended, and valid markup does not guarantee a rich result.Google's own documentation
Microsoft BingReported from SMX Munich in March 2025: schema markup helps Microsoft's LLMs understand content.Secondhand, via a trade publication owned by an SEO vendor
OpenAI, Perplexity, GeminiNot established in the sources reviewed.No primary source found

Google's AI features documentation is the clearest statement available. It says there is "no special schema.org structured data that you need to add" to appear in these features, and that there are no additional technical requirements.

The same page does list structured data under ordinary SEO best practices. It recommends "making sure your structured data matches the visible text on the page", which is a general recommendation rather than an AI-specific requirement.

The Bing item deserves care, for two separate reasons. Search Engine Land's report relays a LinkedIn summary of a talk by Microsoft's Fabrice Canel, rather than a verbatim quote, though Canel confirmed the details in the comments.

The second reason is disclosure: Search Engine Land is owned by Semrush, which sells SEO tooling, and that is a commercial interest worth naming when the finding favours doing more SEO work.

The report says schema helps the LLMs "understand" content. It does not claim schema improves rankings or citations, and it states plainly that whether Gemini, OpenAI or Perplexity use schema is unclear.

The careful reading is that helping a model understand a page and making a model cite the page are different claims, and only the first has any support.

What changed in 2026

Two entries in Google's documentation changelog matter for anyone who built an AI-visibility plan around markup.

  • FAQ rich results ended. The 8 May 2026 entry announced the deprecation, stating the feature would no longer appear in Google Search from 7 May 2026. The documentation was removed on 15 June 2026. FAQPage remains valid schema.org vocabulary, but Google no longer shows it as a rich result.
  • llms.txt is not needed. On 15 June 2026 Google clarified that these files are not needed for Google Search, and that they will not negatively or positively impact visibility or rankings. Note the wording: Google says the files are not needed, which is narrower than saying they are never read.

The pattern is that tactics sold as AI shortcuts, whether a special file or a special markup type, have been explicitly declined by the largest search engine. That does not make them useless for every engine, but it does remove the assumption that they are required.

Which schema types fit technical content

Pick types because they describe your page accurately, not because they are rumoured to attract citations.

  • TechArticle. Schema.org defines it as a technical article such as a how-to guide or specification. It adds two properties that suit developer content: dependencies, defined as prerequisites needed to fulfil steps in the article, and proficiencyLevel, with expected values Beginner or Expert. The schema.org page carrying these is the development version, so details may change.
  • BreadcrumbList. Describes where the page sits in the site hierarchy, and is cheap to generate from the pillar and slug.
  • FAQPage. Valid for pages with a visible question-and-answer section. With the Google rich result gone, its remaining value is clarity for other consumers, and it carries a maintenance duty: the markup must keep matching the visible text.
  • Organization or author details. Useful for stating who publishes the page. Keep them factual.

A TechArticle block for a tutorial looks like this:

{
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "headline": "Build a Custom MCP Server",
  "description": "Step-by-step tutorial for building and testing an MCP server.",
  "proficiencyLevel": "Beginner",
  "dependencies": "Node.js 20 or later, a code editor",
  "author": { "@type": "Organization", "name": "ModelRefs Editorial" },
  "publisher": { "@type": "Organization", "name": "ModelRefs", "url": "https://modelrefs.com" },
  "datePublished": "2026-07-17",
  "dateModified": "2026-07-17",
  "mainEntityOfPage": "https://modelrefs.com/tutorials/build-a-custom-mcp-server"
}

Generate this from the same source that produces the visible byline and dates, so the two cannot drift apart.

Rules that keep markup safe

Google's general guidelines set the limits, and they are the same rules that protect you from a manual action.

  • Mark up only what readers can see. The guidelines say plainly: do not mark up content that is not visible to readers of the page.
  • Keep it accurate. The guideline is that structured data "must be a true representation of the page content". Do not add ratings, reviews or claims the page does not show.
  • Keep time-sensitive fields current. A dateModified that never changes misleads, and so does one that changes without a real edit.
  • Prefer JSON-LD. Google lists three supported formats and labels JSON-LD as recommended.
  • Do not expect a display guarantee. Google states it does not guarantee that structured data will show up in search results.

The consequence of breaking the rules is limited but real. A page under a structured data manual action loses eligibility to appear as a rich result, and Google states this does not affect how the page ranks in web search.

Verify what a crawler sees

Correct markup is worthless if the crawler never receives it. That is the failure described in how AI answer engines cite developer content, where content existed for browsers and was missing from the HTML a non-JavaScript fetch returned.

The script below fetches a page without executing JavaScript, finds every JSON-LD block, checks that each parses, and for FAQPage blocks confirms that the questions and the start of each answer appear in the visible text. It uses only the Python standard library.

"""Fetch a page the way a non-JS crawler does and audit its JSON-LD.

Usage: python audit_jsonld.py <url-or-local-html-file>
Standard library only. No JavaScript is executed.
"""
import json
import re
import sys
import urllib.request
from html.parser import HTMLParser


class Scan(HTMLParser):
    def __init__(self):
        super().__init__()
        self.in_ld = False
        self.skip = 0
        self.ld_blocks = []
        self.text = []

    def handle_starttag(self, tag, attrs):
        if tag == "script" and dict(attrs).get("type") == "application/ld+json":
            self.in_ld = True
            self.ld_blocks.append("")
        elif tag in ("script", "style"):
            self.skip += 1

    def handle_endtag(self, tag):
        if tag == "script" and self.in_ld:
            self.in_ld = False
        elif tag in ("script", "style") and self.skip:
            self.skip -= 1

    def handle_data(self, data):
        if self.in_ld:
            self.ld_blocks[-1] += data
        elif not self.skip:
            self.text.append(data)


def norm(s):
    return re.sub(r"s+", " ", s).strip().lower()


def load(src):
    if src.startswith("http"):
        req = urllib.request.Request(src, headers={"User-Agent": "jsonld-audit/1.0"})
        return urllib.request.urlopen(req, timeout=20).read().decode("utf-8", "replace")
    with open(src, encoding="utf-8") as f:
        return f.read()


def main(src):
    scan = Scan()
    scan.feed(load(src))
    visible = norm(" ".join(scan.text))
    print(f"JSON-LD blocks found: {len(scan.ld_blocks)}")
    problems = 0
    for i, raw in enumerate(scan.ld_blocks, 1):
        try:
            data = json.loads(raw)
        except json.JSONDecodeError as e:
            print(f"  [{i}] INVALID JSON: {e}")
            problems += 1
            continue
        kind = data.get("@type")
        print(f"  [{i}] @type = {kind}")
        if kind == "FAQPage":
            for q in data.get("mainEntity", []):
                question = norm(q.get("name", ""))
                answer = norm(q.get("acceptedAnswer", {}).get("text", ""))
                q_ok = question in visible
                a_ok = answer[:60] in visible
                if not (q_ok and a_ok):
                    problems += 1
                print(f"      question visible: {q_ok} | answer visible: {a_ok} | {question[:50]}")
    print("RESULT:", "OK" if problems == 0 and scan.ld_blocks else f"{problems} problem(s)")


if __name__ == "__main__":
    main(sys.argv[1])

What ModelRefs emits, and what the script found

Running the script against this site is more useful than a synthetic fixture, so that is what we did, targeting the prerendered page for the world models explainer.

JSON-LD blocks found: 7
  [1] @type = Organization
  [2] @type = WebSite
  [3] @type = Article
  [4] @type = BreadcrumbList
  [5] @type = FAQPage
      question visible: True | answer visible: True | are world models going to replace large language m
      question visible: True | answer visible: True | what is the difference between a world model and a
      question visible: True | answer visible: True | is v-jepa 2 open source?
      question visible: True | answer visible: True | why does yann lecun argue language models cannot r
      question visible: True | answer visible: True | can i use a world model today in a product i am bu
RESULT: OK

Two things are worth reading out of that output, and only one of them is good news.

The good news is that all five FAQ entries pass, meaning every question and the start of every answer appears in the HTML a non-JavaScript crawler receives. That is the check that matters most.

The bad news is in the type list, where Article and BreadcrumbList each appear twice, at blocks 3 and 4 and again at 6 and 7. The page therefore describes itself as two articles sitting in two breadcrumb trails.

That is a duplication we had not noticed until this script printed it, and it is a real defect rather than a cosmetic one. It is now on our open list and recorded here rather than quietly fixed, because this guide is about checking your own output.

The type list also corrects a common assumption, because ModelRefs does not emit TechArticle on its articles. Registry-driven articles, including this guide, emit Article, BreadcrumbList and FAQPage. TechArticle is reserved for tutorials, workflows and methodologies, which is the right split: a decision guide is not a how-to.

For the failure case, the same script was run against a client-rendered shell that carries FAQ markup but no visible text at fetch time:

JSON-LD blocks found: 1
  [1] @type = FAQPage
      question visible: False | answer visible: False | is v-jepa 2 open source?
RESULT: 1 problem(s)

Both runs happened before this guide was published. The script checks structure and visible-text agreement only: it does not validate against schema.org, and it cannot tell you whether any engine will use the markup.

The ModelRefs citation test

This section describes a test that has not been run, so no results exist and none are implied.

The question: does adding or removing JSON-LD change how often ModelRefs pages are cited by AI answer engines, when the visible text is identical?

An earlier draft of this guide listed a blocker. The visible Quick Answer box rendered client-side only, so non-JavaScript crawlers never received it, and running the test then would have confounded markup with missing content.

That blocker is now cleared, because the quick answer moved into the article registry, which the prerenderer reads when it builds the static page. The text now appears in the HTML a crawler receives, so the test can proceed.

Planned design:

  • Groups. Split comparable articles into two groups matched by pillar and publication age. One group keeps its JSON-LD, the other has it removed, and visible text stays identical.
  • Measurement. Run a fixed panel of prompts against the major answer engines on a regular schedule, recording whether modelrefs.com is cited and in what position. Also track crawler requests in server logs, plus impressions in Bing Webmaster Tools and Search Console.
  • Duration. At least one full freshness cycle of 90 days, using the same prompts throughout.
  • Reporting. We will publish the result whichever way it falls, including a null result.

Limits stated up front. With only a few dozen articles, the test can show a large effect or none at all, but it cannot resolve a small one.

Citation behaviour is also volatile, by the admission of the data providers who track it, so one 90-day window is a snapshot rather than a trend. A result for this site also says little about a site with different authority and traffic.

The follow-up article will be written only once that data exists.

Sources

Google Search Central, AI features and your website. No special markup required, and eligibility is indexing plus snippet eligibility, accessed 18 Oct 2026.

Google Search Central, documentation updates. The FAQ rich result deprecation on 8 May 2026, its documentation removal on 15 June 2026, and the llms.txt clarification of the same date, accessed 18 Oct 2026.

Google Search Central, General structured data guidelines. JSON-LD as the recommended format, true-representation and visible-content rules, the absence of a display guarantee, and manual action consequences, accessed 18 Oct 2026.

Search Engine Land, Microsoft Bing/Copilot use schema for its LLMs (Barry Schwartz, 20 March 2025). A secondhand report of a Bing statement, flagged as such, from a publication owned by Semrush, accessed 18 Oct 2026.

Schema.org, TechArticle. The type definition and the dependencies and proficiencyLevel properties, read on the development version of the site, accessed 18 Oct 2026.

Methodology: every statement about what Google says is taken from Google's own documentation or changelog, read on 18 Oct 2026. The Bing statement is reported as secondhand, because the only source found is a news summary of a conference talk. The audit script was run against a live prerendered ModelRefs page and a client-rendered shell, and both outputs are shown as produced. The citation test in this guide is a plan, not a result.

Frequently asked questions

Does schema markup get you cited by ChatGPT, Perplexity or Google AI Overviews?

No source reviewed shows that. Google says no special markup is required for AI Overviews or AI Mode. Bing is reported to say schema helps its LLMs understand content, which is not the same as increasing citations.

Is FAQPage schema still worth adding?

Google no longer shows FAQ rich results, which its changelog records as ending on 7 May 2026. The markup remains valid, and it costs little if it is generated from the visible FAQ text. Its AI-citation value is unproven, so do not add it for that reason alone.

Do I need an llms.txt file?

Google states that llms.txt files are not needed for Google Search and will not negatively or positively impact visibility or rankings. Other services may read them, but we found no primary source showing a citation benefit.

What is the most common structured data mistake on technical sites?

Markup that exists in the source but not in the HTML a crawler receives, or FAQ markup that no longer matches the visible answers. The script in this guide checks both.

Which schema type should a tutorial use?

TechArticle, with proficiencyLevel and dependencies filled in where they apply, plus BreadcrumbList. Note that ModelRefs itself emits Article rather than TechArticle on registry-driven articles, and reserves TechArticle for tutorials, workflows and methodologies.