Learning Hub — Beginner’s Guide
⭐ Beginner — No coding experience needed

What you will learn in this guide

1 What is JSON-LD?

JSON-LD is a way of describing your page content to search engines in a structured format. It sits in a <script type="application/ld+json"> tag in the head or body of your HTML.

Why JSON-LD must be valid:Google ignores invalid JSON-LD silently. You get no warning, no email, no Search Console alert. The rich results just stop appearing. Validation before publishing is essential.

2 The 5 most common JSON errors

ErrorExampleFix
Trailing comma{"a":1,"b":2,}Remove the comma before }
Missing comma between properties{"a":1 "b":2}Add comma between key-value pairs
Unescaped quotes inside strings"name":"O'Reilly" with raw apostrophe is fine; "name":"He said "hi"" is notEscape inner quotes: \"
Single quotes instead of double{'a':1}JSON requires double quotes around keys and string values
Unquoted keys{a:1}Always quote keys: {"a":1}

3 How to validate your JSON-LD

  1. 1Copy your JSON-LD blockFrom your page source, copy everything between <script type="application/ld+json"> and </script>.
  2. 2Paste into the JSON ValidatorOpen schema-tools.html#json-checker and paste your snippet. The tool reports the line and column of any error.
  3. 3Run Google's Rich Results TestEven if JSON is valid, Google may reject the schema for missing required fields. Use Google's tool to confirm rich-result eligibility.
  4. 4Fix and re-testRe-validate after every change. Don't publish until both validators pass cleanly.

4 When automation breaks JSON

Most schema problems come from generators that build JSON from a template. Watch for:

Always log your JSON-LD outputto a server log on staging before going live. Many WordPress sites silently break schema on every plugin update.

4 Why this bug is worse than a bug that crashes

Almost every defect in software announces itself. A page errors, a build fails, a test goes red, a customer complains. Broken JSON-LD does none of that.

Google reaches a block it cannot parse, discards it, and carries on. The page renders perfectly. Nothing appears in Search Console. No email arrives. The only symptom is an enhancement that stops appearing — and it stops appearing gradually, as pages are recrawled over days or weeks, so there is not even a clean date to correlate against a deploy.

The result is that structured data on most sites is not maintained; it is abandoned, working or not, until somebody happens to look. And the thing that broke it was almost never a person editing schema. It was a plugin update, a theme change, or a bulk edit that nobody connected to markup at all.

There is no partial credit. JSON is parsed as a whole. A stray comma in the last property of a fifty-line block discards all fifty lines — including the forty-nine that were correct. One character, and the entire block is as if it were never there.

5 Where these errors really come from

The five syntax errors listed above are what you see. It is worth understanding what produces them, because the fix is almost never "be more careful".

The unescaped quote is a template bug. Somebody enters a product name containing a double quote, or a description with a quoted phrase, and the template drops that value straight into a JSON string. The quote terminates the string early, and the parse dies. The answer is not to forbid quotation marks in your content — it is to stop building JSON by gluing strings together. Any system that concatenates its way to JSON-LD will produce this bug eventually; a system that serialises a real object structure cannot.

The trailing comma is a hand-editing bug. Somebody removed a property and left the comma behind. It is the signature of markup being maintained by hand, which is itself the deeper problem: schema that is written once and edited by hand will drift out of step with the page it describes within months.

Single quotes and unquoted keys are a copy-paste bug. Somebody pasted a JavaScript object literal, which is valid JavaScript and is not JSON. The two look almost identical and are not the same language.

The pattern in all three: the error is a symptom of how the markup is produced. Generate it from your data, serialise it properly, and this whole class of failure stops happening.

6 Two validators, and the thing neither of them checks

Fixing the syntax gets you past the first gate. There are three, and most sites stop after one.

  1. 1Does it parse?A JSON validator answers this. It is necessary and it proves very little — a block can parse cleanly and describe nothing Google cares about.
  2. 2Does it qualify?Google's Rich Results Test answers this. Valid JSON with a missing required property, or a type that is not eligible for any enhancement, will be parsed perfectly and used for nothing.
  3. 3Is it true?No validator answers this, and it is the one that costs money. Markup asserting a price the page does not show is valid JSON, valid schema, and a false statement about your own product. In Google's shopping surfaces that is grounds for item disapproval; organically the enhancement can simply be dropped. And it misleads the shopper who clicked expecting the price they were shown.

