What Is JSON-LD and Why Does It Matter?
JSON-LD (JavaScript Object Notation for Linked Data) is the format Google recommends for implementing schema markup on websites. It sits in a <script type="application/ld+json"> tag in your HTML — separate from your visible content — and declares structured facts about your pages, your business, and the relationships between them in a vocabulary defined at Schema.org.
If you have read our parent guide on schema and structured data, you understand why schema matters strategically: it is the bridge between traditional SEO and LLM Optimisation, the machine-readable layer that serves Google, Bing, ChatGPT, Perplexity and AI agents simultaneously. This guide is the practical companion — how to actually write, implement, test and maintain JSON-LD markup that works.
Three things make JSON-LD the right choice over older formats like Microdata and RDFa. First, separation of concerns: JSON-LD lives in a script tag, not tangled into your HTML attributes, so you can add or modify structured data without touching page markup. Second, the graph model: JSON-LD supports @id references that connect entities into a coherent knowledge graph, mirroring how search engines and LLMs organise information internally. Third, Google’s explicit preference: their documentation states “we recommend using JSON-LD for structured data” and their tools are optimised for parsing it. Every code example in this guide uses JSON-LD exclusively.
JSON-LD Syntax: The Fundamentals
Before diving into specific schema types, you need to understand the core syntax that every JSON-LD block shares. A JSON-LD block is valid JSON wrapped in a script tag. Every block needs a @context (always “https://schema.org” for SEO purposes) and a @type (the schema type you are declaring). Properties are key-value pairs defined by Schema.org for each type.
Basic Structure
The simplest JSON-LD block declares a single entity. Here is a minimal Organization declaration:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Your Company Name",
"url": "https://www.example.com"
}
</script>
That is technically valid — but it is far too thin to be useful. A useful Organization block includes your logo, contact information, social profiles, founding date, areas served, and the topics you are authoritative for. The more complete and accurate your structured data, the more confidently search engines and AI systems can represent your business.
The @id Graph Model
The most powerful — and most commonly missed — feature of JSON-LD is the @id property. It assigns a unique identifier to an entity, allowing other schema blocks to reference it. This creates a connected graph rather than isolated fragments.
{
"@type": "Organization",
"@id": "https://www.example.com/#organization",
"name": "Your Company Name"
}
{
"@type": "WebSite",
"@id": "https://www.example.com/#website",
"publisher": { "@id": "https://www.example.com/#organization" }
}
{
"@type": "WebPage",
"@id": "https://www.example.com/about/#webpage",
"isPartOf": { "@id": "https://www.example.com/#website" }
}
Notice how each entity has a stable @id (typically your URL with a hash fragment like #organization, #website, #webpage) and references other entities by their @id. This is how your schema becomes a knowledge graph rather than a collection of disconnected facts. WebPage links to WebSite via isPartOf. WebSite links to Organization via publisher. Article links to WebPage via mainEntityOfPage. Person links to Organization via worksFor. The result is a machine-readable map of your business that search engines and LLMs can traverse — exactly the kind of structured knowledge representation they are designed to process.
Multiple Entities in One Block
You can declare multiple entities in a single JSON-LD block using the @graph property. This is cleaner than having multiple separate script tags and is the pattern used by most SEO plugins including RankMath:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://www.example.com/#organization",
"name": "Your Company Name",
"url": "https://www.example.com"
},
{
"@type": "WebSite",
"@id": "https://www.example.com/#website",
"name": "Your Company Name",
"publisher": { "@id": "https://www.example.com/#organization" }
},
{
"@type": "WebPage",
"@id": "https://www.example.com/about/#webpage",
"isPartOf": { "@id": "https://www.example.com/#website" },
"name": "About Us"
}
]
}
</script>
Google supports both approaches — multiple script tags and single @graph blocks — equally. The key is that your @id references resolve correctly regardless of which approach you use.
Worked Examples: Every Major Schema Type
The following examples are production-ready JSON-LD blocks for each major schema type. They are categorised using the three-tier taxonomy from our parent guide: Entity Foundation, Content Enrichment, and Commercial/Specialist types. Every example includes the properties that matter for both Google rich results and AI visibility — not just the minimum required fields.
Organization / ProfessionalService
The most important schema type for any business. This declares your core entity identity — who you are, where you operate, what you are authoritative for, and how to reach you.
{
"@type": "ProfessionalService",
"@id": "https://www.example.com/#organization",
"name": "Your Company Name",
"legalName": "Your Company Ltd",
"url": "https://www.example.com",
"logo": {
"@type": "ImageObject",
"url": "https://www.example.com/logo.png",
"width": 300,
"height": 60
},
"image": "https://www.example.com/office-photo.jpg",
"description": "Brief description of what your business does.",
"foundingDate": "2005",
"founder": { "@id": "https://www.example.com/#founder" },
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Business Street",
"addressLocality": "Southampton",
"addressRegion": "Hampshire",
"postalCode": "SO14 1AA",
"addressCountry": "GB"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 50.9097,
"longitude": -1.4044
},
"telephone": "+44-XXXX-XXXXXX",
"email": "info@example.com",
"areaServed": [
{ "@type": "Country", "name": "United Kingdom" },
{ "@type": "Country", "name": "United States" }
],
"knowsAbout": [
"Search Engine Optimisation",
"LLM Optimisation",
"Schema Markup",
"Entity SEO"
],
"sameAs": [
"https://www.linkedin.com/company/your-company/",
"https://x.com/yourcompany",
"https://www.facebook.com/yourcompany"
]
}
Key properties for AI visibility: knowsAbout explicitly tells AI systems what topics your entity is authoritative for — this directly influences whether LLMs consider you a relevant source. sameAs links to your verified profiles help AI systems resolve your entity across platforms. areaServed helps AI agents filter businesses by geography when processing location-specific queries. Most implementations we audit are missing at least two of these three properties.
Person (Author / Founder)
Establishes individual entity authority. Critical for E-E-A-T signals — Google and LLMs evaluate the expertise of content creators, not just websites.
{
"@type": "Person",
"@id": "https://www.example.com/#founder",
"name": "Jane Smith",
"jobTitle": "Founder & SEO Consultant",
"worksFor": { "@id": "https://www.example.com/#organization" },
"url": "https://www.example.com/about/",
"description": "SEO consultant with 20+ years of experience specialising in technical SEO and structured data.",
"knowsAbout": [
"Search Engine Optimisation",
"JSON-LD Structured Data",
"Entity SEO"
],
"sameAs": [
"https://www.linkedin.com/in/janesmith/",
"https://x.com/janesmith"
]
}
The worksFor property creates a bidirectional link — the Person works for the Organization, and the Organization’s founder property points back to the Person. This kind of cross-referencing strengthens both entities in the graph.
FAQPage
The single highest-value schema type for AI visibility. Provides explicit question-answer pairs that LLMs can extract and cite with maximum confidence.
{
"@type": "FAQPage",
"@id": "https://www.example.com/services/#faq",
"mainEntityOfPage": {
"@id": "https://www.example.com/services/#webpage"
},
"mainEntity": [
{
"@type": "Question",
"name": "How long does SEO take to show results?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Most businesses see measurable improvements within 3-6 months. Competitive industries may take 6-12 months for significant movement on high-value terms. We set realistic timelines during the audit phase based on your specific market and starting position."
}
},
{
"@type": "Question",
"name": "Do you offer ongoing SEO retainers?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. After the initial foundation phase, we offer monthly retainers covering content strategy, technical monitoring, link building, and performance reporting. Retainers start from £2,000 per month depending on scope."
}
}
]
}
Critical rules: every question and answer in the schema must be visible on the page (hidden FAQ content violates Google guidelines). Keep answers between 50 and 200 words — long enough to be authoritative, short enough to be extractable. Use natural-language questions that match how users actually ask. The mainEntityOfPage reference connects the FAQ to the page’s WebPage node, keeping it in the entity graph rather than floating disconnected.
HowTo
Marks up step-by-step processes. Heavily favoured by AI systems answering procedural queries because the sequential structure matches their output format.
{
"@type": "HowTo",
"@id": "https://www.example.com/guide/#howto",
"name": "How to Audit Your Schema Markup",
"description": "A practical process for evaluating your structured data implementation.",
"totalTime": "PT45M",
"step": [
{
"@type": "HowToStep",
"name": "Run the Rich Results Test",
"text": "Go to search.google.com/test/rich-results and enter your homepage URL. Document which schema types are detected and any validation errors.",
"url": "https://www.example.com/guide/#step-1"
},
{
"@type": "HowToStep",
"name": "Check for duplicate schema blocks",
"text": "View page source and search for application/ld+json. Count the blocks. Multiple Organization blocks from different sources means duplication.",
"url": "https://www.example.com/guide/#step-2"
}
]
}
The totalTime property uses ISO 8601 duration format: PT45M means 45 minutes, PT1H30M means 1 hour 30 minutes. Each step should be a single, clear action — not a paragraph of explanation. If a step requires tools or materials, declare those with the tool and supply properties.
Article / BlogPosting
Establishes content provenance — who wrote this, when, for which publication. Essential for E-E-A-T and AI author attribution.
{
"@type": "Article",
"@id": "https://www.example.com/blog/post-title/#article",
"headline": "Your Article Title",
"description": "Brief description of the article content.",
"datePublished": "2026-02-18T10:00:00+00:00",
"dateModified": "2026-02-18T14:30:00+00:00",
"wordCount": 2500,
"author": { "@id": "https://www.example.com/#founder" },
"publisher": { "@id": "https://www.example.com/#organization" },
"mainEntityOfPage": {
"@id": "https://www.example.com/blog/post-title/#webpage"
},
"image": {
"@type": "ImageObject",
"url": "https://www.example.com/images/featured.jpg",
"width": 1200,
"height": 630
}
}
Note how author and publisher reference @id values from other schema blocks rather than repeating the full entity data. This is the graph model in action — define each entity once, reference it everywhere. Also note datePublished and dateModified use full ISO 8601 format with timezone offset. LLMs use these timestamps when evaluating content freshness.
VideoObject
Declares video metadata. The key AI-visibility property is transcript — it makes your video content directly parseable by AI systems without them needing to process the video file.
{
"@type": "VideoObject",
"@id": "https://www.example.com/guide/#video",
"name": "How to Implement Schema Markup",
"description": "Step-by-step walkthrough of JSON-LD implementation.",
"thumbnailUrl": "https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg",
"uploadDate": "2026-01-15T10:00:00+00:00",
"duration": "PT8M30S",
"contentUrl": "https://www.youtube.com/watch?v=VIDEO_ID",
"embedUrl": "https://www.youtube.com/embed/VIDEO_ID",
"transcript": "Full transcript of the video content goes here..."
}
Duration uses ISO 8601 format: PT8M30S means 8 minutes 30 seconds. thumbnailUrl is a required property — VideoObject without it triggers validation errors. If you embed YouTube videos, our SEO Strategy theme extracts title, thumbnail URL and duration automatically from the embed URL and compiles the VideoObject schema for you.
Service
Declares what your business offers. Particularly valuable for AI Agent Optimisation — agents evaluating vendors need structured service descriptions to compare businesses efficiently.
{
"@type": "Service",
"@id": "https://www.example.com/services/seo/#service",
"name": "SEO Consulting",
"description": "Comprehensive SEO strategy, implementation and monitoring.",
"provider": { "@id": "https://www.example.com/#organization" },
"areaServed": {
"@type": "Country",
"name": "United Kingdom"
},
"serviceType": "Search Engine Optimisation",
"offers": {
"@type": "Offer",
"price": "600",
"priceCurrency": "GBP",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": "600",
"priceCurrency": "GBP",
"unitText": "day"
}
}
}
The provider property links back to your Organization entity — this is the connection that allows AI systems to associate services with the business offering them. offers with pricing information is increasingly important for AI agents making purchasing recommendations. Businesses that provide pricing context in structured data are more likely to be included in agent-generated shortlists because the agent has the data it needs to make comparisons.
Where to Place JSON-LD in Your HTML
Google accepts JSON-LD in both the <head> and <body> of your HTML. Both locations work equally well for validation and rich results. The practical choice depends on your CMS and workflow.
For WordPress sites, the cleanest approach is outputting JSON-LD via wp_head (an action hook that injects content into the HTML head section). This is what SEO plugins like RankMath use, and it is the approach our theme uses for custom schema compilation. The advantage is that structured data is generated programmatically from defined fields rather than being pasted as static HTML blocks — which means it stays synchronised with your actual content and cannot be accidentally deleted by content editors.
If you do not have programmatic control over your site’s head, you can place JSON-LD in a Custom HTML block within your page content, or use a plugin like Insert Headers and Footers to inject it. For static sites, include it in your page templates. The placement matters far less than the accuracy and completeness of what is inside the block.
WordPress Implementation Patterns
WordPress is the most common platform we implement JSON-LD on, and it presents specific challenges and opportunities. The biggest challenge is schema collision — multiple plugins and themes outputting conflicting structured data. The opportunity is programmatic generation from WordPress’s structured content fields.
SEO Plugin Schema (RankMath, Yoast, AIOSEO)
Modern SEO plugins generate a comprehensive @graph block automatically, typically including Organization, WebSite, WebPage, BreadcrumbList, and Article nodes. This provides decent baseline coverage — but it is generic. Plugin-generated schema uses global settings for Organization data and derives page-level schema from post metadata. For many sites, this is sufficient for basic coverage.
The problems arise when you need more than basic coverage: FAQPage schema for specific pages, HowTo for guide content, VideoObject for embedded videos, Service for service pages, or custom knowsAbout properties on your Organization entity. Adding these via custom code introduces the risk of duplication and conflict with the plugin’s output.
De-duplication Strategy
The solution is establishing a clear ownership model. Either the plugin owns schema output and you extend it via the plugin’s filters (RankMath provides rank_math/json_ld for this), or your theme owns schema output and you suppress the plugin’s generation for specific types. Our approach uses WordPress filters to remove plugin-generated FAQ and HowTo nodes when our theme is compiling its own from structured meta fields — preventing duplication while still letting the plugin handle the base Organization, WebSite, and WebPage graph.
The practical test: view your page source, search for application/ld+json, and count the blocks. If you see more than one Organization entity, you have a problem. If you see FAQPage in both the plugin’s graph and a separate custom block, you have duplication. Fix these before adding any new schema types.
Security: Hardened JSON Encoding
When generating JSON-LD from user-editable content (post titles, meta descriptions, FAQ answers), there is a cross-site scripting (XSS) risk if the content contains HTML or script tags. Standard json_encode() in PHP will pass through angle brackets, meaning a malicious FAQ answer containing <script> tags could execute in the browser.
The fix is using PHP’s hex encoding flags: json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT). The JSON_HEX_TAG flag converts < and > to their Unicode equivalents, preventing script injection while keeping the JSON-LD valid for search engines. This is a detail most schema guides miss — but it matters for any site where content editors can modify schema-connected fields.
Testing and Validation Tools
No schema implementation is complete without validation. Here are the tools you need, in order of importance:
Google Rich Results Test
URL: search.google.com/test/rich-results
The primary validation tool. Enter a URL or paste code directly. It shows which schema types Google detected, whether they are eligible for rich results, and any errors or warnings. Use this for every page after implementing or modifying schema. Key things to check: are all expected types detected? Are required properties present and valid? Are there warnings about recommended properties you could add? This is the tool that tells you what Google actually sees — not what you think you published.
Schema.org Validator
URL: validator.schema.org
Validates against the full Schema.org vocabulary, not just Google-supported types. Useful for catching syntax errors and validating schema types that Google doesn’t generate rich results for but that AI systems still parse. If your JSON-LD passes here but fails in the Rich Results Test, the issue is usually Google-specific requirements (like missing required properties for a particular rich result type).
Google Search Console Enhancements
After deployment, Search Console’s Enhancements section is your ongoing monitoring dashboard. It shows which rich result types Google has detected across your site, how many pages have valid markup, and which pages have errors or warnings. Check this weekly — schema can break silently when content is updated, plugins are upgraded, or themes are modified.
Manual Source Code Review
Automated tools miss duplication issues. View your page source, search for application/ld+json, and manually verify: one Organization entity only, no conflicting property values between blocks, @id references resolving correctly, and no empty required fields. This ten-minute manual check catches problems that automated validators do not flag.
Common JSON-LD Mistakes and How to Fix Them
After auditing hundreds of sites, these are the mistakes we see most often — and they are almost always silent failures. The schema looks correct in the code, but search engines and AI systems either ignore it or misinterpret it.
Malformed JSON
A single missing comma, unclosed bracket, or unescaped quotation mark breaks the entire JSON-LD block. The browser does not show an error. Google silently ignores it. The fix: paste your JSON-LD into a JSON validator (jsonlint.com) before deploying. If you are generating JSON dynamically, test with varied content including special characters, apostrophes, quotation marks and HTML entities in your source data.
Duplicate Entity Nodes
Two Organization blocks with different addresses. Two FAQPage blocks from plugin and custom code. Two Article blocks from theme and page builder. Google may use either one unpredictably. The fix: establish a single source of truth. Audit every plugin, theme component and custom code snippet that outputs JSON-LD. Remove duplicates at source, or use filters to suppress one.
Orphaned @id References
Your Article references { "@id": "https://example.com/#author" } but no Person entity with that @id exists anywhere in your schema. The reference points to nothing. The fix: every @id reference must resolve to an entity declared somewhere in your site’s schema. If you reference an author, that Person entity must exist — either on the same page or on another page Google has crawled.
Content-Schema Mismatch
Your FAQPage schema declares questions that do not appear visibly on the page. Your Product schema lists a price that differs from the visible price. Google explicitly penalises content-schema mismatches — structured data must accurately reflect visible page content. The fix: never use schema to declare information that is not also visible to users on the page.
Empty Required Properties
FAQPage with "mainEntity": [] (no questions). VideoObject without thumbnailUrl. Article without author. Empty or missing required properties are worse than having no schema at all — they signal to Google that your structured data is broken. The fix: validate before deploying, and set up conditional logic so schema types only output when their required data is actually populated.
JSON-LD for AI Visibility: Beyond Rich Results
Most JSON-LD guides focus exclusively on Google rich results. That is an increasingly incomplete picture. In 2026, the primary value of well-implemented JSON-LD is not rich snippets — it is AI visibility across every system that reads your site.
When ChatGPT browses your website, it parses your JSON-LD. When Perplexity retrieves your page as a citation source, it extracts structured data. When an AI agent evaluates your business for a vendor comparison, it reads your Organization, Service and Review schema. When Google AI Overviews synthesise information from multiple sources, structured data provides the high-confidence facts they cite.
This means your JSON-LD strategy should prioritise properties that serve AI systems, not just properties that trigger rich results. knowsAbout on your Organization entity tells AI what you are authoritative for. transcript on VideoObject makes video content machine-parseable. Service schema with pricing helps AI agents compare your offerings. FAQPage provides ready-made answers in the exact format LLMs generate. These properties may never trigger a visible rich result in Google — but they directly influence whether AI systems cite, recommend and accurately represent your business.
This is the insight behind our positioning of schema as the bridge between SEO and AI. JSON-LD is not an SEO tactic. It is the machine-readable API for your business information — and every AI system that touches your website is calling that API.