Web & SEO
If you are searching for JSON-LD website, or for structured data errors, you are typically in one place: someone turned on a schema plugin, or pasted a script in the layout, and Search Console or a test tool shows warnings — or shows nothing, because Google chose to ignore you. FAQPage on a page without questions. Review with five stars you wrote yourself. LocalBusiness on a bureau that sells nationally. Organization without a name that matches the footer. The relaunch post is cutover and 301s. The performance post is LCP. This one is the truth in the script. Markup you cannot point at in the HTML is not structured data. It is a hope you call rich results.
JSON-LD is a promise: this is what the page is, in a language a machine can parse. The promise holds when a human can read the same sentence on the page. It rots when you describe a product you do not show, an FAQ you folded away, or an address you do not want to stand behind as a shop. Google has said it for years: markup must reflect visible content. The habit is still to install a plugin, turn on every type, and call it SEO. You have not earned rich results. You have earned a script a quality rater can use against you.
TL;DR
The main takeaways
- JSON-LD is the truth about the page, in a parseable language. If the sentence is not visible, delete the script.
- FAQPage needs visible questions. Review needs real reviews. LocalBusiness needs you to be a local place.
- Organization, WebSite, Service, Article, BreadcrumbList — pick what the page actually is. Not the whole catalogue.
- A plugin that turns on every type is how you get warnings and ignored markup. Fewer honest nodes beat a dump.
- Test with Rich Results and with your eye: can you point at the field in the HTML? If not, it is not data. It is decoration.
- The performance post is LCP. Relaunch is 301s. This is refusing to let schema say something the page does not.
Why this matters at all
Structured data is a promise to two parties: the crawler, which would like to understand the page without guessing, and the quality rater (human or system) that checks whether you are cheating. The promise holds when FAQ markup matches the questions you actually show, when Article has the author and date the page shows, when Organization has the name and company id the footer has. It rots when you hope for stars, FAQ extraction or a knowledge panel by describing something the user cannot see.
Teams do it because a plugin or an agency slide said 'turn on schema and you get rich results'. The first test tool goes green. It becomes the habit. Three months later the homepage has LocalBusiness, Product, FAQPage and Review in one script, and none of it stands as content. Google does not show the stars. Now and then Search Console shows 'either/or' or 'non-critical issues'. You fix one warning. You do not touch the truth.
The damage is not only missing rich results. Markup that overclaims is a signal you have asked to be treated as that. A Review you wrote yourself. An AggregateRating without sources. An FAQ that only exists in JSON. A price you put on Product that you do not show — and that we do not put on a marketing site anyway. You have told a machine something you will not stand behind on the page. That is the opposite of SEO. It is asking for your honest pages to be met with scepticism too.
We write this because 'we have JSON-LD' has become a tick you add at go-live. An honest setup is boring: one @type that fits the page, fields you can point at, and no nodes you turned on 'to be safe'. Without that habit you have a script from the plugin. You do not have structured data.
What JSON-LD actually is — and what a schema plugin is not
JSON-LD is a script of type `application/ld+json` that describes the page with schema.org types. It is not a secret ranking factor you can switch on. It is a label on what you have already written. WebSite and Organization on a site that has a name and a homepage. Article on a post with an author and a date. Service on a service you describe. FAQPage on a page that shows questions and answers. BreadcrumbList on the trail the user can see. Each type is a job. Not a shelf you empty into `<head>`.
It is not the same as Open Graph and Twitter tags. Those are sharing: title, description, image, when someone posts the URL. JSON-LD is meaning: what kind of page this is, who publishes it, which questions sit on it. You can have honest OG without JSON-LD. You can have JSON-LD that contradicts OG and the H1. The crawler and the messenger unfurl then choose. You have not chosen. Write the H1 and the meta first. Write JSON-LD as a mirror, not as a second draft.
It is also not the same as a sitemap or a canonical. The sitemap is the list of URLs you want crawled. Canonical is which variant is preferred. JSON-LD says what the preferred page means. Pasting Organization on every URL and forgetting Article on the post is saying every page is the company. Pasting FAQPage on every URL is saying every page is a Q&A. Both are lies if the page is a marketing section without that block.
And it is not 'Yoast / RankMath / a React component that dumps the whole graph'. A plugin can be a tool if you turn off what you have no content for. A component can be a tool if it reads the same dictionary the page renders. What typically goes wrong is a dump: every type, empty fields, an address you do not want to be LocalBusiness on, and a review you never received. The inventory is the script you deploy and the HTML it mirrors. Everything else is a hope you parked with a vendor.
What typically goes wrong when someone says we have schema
The first failure is turning on types the page is not. LocalBusiness on a site that sells nationally and internationally — you have a Danish address, you are not a shop with opening hours as the product. Product on a service without a visible product, without an offer, without what you may show as a price. Review and AggregateRating you wrote yourself, 'so we can get stars'. Each wrong type is a place a test tool can go green and a rater can say no. Pick the type you can defend in a meeting where someone opens the page next to the script.
The second failure is fields that do not sit on the page. A `description` that is a different draft from the lead. An `author` who is not named. A `datePublished` you set to today on an old post every time you deploy. A `telephone` on Organization that you do not show. Google has repeated: markup must match visible content. That is not a guideline you can 'take later'. It is the whole job. If the field is true, show it. If you will not show it, do not mark it up.
The third failure is pasting the same graph on every page. Homepage, service, post, 404 — the same Organization + FAQ + WebSite in one lumped script. Organization and WebSite can belong on the homepage and in a site-wide block you keep honest. FAQ belongs where the FAQ is. Article belongs on the article. A 404 with Article is a lie. The error-pages post is chrome. This is letting the script follow the template, not letting the layout be a dump.
The fourth failure is chasing rich results as the goal. Stars, FAQ extraction, sitelinks searchbox. Some of those are restricted, retired, or given to pages that already have trust. You control the markup. You do not control the extract. An honest Article with author, date and an image the page shows beats a Review you invented. If you want FAQ extraction, write the FAQ as content first. The script comes after. The speed post is LCP. This is refusing to let a hope of SERP chrome drive what you put in `<head>`.
A mirror of the page vs. a dump from the plugin
The honest mirror
Each node is a sentence you can point at in the HTML. Fewer types. Real fields.
- Organization / WebSite from the same siteConfig the footer already uses
- Article, Service, FAQPage, BreadcrumbList only on the templates that show them
- No Review, product price or LocalBusiness you will not stand behind as content
- Is boring to maintain, and that is the whole point — the test tool and the eye agree
The rotten dump
Every type on, empty fields, and a graph you have never read.
- The plugin or the agency turned on LocalBusiness, Product, FAQ and Review on the homepage
- Fields that do not sit on the page — or that contradict the H1 and the meta
- The same script on 404, article and service so you 'do not forget SEO'
- Is a hope you call structured data. The crawler does not owe you stars for it
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "The same H1 the page shows",
"datePublished": "2026-11-02",
"author": { "@type": "Organization", "name": "The same name as in the footer" }
}
{
"@type": "FAQPage",
"mainEntity": [{
"@type": "Question",
"name": "A question that does not exist in the HTML"
}]
}How to decide whether you owe JSON-LD at all — and which type
Without this order you get another script you call schema.
- 01
Write the page first. Mark it up after
H1, lead, visible FAQ, visible author, visible address if you want to own it as content. If the block is not there, the type is not there. A plugin that 'generates FAQ from H2s' you never asked as questions is a dump. The relaunch post is URLs. This is the sentence on the page.
- 02
Pick one primary @type that fits the template
Homepage: Organization + WebSite. Service: Service with a provider. Post: Article or BlogPosting. FAQ block: FAQPage as extra, not as a replacement. Breadcrumbs: BreadcrumbList that matches the visible trail. If you are torn between LocalBusiness and Organization, and you sell nationally, Organization is the word. An address in the footer does not make you a shop.
- 03
Fill only fields you can point at
Name, URL, logo, description, date, author, question, answer. If you do not show a phone number, omit telephone. If you do not show reviews, omit Review. If you do not show a price — and on a marketing site you typically should not — omit Offer. An empty field is not 'ready for later'. It is noise in the graph.
- 04
Put the script where the template actually renders
The same dictionary as the page. The same date as `publishedAt`. The same FAQ array as the block. WordPress: one plugin you have turned types off in, not two that both dump. Next.js: one JsonLd component that receives data, not a hardcoded lump in the root layout on every URL. Test one URL at a time.
- 05
Test with the tool and with your eye — and repeat when you edit
Rich Results Test and the schema validator can say valid and still be a lie if the page does not show it. Open the page. Point. If you cannot, delete the node. When you change the H1 or remove the FAQ, you change the script the same day. The monitoring post is GSC. This is owning the graph so the 'structured data' report is not full of nodes you never meant.
“You have structured data when the crawler can check the sentence on the page. A script without truth is hope.”
Homepage, article, service and FAQ — same word, four jobs
The homepage is the job that most often gets the whole catalogue. It is the company and the site: Organization with legalName, an address you will stand behind, sameAs to the profiles you actually own, WebSite with the name you use. It is not LocalBusiness unless the local place is the product. It is not FAQPage unless the homepage shows the questions. It is not Product. An honest site-wide block beats a dump you copied from a theme.
The article is the job that most often forgets author and date, or puts them in the script and hides them in the UI. BlogPosting / Article with headline = H1, datePublished = the date you show, author = the byline you show, image = the hero you show. Update dateModified when you actually edit, not when you deploy. A post without a visible date should not have a date in JSON-LD you hope for in the SERP.
The service is the job that most often becomes Product with Offer, because someone wanted price markup. A service is Service: name, description, provider pointing at Organization. Area served, if you mean it. Not a price field you do not show — and that you should not show on this site. An Offer without a visible price is a lie. An Offer with a price you will not defend on a call is worse. Write what you do. Mark that up. Leave the price in the conversation.
The FAQ is the job that most often becomes a hidden array. FAQPage is right when the page shows questions and answers as content — not as an accordion you have `display:none` on, and not as H2s you never asked as questions. Four to six real questions beat twenty thin ones. The JSON-LD is the same array the block renders. If you remove the block, you remove the node. Search Console extraction is a bonus you do not control. The visible FAQ is the job.
What you should typically do in the situation you are in
The left is what you typically say. The right is the next step we typically recommend.
Situation
The plugin has turned on LocalBusiness, Product, FAQ and Review on the homepage
Next step
Turn off what the page is not. Organization + WebSite. The rest belongs on the templates that show them
Situation
Search Console shows FAQ warnings, and the page has no questions
Next step
Delete FAQPage. Or write the questions as visible content. A hidden array is not a fix
Situation
You want stars in the SERP, and you have no reviews to show
Next step
Delete Review. Stars you wrote yourself are a signal you have asked to be met as that
Situation
The Article date in the script changes on every deploy
Next step
Bind datePublished to the date the page shows. dateModified only when you actually edit
Situation
The same JSON-LD lump sits in the root layout on every URL
Next step
Move it to the template. A 404 is not an Article. A service is not an FAQ unless it shows one
Checklist before you call it structured data
If you are missing several of these, the sentence is we have JSON-LD — the setup is a script you have not read.
- Each node has an @type you can defend when the page is open next to the script
- Each field can be pointed at in the HTML — or it is deleted
- No Review, AggregateRating, product price or LocalBusiness you will not show as content
- FAQPage, Article and Service live on the templates that render them — not in one dump in the layout
- You have run Rich Results on the URLs you changed, and you have looked at the page, not only at 'valid'
- Performance and relaunch are other jobs. This is refusing to let schema say something the page does not
Questions we hear again and again
What is JSON-LD on a website, and is it required?
JSON-LD is a script that describes the page with schema.org types. It is not required to rank. It is a mirror you offer the crawler so it does not have to guess. Without honest content to mirror, it is noise. With honest content — a name, an article, a service, a visible FAQ — it is the clean way to say it. A plugin that turns on every type is not 'having JSON-LD'. It is having a dump.
May we put FAQ schema on pages without a visible FAQ?
No. FAQPage is for pages that show questions and answers. A hidden array, an accordion with display none, or H2s you never asked as questions is what Google has asked you not to do. Write the FAQ as content, or omit the type. Rich results are a bonus you do not control. The visible block is the job. A warning in Search Console is often the page telling you the script is lying.
Should a bureau with a Danish address use LocalBusiness?
Only if the local place is what the page sells — a workshop, a clinic, a shop with opening hours as the product. A bureau that sells nationally and internationally, with an address in the footer, is Organization (and typically ProfessionalService), not LocalBusiness. The wrong type is how you ask for local rich results you will not defend, and how you confuse the graph you actually meant.
Do we get stars in Google if we add Review markup?
Not because you added markup. And not if the review is not visible, or if you wrote it yourself. Review and AggregateRating are among the types most often abused, and most often ignored. If you have real, visible reviews with a source, you may mark them up. If you do not, do not. Stars you invented are a signal you have asked to be treated as that.
Is this the same as relaunching without losing SEO, or having fast pages?
No. The relaunch post is cutover, 301s and parity. The performance post is LCP and Core Web Vitals. This is the truth in the script: an @type that fits, fields you can point at, no nodes you turned on to be safe. You can have a fast site with a rotten dump in `<head>`. You can have a clean relaunch and paste LocalBusiness on the homepage the next day. They are three jobs. One does not replace the others.
If you have a schema plugin on and a page the script cannot point at
Let us separate an honest mirror from a dump you call SEO.
Markup that matches the HTML beats a catalogue you turned on for rich results.