So the check worth automating is not "does it validate" but "does the value in the JSON-LD equal the value on the rendered page". Price against price. Availability against the state of the Add to Cart button. Headline against the H1. That comparison is the only thing standing between you and markup that is confidently, validly wrong.

7 Make the check automatic, or it will not happen

Structured data breaks at deploy time, because that is when the code that generates it changes. Which means a manual validation step — however well-intentioned — will be skipped on precisely the release that needed it, and the breakage will then sit undetected for as long as it takes somebody to notice a missing enhancement.

The efficient shape of this is template-level. One product template renders every product; a regression in it breaks all of them at once, so a single watched URL detects the problem for the cost of one fetch. Conversely, watching a hundred product pages while watching no article page leaves an entire template unobserved.

So: for every template that emits structured data — product, category, article, author, the homepage — take one instance, fetch it on every deploy and on a schedule, and assert that it parses, that the required properties are present, and that the values agree with the page.

Run it on a schedule as well as on deploys, because plugin auto-updates and CDN configuration changes are deploys that nobody on your team made.

8 Frequently asked questions

What happens if my JSON-LD is invalid?

Nothing visible, which is exactly the problem. Google discards a block it cannot parse and moves on. There is no warning, no email, and no Search Console error — the enhancement simply stops appearing, and it stops appearing gradually as pages are recrawled, so there is not even a clear date to correlate against. This is why structured data breaks silently and stays broken for months: every other kind of bug announces itself, and this one does not.

Why is one missing comma enough to break everything?

Because JSON is parsed as a whole, not line by line. A parser reading your Product block hits the malformed character, cannot construct a valid object, and abandons the entire script tag — not just the property that was wrong. So a stray comma in the last property of a fifty-line block discards all fifty lines, including the forty-nine that were perfect. There is no partial credit, and that is why validation before publishing is not optional.

Where does the unescaped quote problem come from?

A CMS field containing a double quote, almost always. Somebody types a product name with quotation marks in it, or a description containing a quoted phrase, and the template drops that value into a JSON string without escaping it. The quote terminates the string early and the parse fails. The fix is not to ban quotes from your content — it is to escape values properly when generating the markup, which is the template's job. Any system building JSON-LD by string concatenation will eventually produce this bug; systems that serialise a real object structure will not.

Does valid JSON mean Google will use my schema?

No, and this catches people out after they have fixed the syntax. Valid JSON is the first gate; valid schema is the second. Google can parse your block perfectly and still reject the enhancement because a required property is missing, or because the type does not qualify for any rich result. So run two checks: a JSON validator to confirm it parses, then Google's Rich Results Test to confirm the schema qualifies. Passing the first tells you nothing about the second.

What does neither validator check?

Whether the markup is true. A Product block asserting £29.99 while the page displays £34.99 is perfectly valid JSON and perfectly valid schema — it parses, it has every required field, and it passes every automated test in existence. It is also a false statement about your own product in machine-readable form, which in Google's shopping surfaces is grounds for item disapproval and organically can get the enhancement dropped. Structured data must describe the visible page, and only a comparison between the two catches a violation.

How do I stop this recurring?

Assert it automatically, on every deploy. Structured data breaks at deploy time — a plugin update, a template change, a bulk edit — and it breaks invisibly, which means a manual check will be skipped on exactly the release that needed it. Take one representative page per template, fetch it, and assert three things: the JSON-LD parses, the required properties are present, and the values match the rendered page. One watched URL per template detects a regression across every page that template renders.

Should I put JSON-LD in the head or the body?

Either works — Google reads it from both. What matters far more is that it is in the HTML your server sends, rather than injected by JavaScript after load. Google does render, so script-injected schema can be picked up, but rendering is queued and less certain than markup that was simply there. And many AI retrieval fetchers parse the served HTML and never run JavaScript at all, so schema injected client-side is invisible to them permanently. Put it in the served response and the question disappears.

Written by
John
Founder, aiwebpageseo

JSON-LD is unforgiving in a specific way: it either parses or it does not, and when it does not, nothing tells you. One unescaped quote and the whole block is discarded silently — no warning, no email, no Search Console alert. Validate before publishing, and then check the second thing that no validator checks: that the values in the markup match the values on the page.

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical website tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.