Structured Data · JSON-LD · SEO

How to add JSON-LD structured data to your website

JSON-LD tells search and AI engines who you are and what each page is. Which schema types to use per page, how to link them with @id, and how to test them.

Mohit Goyal 6 min read
How to add JSON-LD structured data to your website

To add JSON-LD structured data, put a <script type="application/ld+json"> tag in each page's HTML containing schema.org data that describes that page: who runs the site, what the page is, and where it sits in the site. Use one main type per page, link every page to the same Person or Organization with an @id, and test it in Google's Rich Results Test. Only describe what visitors can actually see.

Every page on this site carries its own JSON-LD, generated from the same data the page renders. Below is the setup I use, the mistakes I have fixed on my own site, and a free Schema Markup Generator if you would rather not write JSON by hand.

What is JSON-LD structured data?

Structured data is a description of a page written for machines. JSON-LD is the format: a block of JSON inside a script tag, using the shared schema.org vocabulary. Search engines read it to understand that a page is an article by a particular person, a service with a list of deliverables, or a business with an address and opening hours.

It does two jobs. It can make a page eligible for rich results, such as product prices or breadcrumbs in Google. And it gives answer engines, such as AI Overviews, ChatGPT and Perplexity, clean facts they do not have to infer from your prose.

Which schema types should each page use?

One main type per page, plus breadcrumbs. This is the map I use on mohitgoyal.in:

PageMain typeAlso included
HomePersonWebSite and ProfilePage, linked to the Person
Project pageCreativeWorkBreadcrumbList
Projects or tools listingItemListBreadcrumbList
Service pageService, with an OfferCatalog of deliverablesBreadcrumbList
Case studyArticle, with the client as an OrganizationBreadcrumbList
Blog postBlogPostingBreadcrumbList, and FAQPage when the post has an FAQ
Free tool pageWebApplicationHowTo, FAQPage and BreadcrumbList

For other kinds of site the same idea applies. A restaurant or clinic home page uses LocalBusiness or a more specific subtype, a store uses Product on product pages, and an event page uses Event.

Two rules keep the map honest. First, the main type should match what a visitor would call the page: if they would call it an article, it is an Article or BlogPosting. Second, breadcrumbs should mirror the real navigation. If the breadcrumb trail in the markup says Home, Blog, Post, the page should show the same path, and every URL in it should return a 200.

How do you link pages together with @id?

Give the main entity an @id, a stable URL-like identifier, and refer to it from every other page. On this site the Person has the id https://mohitgoyal.in/#person. The WebSite says its publisher is that id, the ProfilePage says its main entity is that id, and every blog post and project names the same Person as author.

Rendering diagram…

The result is one connected graph instead of dozens of disconnected snippets. An engine reading any page learns that it belongs to the same site and the same person as every other page. For a business, use an Organization with an @id in the same way.

What does a good JSON-LD block look like?

When a page has several entities, wrap them in an @graph array. Here is a trimmed version of the markup on a blog post:

json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "BlogPosting",
      "@id": "https://mohitgoyal.in/blog/example#post",
      "headline": "Post title",
      "datePublished": "2026-10-25",
      "author": { "@type": "Person", "@id": "https://mohitgoyal.in/#person", "name": "Mohit Goyal" },
      "isPartOf": { "@id": "https://mohitgoyal.in/#website" }
    },
    {
      "@type": "BreadcrumbList",
      "itemListElement": [
        { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://mohitgoyal.in/" },
        { "@type": "ListItem", "position": 2, "name": "Blog", "item": "https://mohitgoyal.in/blog" }
      ]
    }
  ]
}

One detail worth copying: when the JSON is printed inside a script tag, I escape every < as <. That way no text from the content, however odd, can close the script tag early and inject markup.

What mistakes should you avoid?

Wrong data is worse than no data

My home page used to output an FAQPage where every quick question carried the same About text as its answer. That is low-quality markup, so I removed it. If the data is not true and distinct, leave the type out.

The other mistakes I see most often:

  • Marking up what is not on the page. Reviews, prices or FAQs that visitors cannot see break Google's guidelines and can cost you rich results.
  • Client-side injection. JSON-LD added by a script after load may never be seen by crawlers that do not run JavaScript. Render it on the server.
  • Hand-written blocks that drift. A price or address changes on the page but not in the markup. Generate the JSON-LD from the same data the page uses, so it cannot go stale.
  • Several unrelated main types on one page. Pick what the page is about. A blog post is a BlogPosting, not also a Product and a LocalBusiness.
  • Invented ratings. Never add an aggregateRating you cannot back up with reviews shown on the page.

How do you add JSON-LD in Next.js or WordPress?

  1. 1

    Decide the main type per template

    Use the table above. Templates, not individual pages, are what you mark up.

  2. 2

    Generate from page data

    In Next.js or TanStack Start, build the object from the same data the page renders and print it in a script tag on the server. In WordPress, use your SEO plugin's schema settings or a small plugin that reads the post's fields.

  3. 3

    Link to your main entity

    Every page refers to the same Person or Organization @id.

  4. 4

    Test before launch

    Run each template through the Rich Results Test and the Schema Markup Validator.

  5. 5

    Watch Search Console

    After launch, check the enhancement reports for errors and warnings, and fix them at the template level.

For a single page, such as a local business home page or one event, the free Schema Markup Generator writes the block for you from a plain description and never invents values. For the rest of the technical setup on a Next.js site, see my technical SEO checklist for Next.js.

Does structured data help with AI answers?

It helps engines get your facts right, which is the first step to being quoted. Structured data is one part of that. The others are server-rendered pages, answer-first writing and consistent facts across your site, covered in how to get cited in AI Overviews.

I add schema at the template level on every site I build, and I audit and fix it on existing sites through my technical SEO and Core Web Vitals service.

Frequently asked

What is JSON-LD?+

JSON for Linked Data. It is a way to add structured data to a page in a single script tag, using the schema.org vocabulary, without changing the visible HTML. Google recommends it over Microdata and RDFa.

Does structured data improve rankings?+

Not directly. It helps search engines understand the page and can make it eligible for rich results, which tend to raise clicks. Answer engines also use it as a clean source of facts.

Where should the JSON-LD script go?+

In the page's HTML, usually the head. It must be in the server-rendered HTML, not injected later by JavaScript that some crawlers will not run.

Should I still add FAQ schema?+

Add it when the page has a real, visible FAQ with distinct answers. Google now shows FAQ rich results mainly for well-known government and health sites, but the markup still describes your questions and answers to search and AI engines.

How do I test JSON-LD?+

Run the page through Google's Rich Results Test for rich result eligibility and the Schema Markup Validator for a full schema.org check. Then inspect the live URL in Search Console after launch.

Can I generate JSON-LD without writing code?+

Yes. My free Schema Markup Generator turns a plain description into valid JSON-LD for a local business, organization, product, article, FAQ, event or app, ready to paste.

Mohit Goyal

Written by Mohit Goyal

Senior Web Developer in Gurugram, India. 100+ fast, SEO-friendly sites shipped in 4+ years with Next.js, React and WordPress, including the procol.ai rebuild. Send me your next project.

Keep reading

Let's build

Have a site that needs to be fast, rank and convert?

Open to Work. Usually replies within a day.