/ โ† JSON Fixes / JSON-LD format explained
In this guide
  1. What JSON-LD means
  2. JSON vs JSON-LD: the actual difference
  3. The special keys: @context, @type, @id and @graph
  4. JSON-LD examples, annotated
  5. How Google reads JSON-LD
  6. Where JSON-LD comes from on common platforms
  7. The fix, step by step
  8. Edge cases worth knowing
  9. Keeping your JSON-LD correct
  10. Questions and answers

What JSON-LD means

JSON-LD stands for JavaScript Object Notation for Linked Data. It is a W3C standard, first published in 2014 and updated as JSON-LD 1.1 in 2020, for writing linked data using normal JSON syntax. The community site at json-ld.org hosts the specification links and a playground for testing.

On a website, JSON-LD is almost always used to carry structured data written with the Schema.org vocabulary. Schema.org is a shared dictionary of types such as LocalBusiness, Product, Article and FAQPage, and properties such as name, address and price. JSON-LD is the container; Schema.org supplies the words that go inside it.

The block sits in a script tag with a special media type:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Bakery",
  "name": "Example Bakery",
  "telephone": "+44 1632 960961",
  "url": "https://example.com/"
}
</script>

Because the type is application/ld+json and not text/javascript, the browser does not run it and visitors never see it. Search engines, AI crawlers and other tools read it as data. That separation is why Google recommends JSON-LD over the older Microdata and RDFa formats: you can add, change or remove it without touching the visible HTML.

๐Ÿ’ก If you are new to structured data, the beginner tutorial on schema markup covers the vocabulary side; this page concentrates on the format itself.

JSON vs JSON-LD: the actual difference

Every JSON-LD document is valid JSON. The difference is that JSON-LD gives certain keys a fixed meaning, so a program that has never seen your data before can still work out what it describes. Plain JSON has no such agreement: a key called name could mean anything, and only the developer who wrote it knows.

PointPlain JSONJSON-LD
SyntaxObjects, arrays, strings, numbers, true, false, nullExactly the same syntax
Meaning of keysPrivate to the app that uses itDefined by a vocabulary named in @context
IdentityNo standard way to say two records are the same thing@id gives each thing a global identifier
TypeUsually a custom field, if any@type points to a defined class
Typical useAPIs, config files, app dataStructured data for search engines, knowledge graphs
Media typeapplication/jsonapplication/ld+json

So the honest answer to json vs json-ld is that you are not choosing between two formats. JSON-LD is JSON with an agreed set of rules on top. Anything that can parse JSON can parse JSON-LD; it simply will not understand the linked data part unless it knows the rules.

This also means a JSON syntax error breaks JSON-LD completely. A trailing comma, a smart quote pasted from a word processor or a missing bracket stops the parser before it reads a single property. The JSON syntax guide lists the common mistakes and how to spot them.

The special keys: @context, @type, @id and @graph

JSON-LD reserves keys that start with @. You only need four of them for nearly all website structured data.

@context

Tells the reader which vocabulary the other keys come from. For search, it is "https://schema.org". With that context, name means the Schema.org property name and nothing else. Google accepts http or https and with or without a trailing slash, but use https://schema.org consistently.

@type

Says what kind of thing the object is. It must match a Schema.org type exactly, including capitals: LocalBusiness works, localbusiness does not. You can give more than one type as an array, for example ["WebPage", "TechArticle"].

@id

A unique identifier for the thing, written as a URL. It does not have to be a page that loads; it is a name. The convention is your page URL plus a fragment, such as https://example.com/#business. Once an object has an @id, other objects can point to it instead of repeating it. The guide to schema @id values covers naming patterns and common clashes.

@graph

Holds several top-level objects in one block, sharing a single @context. This is how WordPress SEO plugins output a website, a web page, a breadcrumb trail and a business in one script tag.

{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Bakery",
      "@id": "https://example.com/#business",
      "name": "Example Bakery",
      "url": "https://example.com/"
    },
    {
      "@type": "WebPage",
      "@id": "https://example.com/opening-times/#webpage",
      "url": "https://example.com/opening-times/",
      "name": "Opening times",
      "publisher": { "@id": "https://example.com/#business" }
    }
  ]
}

The publisher property contains only an @id. A reader joins the two objects together, so the page is published by the bakery described above. That joining is the linked part of linked data.

โš ๏ธ An @id reference that points to nothing on the page is not an error in the JSON-LD standard, but Google cannot use it either. Make sure every referenced @id is defined somewhere in the page's structured data.

JSON-LD examples, annotated

A local business

{
  "@context": "https://schema.org",
  "@type": "Bakery",
  "@id": "https://example.com/#business",
  "name": "Example Bakery",
  "telephone": "+44 1632 960961",
  "url": "https://example.com/",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "1 Example Street",
    "addressLocality": "Exampletown",
    "postalCode": "EX1 1AA",
    "addressCountry": "GB"
  },
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
    "opens": "08:00",
    "closes": "17:00"
  }]
}

