JSON-LD implementation: from messy to structured in one day
- Most websites unnecessarily duplicate their organization schema. This can lead to inconsistencies between pages and unclear signals to search engines.
- Site-wide script defines three entities once. Website, Organization, and Person only need to be specified in one place.
- Page-level JSON-LD remains limited and clear. WebPage + Service/BlogPosting + optional BreadcrumbList and FAQ.
- A stable @id strategy prevents linking errors. Use [URL]#webpage, [URL]#service, [URL]#blogpost as a consistent fragment pattern.
- 10 common mistakes that can break rich results. From self-referencing loops to trailing commas and smart quotes in JSON strings.
- Implementation requires thorough planning and testing. Add site-wide script, modify page template, validate, and gradually roll out.
Many websites have a JSON-LD implementation that has slowly become a patchwork quilt. Organization schema on every page. Inconsistent @ids. Service nodes mixed with BlogPosting where they don't belong. FAQs that refer to content that is not on the page.
The result: validation errors in Search Console, structured data that sends unclear signals, and markup that is difficult to maintain.
This article explains how to implement JSON-LD in a way that scales and remains consistent. Structured data is not a replacement for technical SEO, but it is an essential building block for making your page intent clear to search engines.
Why almost all JSON-LD implementations become messy
JSON-LD implementations usually start well. A developer adds Organization schema to the homepage. Then comes a product page, which also gets Organization schema. And a Service node. Then come blog articles, which get Organization + BlogPosting. Before you know it, the same Organization definition is on hundreds of pages, but with subtle differences because they were added at different times.
5 concrete symptoms of drift:
Organization chart with different values. On page A, the logo is 200x200px, on page B it is 400x400px, and on page C it is missing entirely.
Inconsistent @id fragments. Some pages use #organization, others use #company, and still others do not use @id.
Mixed types without logic. A contact page has both Service and AboutPage and ContactPage schemas.
FAQ content that does not exist. The FAQ schema contains questions that are not on the page because they have been copied from a template.
Self-referencing loops. WebPage.mainEntityOfPage refers to itself instead of to the Service or BlogPosting.
These problems arise because there is no clear distinction between what belongs site-wide (always the same) and what belongs page-level (unique per page). For those conducting a thorough technical SEO audit, this is often one of the first technical bottlenecks that comes to light.
Pageswith structured data receive 30% more clicks than standard search results.
The core principles that solve everything
Google recommends JSON-LD because it is easier to implement and maintain than Microdata or RDFa. But only if you do it the right way.
Five principles:
1. One page-level JSON-LD script per page
Place all page-specific structured data in one place <script type="application/ld+json"> block with a @graph array. Not four separate scripts for WebPage, Service, BreadcrumbList, and FAQ. One script, one graph, all nodes included.
2. Stable @id strategy
Each node receives a unique @id based on the canonical page URL plus a fragment. For example: https://example.com/seo#webpage, https://example.com/seo#service, https://example.com/blog/artikel#blogpostUse this pattern consistently throughout the entire site.
3. Strict separation: site-wide vs. page-level
Site-wide entities (Website, Organization, Person) are defined once in a separate script that is loaded on every page. Page-level entities (WebPage, Service, BlogPosting, BreadcrumbList, FAQPage) are located in the page-specific script and refer to the site-wide entities via their @id.
4. Match URLs exactly with canonical
Use the exact same URL as your canonical URL on the page. If your canonical tag <link rel="canonical" href="https://example.com/over-ons"> is, then use exactly https://example.com/over-ons in your @id and url properties. Match www/non-www and trailing slashes exactly with your canonical strategy.
5. Preserve unless invalid (when cleaning up existing implementations)
If you are sanitizing an existing JSON-LD implementation: do not change content unless it is factually incorrect. Does your BlogPosting.description have 180 characters? Leave it as it is. Is there a working image URL? Leave it as it is. Only change what is actually wrong. This prevents unintended ranking impact during cleanup. For new implementations: start immediately with correct data according to the templates below.
Structureddata does not improve your website's ranking. It is used to display search functions. Use it if your pages are suitable for these functions.
What belongs site-wide (and why)
Site-wide entities are data that are the same for the entire website. You define these once in a script that is loaded on every page, usually via your CMS template or header include.
Which entities belong site-wide:
Website (one website, one Website entity)
Contains: name, URL, publisher (refers to Organization @id), inLanguage, optional potentialAction for site search
Organization (one company, one Organization)
Contains: name, url, logo, sameAs (social profiles), optional contactPoint, address, areaServed
Person (consistent author or founder, optional)
Contains: name, url, sameAs (LinkedIn, Twitter), worksFor (refers to Organization @id)
What should NOT be site-wide:
Service nodes (unique per service page)
Blog Posting (unique per article)
BreadcrumbList (unique per page)
FAQPage (unique per page where FAQ is located)
Product (unique per product)
Minimal vs. expanded guidance:
Start minimal. Website name, URL, publisher. Organization name, URL, logo. That's enough. Only add more if you can validate that it is correct and relevant.
Example: joint contactPoint Only applicable if you actually have a separate customer service number. Add address Only if you have a physical location that is relevant to your business. Not because it seems "complete."
Overview table: what belongs where
Site-wide JSON-LD template (copy-paste)
Place this script in the <head> from each page, or via a global template include in your CMS.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "WebSite",
"@id": "https://example.com/#website",
"url": "https://example.com",
"name": "[WEBSITE_NAME]",
"inLanguage": "nl-BE",
"publisher": {
"@id": "https://example.com/#organization"
}
},
{
"@type": "Organization",
"@id": "https://example.com/#organization",
"name": "[ORGANIZATION_NAME]",
"url": "https://example.com",
"logo": {
"@type": "ImageObject",
"url": "[LOGO_URL]"
},
"sameAs": [
"[SOCIAL_URL_1]",
"[SOCIAL_URL_2]",
"[SOCIAL_URL_3]"
]
},
{
"@type": "Person",
"@id": "https://example.com/#founder",
"name": "[FOUNDER_NAME]",
"url": "https://example.com/over-ons",
"sameAs": [
"[LINKEDIN_URL]"
],
"worksFor": {
"@id": "https://example.com/#organization"
}
}
]
}
</script>
Replace the placeholders:
[WEBSITE_NAME]: "ClickForest" or your company name[ORGANIZATION_NAME]: Formal company name[LOGO_URL]: Full URL to your logo (min. 112x112px, preferably square)[SOCIAL_URL_1/2/3]LinkedIn, Facebook, Instagram URLs[FOUNDER_NAME]: Name of the founder/CEO, if applicable[LINKEDIN_URL]: Founder's personal LinkedIn profile
Note about Person: Only add this block if you have a personal brand component in your business (founder-led, thought leadership). Otherwise, remove this entire block.
“Ithelps their content to be understood. Whether it's details about their company, the services they offer, or the content they invest so much time in.”
Page-level JSON-LD for regular pages (services, locations, etc.)
For regular pages (services, about us, contact, location pages), use a limited node set.
Minimum baseline checklist:
WebPage (always required)
Service (only if it is truly a service page)
BreadcrumbList (optional, only if you implement breadcrumbs consistently)
FAQPage (optional, only if FAQ is actually on page)
Linking rules:
WebPage.isPartOf refers to site-wide WebSite @id
WebPage.mainEntity refers to Service @id
Service provider refers to site-wide Organization @id
Service.mainEntityOfPage refers to WebPage @id
Linking cheat sheet by page type
Canonical template for service page:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "WebPage",
"@id": "https://example.com/seo#webpage",
"url": "https://example.com/seo",
"name": "SEO diensten",
"description": "SEO optimalisatie voor bedrijven in België.",
"isPartOf": {
"@id": "https://example.com/#website"
},
"mainEntity": {
"@id": "https://example.com/seo#service"
}
},
{
"@type": "Service",
"@id": "https://example.com/seo#service",
"serviceType": "SEO optimalisatie",
"name": "SEO diensten",
"description": "Technische SEO, content optimalisatie en linkbuilding.",
"provider": {
"@id": "https://example.com/#organization"
},
"areaServed": {
"@type": "Country",
"name": "België"
},
"mainEntityOfPage": {
"@id": "https://example.com/seo#webpage"
}
},
{
"@type": "BreadcrumbList",
"@id": "https://example.com/seo#breadcrumbs",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://example.com"
},
{
"@type": "ListItem",
"position": 2,
"name": "SEO",
"item": "https://example.com/seo"
}
]
}
]
}
</script>
Note about BreadcrumbList: Only add breadcrumbs if you actually display them on the page, or if your site has a clear hierarchy that you can maintain consistently. Do not add them ad hoc on some pages and not on others.
Note about Product pages: Product pages require Product schema with additional properties (offers, availability, reviews, aggregateRating, etc.). This is beyond the scope of this article.
Page-level JSON-LD for blog articles
For blog articles, you use a slightly different set of nodes.
Minimum baseline checklist:
WebPage (required)
BlogPosting (required)
BreadcrumbList (highly recommended)
FAQPage (optional, only if FAQ is on page)
Linking rules:
BlogPosting.mainEntityOfPage refers to WebPage @id
BlogPosting.author refers to site-wide Person @id (if defined)
BlogPosting.publisher refers to site-wide Organization @id
WebPage.isPartOf refers to site-wide WebSite @id
Canonical template for blog post:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "WebPage",
"@id": "https://example.com/blog/seo-tips#webpage",
"url": "https://example.com/blog/seo-tips",
"name": "SEO tips voor 2026",
"description": "Overzicht van praktische SEO tips.",
"isPartOf": {
"@id": "https://example.com/#website"
}
},
{
"@type": "BlogPosting",
"@id": "https://example.com/blog/seo-tips#blogpost",
"headline": "SEO tips voor 2026",
"description": "Overzicht van praktische SEO tips.",
"image": "https://example.com/images/seo-tips-header.jpg",
"datePublished": "2026-01-15T10:00:00+01:00",
"dateModified": "2026-01-20T14:30:00+01:00",
"author": {
"@id": "https://example.com/#founder"
},
"publisher": {
"@id": "https://example.com/#organization"
},
"mainEntityOfPage": {
"@id": "https://example.com/blog/seo-tips#webpage"
}
},
{
"@type": "BreadcrumbList",
"@id": "https://example.com/blog/seo-tips#breadcrumbs",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://example.com"
},
{
"@type": "ListItem",
"position": 2,
"name": "Blog",
"item": "https://example.com/blog"
},
{
"@type": "ListItem",
"position": 3,
"name": "SEO tips voor 2026",
"item": "https://example.com/blog/seo-tips"
}
]
}
]
}
</script>
Important for dateModified: Always add dateModified when you update an article. This helps search engines interpret changes better and can contribute to clearer freshness signals, which is also relevant for GEO optimization (Generative Engine Optimization).
Schemamarkup structures your content so that machines and people can find exactly what they need. And when LLMs understand you better, they cite youmore often.
ID and URL strategy that is bulk-proof
A consistent @id strategy is essential to keep your structured data scalable. This becomes particularly crucial for sites with hundreds of product pages or blog articles.
Strict pattern for @id fragments:
WebPage:
[CANONICAL_URL]#webpageService:
[CANONICAL_URL]#serviceBlog Posting:
[CANONICAL_URL]#blogpostBreadcrumbList:
[CANONICAL_URL]#breadcrumbsFAQ Page:
[CANONICAL_URL]#faqImageObject (primary):
[CANONICAL_URL]#primaryimage
Important rules:
Use your canonical URL exactly. Copy the href from your
<link rel="canonical">tag.Match www/non-www exactly. As canonical
https://www.example.comis, use that in JSON-LD as well.Match trailing slash exactly. If canonical ends with
/, use that in @id as well.Use lowercase fragments.
#webpagenot#WebPageor#WEBPAGE.Consistent throughout the entire site. Not on page A
#serviceand on page B#service.
Example of bulk implementation:
If you have 200 product pages, generate the @ids programmatically using exactly the same logic as your canonical URL generation. For Shopify sites: you can automate this via your theme's liquid templates.
Common mistakes (with fixes)
Quick reference: 10 mistakes overview
Detailed explanation for each error
1. Duplicate the organization chart on every page
What you see: Each page has its own Organization definition in the page-level JSON-LD.
Why it's problematic: Inconsistencies between pages can send unclear signals.
Fix: Move Organization to your site-wide script. Let page-level scripts refer via {"@id": "https://example.com/#organization"}.
2. Mixing Blog Posting and Service on the same URL
What you see: A page has both @type: "BlogPosting" as @type: "Service".
Why it's problematic: A page cannot be both a blog article and a service at the same time. This can lead to ambiguity.
Fix: Choose one primary type. Is it an article describing a service? BlogPosting. Is it a landing page for a service? Service + WebPage.
3. WebPage.mainEntityOfPage refers to itself
What you see:
{
"@type": "WebPage",
"@id": "https://example.com/seo#webpage",
"mainEntityOfPage": {
"@id": "https://example.com/seo#webpage"
}
}
Why it's wrong: mainEntityOfPage is intended to refer from an entity (Service, BlogPosting) to the WebPage where it is located. Not the other way around.
Fix: Remove mainEntityOfPage from WebPage. Use mainEntityOfPage Only IN the Service/BlogPosting node to refer back to WebPage.
4. FAQ content that is not on the page
What you see: FAQPage schema with questions that are not literally in the visible HTML.
Why it's wrong: Google's guidelines require structured data to match visible content. This can lead to manual action.
Fix: Only add FAQ schema if the questions AND answers are actually on the page. Do not copy and paste FAQs from a template.
5. Description with claims that you cannot substantiate
What you see: "description": "We are the best SEO agency in Belgium with 500+ satisfied customers"
Why it's problematic: If you don't have 500+ customers, this is misleading markup.
Fix: Only use facts that you can prove. Do you have 50 customers? Say so. Don't have customer data? Leave it out or keep it general.
6. Change URL formats halfway through the site
What you see: Homepage used https://example.com, use subpages https://example.com/, yet others https://www.example.com.
Why it's problematic: Inconsistent @ids break the linking between entities.
Fix: Choose one canonical URL format and use it everywhere. If you use canonical tags https://example.com is (without trailing slash), use that consistently in JSON-LD as well.
7. Overfilled sameAs with random sources
What you see: "sameAs": ["https://facebook.com/bedrijf", "https://linkedin.com/company/bedrijf", "https://random-directory.com/bedrijf123", "https://spam-linkfarm.org/bedrijf"]
Why it's problematic: SameAs is intended for official, authoritative sources. Not for every place where your company is mentioned.
Fix: Only use official social profiles (LinkedIn, Facebook, Twitter, Instagram) and official sources such as Wikipedia (if relevant). Max 3-5 URLs that you actually check and maintain.
8. Multiple JSON-LD scripts without reason
What you see: Four separate <script type="application/ld+json"> blocks on one page for WebPage, Service, BreadcrumbList, and Organization.
Why it is problematic: Unnecessarily complex, difficult to maintain, increases the risk of duplication and inconsistency.
Fix: Consolidate into two scripts: one site-wide (WebSite, Organization, Person) and one page-level (WebPage, Service/BlogPosting, BreadcrumbList, FAQ) with @graph.
9. Broken JSON due to syntax errors
JSON is strict in its syntax requirements. Three common errors:
A. Trailing commas
What you see:
{
"name": "Test",
"url": "https://example.com",
}
Why it's wrong: JSON does not allow a trailing comma after the last property.
Fix: Remove the comma after the last property in each object.
B. Smart quotes (typographic quotation marks)
What you see:
{
"name": "Test's Service"
}
(Note the typographic apostrophe instead of straight quotation marks)
Why it's wrong: JSON requires straight double quotes (") for keys and string values. Typographic quotes (" " ' ') break parsing.
Fix: Replace all typographic quotes with straight quotes. Be sure to check this if you copy JSON from Word, Google Docs, or some WYSIWYG editors.
C. Escaping quotes within strings
What you see (invalid):
{
"name": "Test "Premium" Service"
}
Why it's wrong: Quotes within a string must be escaped with a backslash.
Fix correct example:
{
"name": "Test \"Premium\" Service"
}
General fix: Use a JSON validator such as JSONLint before publishing to detect all these syntax errors.
10. Change other scripts in page with JSON-LD edit
What you see: Developer adds JSON-LD and accidentally changes an existing Google Analytics script or other functionality.
Why it's problematic: JSON-LD scripts must be standalone. Changes to other scripts can break tracking, ads, or other functionality.
Fix: Treat JSON-LD as a read-only zone. Add, but do not modify anything else. Always test after deployment to ensure other scripts still function.
“Previously, search engines were primarily indexes of documents. Now, Google is increasingly becoming an index of ‘things’ and facts related to them.”
Checklist for publication
Before you publish your JSON-LD:
JSON syntax validated with JSONLint
Schema types matched with page intent (Service for service page, BlogPosting for article)
All @id references checked (Organization @id correct, WebSite @id correct)
Tested with Google Rich Results Test
Tested with Schema Markup Validator
No errors or critical warnings in validators
Content in structured data matched with visible page content
URLs exactly like canonical URLs (match www/non-www and trailing slash)
DateModified added if article has been updated
Changelog tracking which pages have which schema
Batch process: first 5 pages live, monitor for 48 hours, then roll out to more pages
Structured data does not replace keyword research, but helps search engines understand the page intent more quickly.
Structured data is not a one-time task, but a system that you set up and maintain. Start with the site-wide entities, then add page-level markup according to the templates above, validate thoroughly, and monitor your Search Console for errors.
The sites that do this well have one thing in common: a clear separation between what belongs site-wide and what belongs page-level, with a consistent @id strategy that scales.
Structured data works best in combination with technical SEO, conversion optimization, and GEO strategies that ensure your content is findable in both traditional search engines and AI systems. If you need help auditing or implementing your structured data, a website audit can provide insight into your current situation.
Related articles:
For those who want to dig deeper into the technical side of SEO:
🚀 More leads, higher conversion, better ROI
This article provided you with insights. Now it's time for action. Whether you want to build a profitable webshop, generate more revenue from performance marketing or SEO, or grow with AI marketing - we provide concrete support to help you move forward.
💬 Discuss your challenge directly with Frederiek: Schedule a free strategy consultation or send us a message
📧 Prefer to email? Send your question to frederiek@clickforest.com or call +32 473 84 66 27
Strategy without action remains theory. Let's take your next step together.
Frequently asked questions about JSON-LD
Should I always include BreadcrumbList?
What if I have multiple authors?
Is the FAQ schedule still useful?
How many Things in about is ideal?
Can I list prices in Service structured data?
What is the difference between WebPage and Article?
Sources & References
Official Google & Schema.org documentation:
Google Search Central - Structured data introduction - https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data
Google Search Central - General structured data guidelines - https://developers.google.com/search/docs/appearance/structured-data/sd-policies
Schema.org - Getting started with Schema.org - https://schema.org/docs/gs.html
Schema.org - Organization type specification - https://schema.org/Organization
Validation Tools:
Google Rich Results Test - https://search.google.com/test/rich-results
Schema Markup Validator - https://validator.schema.org/
JSONLint - https://jsonlint.com
Implementation inspiration:
Yoast Developer Portal - Schema functional specification - https://developer.yoast.com/features/schema/functional-specification/