Schema.org Structured Data: The Complete Guide for Rich Search Results
SEO8 min read

Schema.org Structured Data: The Complete Guide for Rich Search Results

Master structured data for Google rich results. Copy-paste JSON-LD templates for articles, products, FAQs, and more. Boost your click-through rates.

Katsau

Katsau Team

December 19, 2025

Share:

Structured data helps search engines understand your content. When implemented correctly, your pages can display rich results—stars, prices, FAQs, and more—directly in search results. This guide covers everything from basics to advanced implementations.

What is Structured Data?

Structured data is a standardized format for providing information about a page. It uses vocabulary from Schema.org and is typically implemented as JSON-LD.

{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "How to Implement Structured Data",
  "author": {
    "@type": "Person",
    "name": "John Doe"
  }
}

When Google reads this, it understands:

  • This page is an Article
  • The title is "How to Implement Structured Data"
  • The author is John Doe

This enables rich results in search:

┌────────────────────────────────────────────────────┐
│ How to Implement Structured Data                   │
│ example.com › blog › structured-data               │
│ By John Doe · 5 min read · Dec 19, 2025            │
│ Learn how to add structured data to your website...│
└────────────────────────────────────────────────────┘

Why It Matters

Pages with structured data can see:

  • 30-40% higher click-through rates with rich results
  • Better understanding by search engines
  • Voice search optimization (Google Assistant, Siri)
  • Knowledge Graph inclusion

JSON-LD vs Microdata vs RDFa

Three formats exist. JSON-LD is Google's recommended format:

Format Implementation Google Preference
JSON-LD <script> in head Recommended
Microdata Inline HTML attributes Supported
RDFa Inline HTML attributes Supported

JSON-LD advantages:

  • Doesn't clutter HTML
  • Easy to generate dynamically
  • Simple to maintain
  • Can be placed anywhere in the document

Essential Schema Types

1. Organization

Tell Google about your company:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "Your Company Name",
  "url": "https://example.com",
  "logo": "https://example.com/logo.png",
  "sameAs": [
    "https://twitter.com/yourcompany",
    "https://linkedin.com/company/yourcompany",
    "https://github.com/yourcompany"
  ],
  "contactPoint": {
    "@type": "ContactPoint",
    "telephone": "+1-555-555-5555",
    "contactType": "customer service",
    "availableLanguage": ["English"]
  }
}
</script>

2. WebSite with Search

Enable sitelinks search box:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "Your Site Name",
  "url": "https://example.com",
  "potentialAction": {
    "@type": "SearchAction",
    "target": {
      "@type": "EntryPoint",
      "urlTemplate": "https://example.com/search?q={search_term_string}"
    },
    "query-input": "required name=search_term_string"
  }
}
</script>

3. Article

For blog posts and news articles:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "Your Article Title",
  "description": "A brief description of the article",
  "image": [
    "https://example.com/image-1x1.jpg",
    "https://example.com/image-4x3.jpg",
    "https://example.com/image-16x9.jpg"
  ],
  "datePublished": "2025-12-19T08:00:00+00:00",
  "dateModified": "2025-12-19T10:30:00+00:00",
  "author": {
    "@type": "Person",
    "name": "Author Name",
    "url": "https://example.com/author/name"
  },
  "publisher": {
    "@type": "Organization",
    "name": "Publisher Name",
    "logo": {
      "@type": "ImageObject",
      "url": "https://example.com/logo.png"
    }
  },
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://example.com/article-url"
  }
}
</script>

4. Product

