Structured data without hand-writing JSON-LD

5 min read · Last checked

  • Generate LocalBusiness, Service and BreadcrumbList markup from the brief
  • Validate it with two free tools before it ships
  • Know which markup Google stopped rewarding in 2026

Structured data is a block of code on a page that states facts in a form a machine can read: this is a plumber, this is its address, this page is a service. The usual format is JSON-LD, a small script block in the page. It is the one place where an assistant is plainly better than writing by hand, because the syntax is fussy and the content comes straight from the client brief. It is also the place where an assistant is most tempted to invent.

What the audit checks, and what it does not

Two checks in the audit cover structured data:

CheckWhat triggers itSeverity
No structured data detectedA page has no JSON-LD blockInfo (0)
Invalid structured dataA JSON-LD block that is not valid JSONWarning (5)

Notice the first one costs nothing. Missing markup does not move the score; broken markup does. And "invalid" means the JSON does not parse, for example a trailing comma or smart quotes. The audit does not check that the markup is true, that it matches the page, or that it qualifies for a rich result in Google. Google's tools do that, and you should use them.

What a local business needs

  • A business type. Use the most specific LocalBusiness subtype that fits, such as Plumber, Dentist or Restaurant, on the home or contact page.
  • BreadcrumbList on pages more than one level down, which describes the path from the home page.
  • Service or Organization markup where a page is genuinely about one service.

A minimal local business block looks like this. The values are placeholders.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Plumber",
  "name": "Example Plumbing",
  "url": "https://example.com/",
  "telephone": "+1-555-0100",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "100 Main Street",
    "addressLocality": "Springfield",
    "addressRegion": "IL",
    "postalCode": "62701",
    "addressCountry": "US"
  },
  "areaServed": "Springfield, IL"
}
</script>

Look at the page source before you add anything. SEO plugins on WordPress often output some structured data already, and a second block that disagrees with the first is worse than none.

Generate it from the brief, and leave out what you don't know

The one rule that matters: a missing value is left out. An assistant asked for a complete LocalBusiness block will invent opening hours, a phone number or a rating to fill the gaps. Google's guidance is that structured data must match the visible text of the page. Wrong data is worse than a short block.

LocalBusiness JSON-LD from the brief

Write JSON-LD for the client's {home / contact} page, using the client brief above and the page text below.

- Use the schema.org type {LocalBusiness, or the most specific subtype that fits, for example Plumber or Dentist}.
- Include only properties whose values are in the brief or in the page text. If a value is missing, leave the property out. Do not guess opening hours, phone numbers, prices, ratings, social links or geo coordinates.
- Output one script block of type application/ld+json and nothing else. It must be valid JSON: double quotes, no trailing commas, no comments.

Page text:
{paste the page text}

BreadcrumbList for a set of pages

Write a BreadcrumbList in JSON-LD for each of these pages. Each line has the page URL and the name the site's navigation uses for it, from the home page down:

{Home | https://example.com/
Services | https://example.com/services/
Drain cleaning | https://example.com/services/drain-cleaning/}

Output valid JSON only, with positions starting at 1 and one item per level of the path. One script block of type application/ld+json per page.

Where the block goes

The block can sit in the head or the body of the page. On WordPress you have three routes: the schema fields of an SEO plugin you already run, a plugin that adds a snippet to one page, or a snippet in a child theme or page builder. Use one route per page so two blocks never disagree. Put the business-wide block on the home or contact page only. Keep the final text in the client's record, because it is the first thing to go stale when the business changes its hours or its phone number.

Validate it before it goes live

Use two free tools. Google's Rich Results Test shows whether Google can read the markup and whether the page qualifies for any rich result. The Schema Markup Validator checks the markup against schema.org without any Google-specific rules. Paste the code or the live URL into both. Then re-run the audit and confirm the missing issue is gone and no invalid one appeared.

If the validator reports a syntax error, give the assistant the block and the message. This is the job it does most reliably:

Fix broken JSON-LD

This JSON-LD block fails to parse. The validator says: {error message}

{paste the block}

Fix only the syntax. Tell me what you changed. Do not change, add or remove any values.

Don't bother with

  • FAQ markup for a rich result. Google's documentation says the FAQ rich result is no longer shown in Search. An update on 15 June 2026 recorded this. Do not add FAQPage markup expecting extra space in results. Keep the FAQ on the page as text.
  • Ratings and reviews you did not collect. Markup that describes something the page does not show is misleading, and it risks a manual action.
  • Types that do not describe the page. Course markup on a blog post, Product markup on a service. The markup has to describe what is on the page.
  • Every type you can think of. One accurate LocalBusiness block beats five guessed ones.

Next

Run your client sites from one place.

Free for up to 3 websites. No card.

Start free