Skip to content

Schema Markup

Structured data tells Google exactly what a page is about. It powers rich results (star ratings, FAQ accordions, breadcrumbs).


LocalBusiness + ProfessionalService in Layout.astro. See Global Layout & SEO for the full template.

Key types to set correctly:

"@type": ["LocalBusiness", "ProfessionalService"]
// or for a restaurant:
"@type": ["LocalBusiness", "Restaurant"]
// or for a travel agency:
"@type": ["LocalBusiness", "TravelAgency"]

Full type list - pick the most specific subtype available.


Enables Google’s FAQ accordion in search results. Requires 5+ questions.

const faqSchema = {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: [
{
"@type": "Question",
name: "How long does a website take?",
acceptedAnswer: {
"@type": "Answer",
text: "Most projects go live within 10-14 days of receiving all content.",
},
},
// ... 4+ more
],
};

Pass via the head slot:

<script slot="head" is:inline type="application/ld+json" set:html={JSON.stringify(faqSchema)} />

Already in the global LocalBusiness schema. Must use real numbers:

aggregateRating: {
"@type": "AggregateRating",
ratingValue: "4.9", // actual average
reviewCount: "38", // actual count
bestRating: "5",
worstRating: "1",
}

Add to individual blog post pages:

const articleSchema = {
"@context": "https://schema.org",
"@type": "Article",
headline: post.data.title,
description: post.data.description,
datePublished: post.data.pubDate.toISOString(),
author: {
"@type": "Organization",
name: "Juju Alpha",
url: "https://jujualpha.in",
},
};

Use Google’s Rich Results Test after deploying to confirm the schema is valid and eligible for rich results.

Common validation errors:

  • aggregateRating.reviewCount must be a number (not a string in some validators - test both)
  • telephone must include country code: +91XXXXXXXXXX
  • url must be the full production URL with https://