Skip to main content
Beta: Front-End Checklist is currently in beta. Some issues are still being fixed. Thanks for your patience.
SEOHigh

Add structured data markup

Schema.org structured data (JSON-LD) is implemented for rich search results.

Utilities
Quick take
Typical fix time 25 min
  • Structured data enables rich snippets in search results
  • Use JSON-LD format (Google recommended)
  • Common types: Article, Product, FAQ, HowTo, LocalBusiness
  • Validate with Google Rich Results Test
Why it matters: Structured data enables rich snippets with stars, prices, images, and FAQ dropdowns in search results—significantly increasing click-through rates.

Rule Details

Structured data helps search engines understand your content and enables rich results.

Code Example

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Executive Widget",
  "description": "Premium quality widget for professionals",
  "image": "https://example.com/images/widget.jpg",
  "offers": {
    "@type": "Offer",
    "price": "49.99",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock"
  }
}
</script>

Why It Matters

Structured data enables rich snippets with stars, prices, images, and FAQ dropdowns in search results—significantly increasing click-through rates.

Common Schema Types

TypeUse ForRich Result
ArticleBlog posts, newsAuthor, date, image
ProductE-commerce itemsPrice, rating, availability
FAQFAQ pagesExpandable questions
HowToTutorials, guidesStep-by-step instructions
LocalBusinessPhysical locationsMap, hours, reviews
OrganizationCompany infoLogo, social profiles
BreadcrumbListNavigation pathBreadcrumb trail

Article Schema

// components/ArticleSchema.tsx
interface ArticleSchemaProps {
  title: string
  description: string
  image: string
  datePublished: string
  dateModified: string
  author: string
  url: string
}
 
export function ArticleSchema({
  title,
  description,
  image,
  datePublished,
  dateModified,
  author,
  url,
}: ArticleSchemaProps) {
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'Article',
    headline: title,
    description,
    image,
    datePublished,
    dateModified,
    author: {
      '@type': 'Person',
      name: author,
    },
    publisher: {
      '@type': 'Organization',
      name: 'Example Company',
      logo: {
        '@type': 'ImageObject',
        url: 'https://example.com/logo.png',
      },
    },
    mainEntityOfPage: {
      '@type': 'WebPage',
      '@id': url,
    },
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
    />
  )
}

Product Schema

interface ProductSchemaProps {
  name: string
  description: string
  image: string
  price: number
  currency: string
  availability: 'InStock' | 'OutOfStock' | 'PreOrder'
  rating?: number
  reviewCount?: number
  brand?: string
  sku?: string
}
 
export function ProductSchema({
  name,
  description,
  image,
  price,
  currency,
  availability,
  rating,
  reviewCount,
  brand,
  sku,
}: ProductSchemaProps) {
  const schema: any = {
    '@context': 'https://schema.org',
    '@type': 'Product',
    name,
    description,
    image,
    sku,
    brand: brand ? { '@type': 'Brand', name: brand } : undefined,
    offers: {
      '@type': 'Offer',
      price: price.toFixed(2),
      priceCurrency: currency,
      availability: `https://schema.org/${availability}`,
    },
  }
 
  if (rating && reviewCount) {
    schema.aggregateRating = {
      '@type': 'AggregateRating',
      ratingValue: rating,
      reviewCount,
    }
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
    />
  )
}

FAQ Schema

interface FAQItem {
  question: string
  answer: string
}
 
export function FAQSchema({ items }: { items: FAQItem[] }) {
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'FAQPage',
    mainEntity: items.map(item => ({
      '@type': 'Question',
      name: item.question,
      acceptedAnswer: {
        '@type': 'Answer',
        text: item.answer,
      },
    })),
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
    />
  )
}
interface BreadcrumbItem {
  name: string
  url: string
}
 
export function BreadcrumbSchema({ items }: { items: BreadcrumbItem[] }) {
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'BreadcrumbList',
    itemListElement: items.map((item, index) => ({
      '@type': 'ListItem',
      position: index + 1,
      name: item.name,
      item: item.url,
    })),
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
    />
  )
}

Organization Schema

export function OrganizationSchema() {
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'Organization',
    name: 'Example Company',
    url: 'https://example.com',
    logo: 'https://example.com/logo.png',
    contactPoint: {
      '@type': 'ContactPoint',
      telephone: '+1-555-555-5555',
      contactType: 'customer service',
    },
    sameAs: [
      'https://twitter.com/example',
      'https://www.linkedin.com/company/example',
      'https://github.com/example',
    ],
  }
 
  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
    />
  )
}

Next.js App Router Integration

// app/blog/[slug]/page.tsx
import { ArticleSchema } from '@/components/ArticleSchema'
 
export default async function BlogPost({ params }) {
  const post = await getPost(params.slug)
 
  return (
    <>
      <ArticleSchema
        title={post.title}
        description={post.excerpt}
        image={post.image}
        datePublished={post.createdAt}
        dateModified={post.updatedAt}
        author={post.author.name}
        url={`https://example.com/blog/${params.slug}`}
      />
      <article>{/* Content */}</article>
    </>
  )
}

Exceptions

  • Necessary utility or compliance pages can be intentionally brief and should not be judged by the same editorial-depth expectations as ranking-focused content.
  • AI-assisted drafting is not a failure by itself; flag unsupported claims, missing editorial review, or low-originality output instead.
  • When a page has both trust-signal issues and crawl/index problems, make the page eligible to rank first and then improve the content quality signals.

Standards

  • Use these references as the standard for the final search-facing HTML, metadata, and crawl behavior.
  • Check the implementation against Google Search Central: Search Essentials before treating the rule as satisfied.
  • Check the implementation against Google Search Central documentation before treating the rule as satisfied.

Verification

Automated Checks

Manual Checks

  • Verify JSON syntax is valid

Use with AI

Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.

Check

Verify implementation

Analyze if this webpage implements structured data using Schema.org vocabulary. Check for JSON-LD, Microdata, or RDFa markup.

Fix

Auto-fix issues

Add appropriate Schema.org structured data to this webpage based on its content type (Article, Product, LocalBusiness, etc.).

Explain

Learn more

Explain how structured data helps search engines understand page content and enables rich snippets in search results.

Review

Code review

Review metadata generation, rendered HTML, structured data, and response headers related to Add structured data markup. Flag exact routes or templates where search-facing output violates the rule, and describe how to verify the final page output.

Sources

References used to support the guidance in this rule.

Further Reading

Tools and supplementary material for exploring the topic in more depth.

Google Search Console
search.google.comTool

Rules that often go hand-in-hand with this one.

Use valid JSON-LD structured data

Validates JSON-LD structured data for syntax correctness, required properties, and schema.org compliance

SEO
Add VideoObject schema to video pages

Checks for VideoObject structured data on pages containing video content to enable video rich results in Google Search.

SEO
Implement valid Article structured data

Validates that articles use the correct Schema.org properties for improved search visibility.

SEO
Add Review schema markup

Validates Review and AggregateRating schema on product, service, and business pages to enable star-rating rich results.

SEO

Was this rule helpful?

Your feedback helps improve rule quality. This stays internal for now.

Loading feedback...
0 / 385