For e-commerce product pages:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Product Name",
  "image": [
    "https://example.com/product-1.jpg",
    "https://example.com/product-2.jpg"
  ],
  "description": "Product description goes here",
  "sku": "SKU123",
  "brand": {
    "@type": "Brand",
    "name": "Brand Name"
  },
  "offers": {
    "@type": "Offer",
    "url": "https://example.com/product",
    "priceCurrency": "USD",
    "price": "99.99",
    "priceValidUntil": "2025-12-31",
    "availability": "https://schema.org/InStock",
    "itemCondition": "https://schema.org/NewCondition"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.5",
    "reviewCount": "127"
  },
  "review": {
    "@type": "Review",
    "reviewRating": {
      "@type": "Rating",
      "ratingValue": "5"
    },
    "author": {
      "@type": "Person",
      "name": "Happy Customer"
    },
    "reviewBody": "Great product, highly recommend!"
  }
}
</script>

5. FAQ Page

Get expandable FAQs in search results:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "What is structured data?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Structured data is a standardized format for providing information about a page to search engines."
      }
    },
    {
      "@type": "Question",
      "name": "How do I implement structured data?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Add JSON-LD scripts to your page's HTML. The recommended placement is in the <head> section."
      }
    },
    {
      "@type": "Question",
      "name": "Does structured data improve SEO?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "While not a direct ranking factor, structured data enables rich results which can significantly improve click-through rates."
      }
    }
  ]
}
</script>

6. How-To

Step-by-step instructions:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "HowTo",
  "name": "How to Build a Website",
  "description": "Learn the basics of building a website",
  "totalTime": "PT2H",
  "estimatedCost": {
    "@type": "MonetaryAmount",
    "currency": "USD",
    "value": "0"
  },
  "supply": [
    {
      "@type": "HowToSupply",
      "name": "Computer"
    },
    {
      "@type": "HowToSupply",
      "name": "Text editor"
    }
  ],
  "tool": [
    {
      "@type": "HowToTool",
      "name": "Web browser"
    }
  ],
  "step": [
    {
      "@type": "HowToStep",
      "name": "Choose a domain",
      "text": "Select and register a domain name for your website.",
      "url": "https://example.com/how-to#step1",
      "image": "https://example.com/step1.jpg"
    },
    {
      "@type": "HowToStep",
      "name": "Set up hosting",
      "text": "Choose a web hosting provider and set up your account.",
      "url": "https://example.com/how-to#step2",
      "image": "https://example.com/step2.jpg"
    },
    {
      "@type": "HowToStep",
      "name": "Build your site",
      "text": "Create your website using HTML, CSS, and JavaScript.",
      "url": "https://example.com/how-to#step3",
      "image": "https://example.com/step3.jpg"
    }
  ]
}
</script>

7. Breadcrumb

Navigation breadcrumbs:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://example.com"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Blog",
      "item": "https://example.com/blog"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "Structured Data Guide",
      "item": "https://example.com/blog/structured-data"
    }
  ]
}
</script>

8. Local Business

For physical businesses:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "name": "Your Business Name",
  "image": "https://example.com/storefront.jpg",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "123 Main Street",
    "addressLocality": "San Francisco",
    "addressRegion": "CA",
    "postalCode": "94102",
    "addressCountry": "US"
  },
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": 37.7749,
    "longitude": -122.4194
  },
  "url": "https://example.com",
  "telephone": "+1-555-555-5555",
  "openingHoursSpecification": [
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
      "opens": "09:00",
      "closes": "17:00"
    }
  ],
  "priceRange": "$$"
}
</script>

9. Software Application

For apps and tools:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "SoftwareApplication",
  "name": "Your App Name",
  "operatingSystem": "Web, iOS, Android",
  "applicationCategory": "DeveloperApplication",
  "offers": {
    "@type": "Offer",
    "price": "0",
    "priceCurrency": "USD"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.8",
    "ratingCount": "1024"
  }
}
</script>

Next.js Implementation

Dynamic structured data in Next.js App Router:

// app/blog/[slug]/page.tsx
import { Metadata } from 'next';

interface BlogPost {
  title: string;
  description: string;
  image: string;
  date: string;
  author: string;
  slug: string;
}

async function getPost(slug: string): Promise<BlogPost> {
  // Fetch post data
}

