Skip to main content
CodeRocket
SEOhightechnical

Add structured data markup

rule · structured-data

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

Code Example

HTML
<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

TSX
// 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

TSX
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

TSX
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) }}
    />
  )
}
TSX
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

TSX
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

TSX
// 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