JSON-LD
JSON-LD (JSON for Linked Data) is the W3C-standard serialization format for embedding structured data in HTML pages — a JSON object wrapped in a script tag that declares schema.org vocabulary describing the page's content and entities.
Definition
JSON-LD is a JSON-based serialization of linked data, designed to be embedded in HTML pages as a discrete <script type="application/ld+json"> block in the head or body. Unlike microdata or RDFa, JSON-LD doesn't intermingle with the page's visible content — the structured-data layer lives separately from the rendered HTML.
Basic shape
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "What JSON-LD is",
"datePublished": "2026-05-22",
"author": {
"@type": "Organization",
"name": "Citare",
"url": "https://citare.ai"
}
}
</script>
The @context field declares the vocabulary (almost always schema.org). The @type field declares what kind of thing this block describes. The remaining fields are properties of that type.
Why JSON-LD over microdata or RDFa
- Separation of concerns. Schema metadata lives in a script tag, page content lives in normal HTML. Edits to one don't break the other.
- Easier validation. A single JSON parse confirms the block is well-formed. Microdata bugs (missing closing tags, mistyped itemprop names) are harder to catch.
- Google's preferred format. Documented preference in Search Central since 2017. Tools mature around it.
- Multiple blocks per page. A page can have an Organization schema, an Article schema, a FAQPage schema, and a BreadcrumbList schema as separate script tags without conflict.
@graph composite pattern
When a page has multiple related entities (e.g., an Article and its Author and the Publishing Organization), the @graph wrapper lets them reference each other via @id URIs:
{
"@context": "https://schema.org",
"@graph": [
{ "@type": "Organization", "@id": "https://citare.ai#org", "name": "Citare" },
{ "@type": "Person", "@id": "https://citare.ai#author-ravi", "name": "Ravi" },
{ "@type": "Article", "author": { "@id": "https://citare.ai#author-ravi" }, "publisher": { "@id": "https://citare.ai#org" } }
]
}
This pattern avoids duplicating entity definitions across pages and lets crawlers consolidate signals properly.
Critical escaping pitfall
If a JSON-LD answer string contains the literal characters </, the browser interprets it as the closing </script> tag and terminates the JSON block early. Fix: escape every </ to <\/ before serializing.
Citare's marketing build does this automatically via serializeSchema() in src/lib/marketing/schema.ts. Manual implementations need the same step.
Validation tools
- Google Rich Results Test — validates against Google's specific feature requirements
- Schema.org Validator — generic schema.org validation
- JSON-LD Playground — graph visualization and processing
See /tools/json-ld-inspector for the free inspector tool.
Frequently asked
Where should JSON-LD blocks be placed in the HTML — head or body?
Either works. Google recommends head for performance (parses before render), but body placement is valid and common. Multiple blocks per page is also fine — Google merges them when interpreting the structured data.
How do I escape JSON-LD content that includes HTML tags like '<head>'?
Replace every occurrence of '</' with '<\\/' before serializing. Without this, a string like 'inside the <head> tag' will accidentally close the script block when the browser encounters '</'. The literal output should be the backslash-forward-slash, which the browser unescapes back to /.
Can the same page have multiple @type values?
Yes, two ways. One: separate <script> blocks for each type. Two: a single @graph block with multiple entities. The @graph approach is cleaner when entities reference each other via @id.
Related
Stop guessing where you rank in AI search
Citare measures citation rate and share of voice across ChatGPT, Google AI Overview, Gemini, Claude, and Perplexity — weekly, for your priority queries. Free forever tier.