Notice that address is a nested object with its own @type. Nesting is how JSON-LD says that a property's value is itself a thing with properties. Country codes use two-letter ISO codes, and times use 24-hour format.

An article

{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "How we bake sourdough",
  "datePublished": "2026-03-02T09:00:00+00:00",
  "dateModified": "2026-09-14T11:30:00+01:00",
  "author": { "@type": "Person", "name": "Sam Example" },
  "image": "https://example.com/images/sourdough.jpg"
}

Dates use ISO 8601. Include a time zone offset so the date cannot be misread. More date rules are in the schema dates guide.

A product

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Seeded rye loaf",
  "image": "https://example.com/images/rye.jpg",
  "offers": {
    "@type": "Offer",
    "price": "4.50",
    "priceCurrency": "GBP",
    "availability": "https://schema.org/InStock"
  }
}

Values such as availability are written as full Schema.org URLs. The price is a plain number without a currency symbol, and the currency goes in its own property. The product schema guide covers the properties Google needs for product results.

How Google reads JSON-LD

Google's documentation says it supports JSON-LD, Microdata and RDFa, and recommends JSON-LD. In practice, this is what happens when Googlebot fetches a page:

  1. It reads every application/ld+json script in the HTML, in the head or the body. Position does not matter.
  2. It parses each block as JSON. A block that fails to parse is dropped, and Search Console may report it as an unparsable structured data item.
  3. It renders the page. JSON-LD added by JavaScript after load can also be read at this stage, as long as rendering succeeds, though server-rendered markup is more dependable.
  4. It matches objects to the features it supports, such as product snippets, breadcrumbs or local business details, and checks each against that feature's required and recommended properties.
  5. It decides whether to show a rich result. Valid markup makes a page eligible; it does not guarantee anything appears.

Google does not need one block per page. Several separate blocks, or one block with a @graph, both work. What matters is that the markup describes content visitors can actually see on the page, which is part of Google's structured data guidelines. Marking up prices, opening hours or questions that are not on the page breaks those guidelines and can lead to a manual action.

What you seeWhat it usually means
Rich Results Test shows no itemsThe block failed to parse, uses a type Google has no feature for, or is not in the fetched HTML
Item detected with errorsA required property for that feature is missing or the wrong kind of value
Item valid with warningsOptional properties are missing; the page can still be eligible
Schema Markup Validator passes, Rich Results Test shows nothingThe markup is valid Schema.org, but the type is not one Google uses for a rich result

The last row confuses many people. Schema.org has hundreds of types and Google builds features for a small number of them. Other types are still read and can help Google and AI systems understand the page, but they will not show in the Rich Results Test. The guide to testing schema and rich results explains both tools in depth.

Where JSON-LD comes from on common platforms

To see what a live page really serves, fetch the raw HTML and pull out the blocks:

curl -s https://example.com/ | grep -o '<script type="application/ld+json">.*</script>'

If a block spans several lines, the grep shows nothing, so open the page in Chrome, press Ctrl+U for the source and search for ld+json instead. In DevTools, the Console line below lists every block the page holds after rendering:

[...document.querySelectorAll('script[type="application/ld+json"]')].map(s => JSON.parse(s.textContent))

If that line throws an error, one of the blocks is not valid JSON.

The fix, step by step

Step 1

Decide what the page describes

Before writing any code, pick the single main thing the page is about: a business, a product, an article, an event. Find the matching Schema.org type on schema.org, such as Bakery for a bakery or Product for a shop item. Note the properties Google lists as required and recommended for that feature in its Search Central documentation. You will know this step is done when you have one type name and a short list of properties whose values are all visible on the page itself.

Step 2

Write the block with @context and @type

Open a plain text editor, not a word processor, so quotes stay straight. Start with an object containing "@context": "https://schema.org" and "@type" set to your chosen type, spelt with the exact capitals Schema.org uses. Add each property as a key in double quotes followed by its value. Nest objects such as PostalAddress or Offer with their own @type. Paste the result into a JSON validator or the JSON-LD Playground and confirm it parses without a single error.

Step 3

Give important things an @id

Add an @id to every object you may want to refer to from elsewhere, such as the business or the website. Use your real domain plus a fragment, for example https://example.com/#business, and use exactly the same value on every page. Where one object refers to another, such as a page publisher, replace the repeated details with a reference containing only that @id. Check that each reference has a matching definition by searching the block for the identifier string.

Step 4

Wrap it in the script tag

Place the JSON inside a script element with type="application/ld+json". Put it in the page head or anywhere in the body; both work. Do not add async, defer or a src attribute, because the data must be inline. If your platform has a header code box or a theme template, use that so the block appears on every page of that type. Save, then view the page source with Ctrl+U and search for ld+json to confirm the block is present.

Step 5

Check the served HTML

