Schema Markup Tutorial: Add JSON-LD to Any Website (Step-by-Step)

Last Updated: February 25, 2026 · 15 min read

Schema markup is the layer of code that transforms an ordinary search result into a rich result with star ratings, images, prices, or FAQ dropdowns. This tutorial walks through every step — from understanding what schema is to deploying validated JSON-LD across HTML, WordPress, Shopify, and Next.js.

✅ What you'll achieve

By the end of this tutorial you will have working, validated schema markup deployed on a real page and eligible for rich results in Google Search.

Part 1: Understand What You're Adding

Schema markup is a JSON block placed inside a <script type="application/ld+json"> tag. It is invisible to visitors but readable by Google. Here is the minimal structure all schema markup follows:

<script type="application/ld+json">
{
  "@context": "https://schema.org",   ← always this, always
  "@type":    "Article",              ← what kind of thing this is
  "headline": "My Article Title",     ← properties that describe it
  "datePublished": "2026-02-25"
}
</script>
@context

Always "https://schema.org" — tells Google which vocabulary you're using

@type

The type of thing (Article, Product, Recipe, FAQPage, etc.)

properties

The specific facts you're declaring (name, price, datePublished, etc.)

Part 2: Pick Your Schema Type

Match the schema type to your page content:

Page typeSchema typeRich result unlocked
Blog post / articleArticleArticle card, Top Stories
Product pageProduct + OfferPrice, stars, availability
RecipeRecipeRecipe card with image & time
FAQ sectionFAQPageExpandable Q&A dropdowns
How-to guideHowToNumbered step previews
Local businessLocalBusiness subtypeKnowledge Panel, Maps
EventEventEvent carousel listing
Job listingJobPostingGoogle Jobs listing
VideoVideoObjectVideo thumbnail + duration

Part 3: Write Your First Schema

Let's add Article schema to a blog post. Fill in your own values where you see placeholders:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "REPLACE: Your article title (max 110 chars)",
  "datePublished": "REPLACE: 2026-02-25T09:00:00Z",
  "dateModified":  "REPLACE: 2026-02-25T09:00:00Z",
  "author": {
    "@type": "Person",
    "name": "REPLACE: Your Name",
    "url":  "REPLACE: https://yoursite.com/about"
  },
  "publisher": {
    "@type": "Organization",
    "name": "REPLACE: Site Name",
    "logo": {
      "@type": "ImageObject",
      "url": "REPLACE: https://yoursite.com/logo.png"
    }
  },
  "image": "REPLACE: https://yoursite.com/article-image.jpg",
  "description": "REPLACE: 1-2 sentence summary of the article."
}
</script>

Part 4: Validate Before Deploying

1

Copy your JSON-LD block (just the JSON, not the <script> tags)

2

Go to SchemaValidator.org → paste into the code input

3

Fix all red errors. Common ones: missing required field, invalid date format, empty string value

4

Address amber warnings (missing recommended properties like image, description)

5

Once error-free, proceed to deployment

Part 5: Add to Your Platform

Plain HTML

Paste the <script> block inside the <head> or just before </body>:

<html>
  <head>
    <title>My Article</title>
    <script type="application/ld+json">
    { ...your schema here... }
    </script>
  </head>
  <body>...</body>
</html>

WordPress (without a plugin)

Add to your theme's functions.php:

function add_article_schema() {
  if ( is_single() ) {
    $schema = array(
      '@context'      => 'https://schema.org',
      '@type'         => 'Article',
      'headline'      => get_the_title(),
      'datePublished' => get_the_date('c'),
      'dateModified'  => get_the_modified_date('c'),
      'author'        => array(
        '@type' => 'Person',
        'name'  => get_the_author(),
      ),
    );
    echo '<script type="application/ld+json">'
      . wp_json_encode($schema) . '</script>';
  }
}
add_action( 'wp_head', 'add_article_schema' );

Next.js (App Router)

// app/blog/[slug]/page.tsx
export default function BlogPost({ post }) {
  const schema = {
    "@context": "https://schema.org",
    "@type": "Article",
    "headline": post.title,
    "datePublished": post.publishedAt,
    "author": { "@type": "Person", "name": post.author }
  };
  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
      />
      <article>...</article>
    </>
  );
}

Shopify

Edit your theme's product.liquid or article.liquid:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "{{ product.title | json }}",
  "description": "{{ product.description | strip_html | json }}",
  "image": "{{ product.featured_image | img_url: '1024x' }}",
  "offers": {
    "@type": "Offer",
    "price": "{{ product.price | money_without_currency }}",
    "priceCurrency": "{{ shop.currency }}",
    "availability": "{% if product.available %}
      https://schema.org/InStock
      {% else %}
      https://schema.org/OutOfStock
      {% endif %}"
  }
}
</script>

Part 6: Confirm It's Working

🔍 View page source

Right-click → View Page Source → Ctrl+F "application/ld+json". If you see your schema, the <script> block is rendering server-side (correct). If you can't find it in source, it is being injected by JavaScript only — fix this.

🔍 Google Rich Results Test

Paste your page URL at search.google.com/test/rich-results. You should see your schema type detected. If not shown, the page may not be publicly accessible or the schema has a rendering issue.

🔍 Google Search Console

After 1–2 weeks post-deploy, check GSC Enhancements. You'll see your schema types listed with valid/error counts. This is your long-term monitoring dashboard.

Frequently Asked Questions

Do I need to add schema markup to every page?

No. Prioritise pages that stand to gain the most from rich results: product pages, recipe pages, FAQ sections, article pages, and local business pages. Adding schema to pages with thin or irrelevant content provides limited benefit.

What happens if I have errors in my schema markup?

Errors prevent Google from generating rich results for that page. Warnings (missing recommended fields) allow the schema to be processed but may reduce rich result quality. Always fix all errors before deploying.

How long until schema markup shows as rich results in Google?

Google typically crawls and processes schema within days to a few weeks of deployment. Rich results then appear when Googlebot recrawls the page and confirms the schema is valid. Monitor via Google Search Console Enhancements tab.

Can I add multiple schema types to one page?

Yes — this is normal and encouraged. Use separate <script type="application/ld+json"> blocks for each schema type. Common combinations: Article + BreadcrumbList + Organization, or Product + BreadcrumbList + FAQPage.

Does schema markup directly improve Google rankings?

Not directly. Schema is not a confirmed direct ranking factor. However, rich results dramatically improve click-through rates (often +20–50%), which increases traffic and sends positive user-behaviour signals to Google.

Is it safe to copy schema templates from this tutorial?

Yes, but replace all placeholder values with your actual content. Using real, accurate data is essential — Google’s spam policies explicitly prohibit misleading or inaccurate structured data.

What is the minimum viable schema I should add to a new site?

Start with: Organization schema (sitewide), BreadcrumbList on all pages, and the primary content type (Article, Product, LocalBusiness, etc.) on each relevant page. These three cover most common rich result opportunities.

Do I need a plugin or CMS tool to add schema markup?

No. Schema is just a JSON block in a script tag — you can add it directly to HTML, PHP, or any template. Plugins (Yoast, RankMath) automate generation for WordPress but are not required for non-WordPress sites.

Ready to Validate Your Schema?

Paste your JSON-LD and get an instant report — free, no login required.

Validate Schema Markup →