export async function generateMetadata({ params }): Promise<Metadata> {
  const post = await getPost(params.slug);

  return {
    title: post.title,
    description: post.description,
    openGraph: {
      title: post.title,
      description: post.description,
      images: [post.image],
      type: 'article',
      publishedTime: post.date,
      authors: [post.author],
    },
  };
}

export default async function BlogPost({ params }) {
  const post = await getPost(params.slug);

  const jsonLd = {
    '@context': 'https://schema.org',
    '@type': 'Article',
    headline: post.title,
    description: post.description,
    image: post.image,
    datePublished: post.date,
    author: {
      '@type': 'Person',
      name: post.author,
    },
    publisher: {
      '@type': 'Organization',
      name: 'Your Site',
      logo: {
        '@type': 'ImageObject',
        url: 'https://example.com/logo.png',
      },
    },
  };

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
      />
      <article>
        <h1>{post.title}</h1>
        {/* Article content */}
      </article>
    </>
  );
}

Validation Tools

Always validate your structured data:

  1. Google Rich Results Test

  2. Schema Markup Validator

  3. Google Search Console

    • Check the "Enhancements" section
    • See which rich results are indexed

Programmatic Validation

Validate structured data across your site using an API:

async function validateStructuredData(url) {
  const response = await fetch(
    `https://api.katsau.com/v1/analyze?url=${encodeURIComponent(url)}`,
    {
      headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
    }
  );

  const { data } = await response.json();

  // Check structured data
  if (data.structuredData && data.structuredData.length > 0) {
    console.log('Found structured data:');
    data.structuredData.forEach(schema => {
      console.log(`- ${schema['@type']}`);
    });
  } else {
    console.log('No structured data found');
  }

  return data.structuredData;
}

// Audit entire sitemap
async function auditSitemap(urls) {
  const results = [];

  for (const url of urls) {
    const schemas = await validateStructuredData(url);
    results.push({
      url,
      hasStructuredData: schemas.length > 0,
      types: schemas.map(s => s['@type']),
    });
  }

  // Report
  const withSchema = results.filter(r => r.hasStructuredData);
  console.log(`${withSchema.length}/${results.length} pages have structured data`);

  return results;
}

Common Mistakes

1. Missing Required Properties

Each schema type has required fields:

// Wrong: Article missing headline
{
  "@type": "Article",
  "description": "..."
}

// Correct
{
  "@type": "Article",
  "headline": "Article Title",
  "description": "..."
}

2. Invalid Image URLs

Images must be absolute URLs:

// Wrong
"image": "/images/photo.jpg"

// Correct
"image": "https://example.com/images/photo.jpg"

3. Incorrect Date Format

Use ISO 8601 format:

// Wrong
"datePublished": "December 19, 2025"

// Correct
"datePublished": "2025-12-19T08:00:00+00:00"

4. Spammy Content

Don't add structured data for content that doesn't exist on the page:

// Wrong: Fake rating not visible on page
"aggregateRating": {
  "ratingValue": "5",
  "reviewCount": "9999"
}

Best Practices

  1. Match visible content - Structured data must reflect what users see
  2. Be specific - Use the most specific type (BlogPosting vs Article)
  3. Keep it updated - Update structured data when content changes
  4. Test regularly - Rich results can stop appearing if data becomes invalid
  5. Don't overdo it - Only add relevant schemas

Conclusion

Structured data is one of the highest-ROI SEO techniques. It's relatively easy to implement and can significantly improve how your pages appear in search results.

Key takeaways:

  1. Use JSON-LD format (Google's preference)
  2. Start with Organization, WebSite, and Article
  3. Validate with Google's Rich Results Test
  4. Monitor in Search Console
  5. Match structured data to visible content

Need to audit structured data across your site? Try Katsau's analyze endpoint — extract and validate JSON-LD from any URL.

Ready to build?

Try Katsau API

Extract metadata, generate link previews, and monitor URLs with our powerful API. Start free with 1,000 requests per month.