Fetch the live page as a crawler would with curl -s https://example.com/page/ and confirm the block appears in the raw HTML, not only after JavaScript runs. Make sure caching or minification plugins have not stripped quotes or merged the block into another script. If the block is missing from the raw HTML but present in DevTools, it is being injected client side, which Google can still read after rendering but which is less dependable than server-side output.

Step 6

Test with the Rich Results Test

Paste the URL into Google's Rich Results Test and run it with the default smartphone crawler. Open each detected item and read any errors and warnings. Errors mean a required property is missing or malformed and the item cannot produce a rich result; warnings mean optional properties are missing. Fix errors first, then decide which warnings are worth filling. A green valid item for your chosen feature confirms Google can read and use the block on that page.

Step 7

Validate against Schema.org

Run the same URL or code through the Schema Markup Validator at validator.schema.org. It checks every type and property against the full vocabulary, including types Google has no rich result for, and flags misspelt property names that the Rich Results Test simply ignores. Correct any unknown properties or wrong value types. When the validator shows your objects with no errors and the properties grouped under the right types, the markup is correct as linked data.

Step 8

Monitor in Search Console

After Google recrawls the page, open the relevant report under Enhancements or Shopping in Search Console, such as Breadcrumbs or Product snippets. Use URL Inspection on the page and open the detected structured data to confirm Google saw the same items you tested. If an item shows as invalid, fix it and use Validate fix on the report. Repeat this check after every theme, plugin or template change, because that is when blocks most often break.

Edge cases worth knowing

Keeping your JSON-LD correct

JSON-LD rarely breaks on its own. It breaks when something else changes: a theme update, a new plugin, a price change that never reached the markup, or a page template edited by someone who did not know the block was there. A few habits keep it healthy:

Questions and answers

1. What is JSON-LD format?

JSON-LD is a way of writing linked data in ordinary JSON, using a few reserved keys such as @context, @type and @id to give the data an agreed meaning. On websites it carries Schema.org structured data inside a script tag with the type application/ld+json, so search engines and AI systems can read facts about the page, such as a business name, a product price or an article date, without parsing the visible text. Browsers ignore the block, so visitors never see it and it does not affect the layout.

2. What is the full form of JSON-LD?

JSON-LD stands for JavaScript Object Notation for Linked Data. JavaScript Object Notation is the common data format made of objects, arrays and simple values, and Linked Data is the idea of giving things global identifiers so that data from different places can be connected. JSON-LD became a W3C Recommendation in 2014, and version 1.1 followed in 2020. The specification and a free playground for testing documents are linked from json-ld.org, which is run by the community that maintains the format.

3. What is the difference between JSON and JSON-LD?

JSON-LD is JSON with extra rules that give certain keys a shared meaning. The syntax is identical, so any JSON parser can read a JSON-LD block. The difference is that JSON-LD names a vocabulary in @context, gives things a type with @type and an identity with @id, so a program that has never seen your data can still understand it. Plain JSON keys only mean what the developer of one application decides, which is fine for APIs but not for search engines.

4. Does Google prefer JSON-LD over Microdata?

Yes, Google recommends JSON-LD for structured data, while still supporting Microdata and RDFa. JSON-LD is easier to add and maintain because it sits in its own script block, separate from the visible HTML, so you can change it without editing your templates around headings and paragraphs. Google treats valid markup in any of the three formats the same way for rich result eligibility, so there is no need to rewrite working Microdata in a hurry, but new markup is best written in JSON-LD.

5. Where should I put JSON-LD on the page?

You can put JSON-LD in the head or anywhere in the body, and Google reads it in either place. Most platforms place it in the head through a plugin or theme setting, which keeps it in one predictable spot. What matters more is that the block is present in the HTML Google fetches or renders, that it is valid JSON, and that it describes content visitors can actually see on that page. Avoid loading it from an external file, because the data must be inline.

6. Can a page have more than one JSON-LD block?

Yes, a page can have several JSON-LD blocks, and Google reads all of them. Many sites have one block from an SEO plugin and another from a theme or app. The risk is duplication: two blocks describing the same business or product with different details can confuse search engines. Either combine everything into one block with a @graph array, or give repeated things the same @id so they are understood as one entity and their properties are merged.

7. Why does my JSON-LD not show in the Rich Results Test?

Usually the block either failed to parse as JSON or uses a type that Google has no rich result for. A trailing comma, a curly quote or a stray comment stops parsing completely, so check the code in a JSON validator first. If it parses, run the Schema Markup Validator: if your items appear there but not in the Rich Results Test, the markup is valid Schema.org but not linked to a Google feature, which is normal for many types and not an error.

Check every JSON-LD block on your site

The JSON checker on aiwebpageseo.com fetches your pages, extracts every application/ld+json block and reports parse errors, missing types and broken @id references, so you can fix a template once instead of page by page.

Open JSON Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All JSON Fixes  ·  How to fix JSON syntax errors  ·  How to test schema markup and rich results  ·  Fixing structured data syntax errors  ·  Schema @id values explained  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO 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.