Structured data is code you add to your pages that tells Google exactly what each piece of content is — in a format machines can read. Think of it as a translation layer between your human-readable content and Google's understanding of it.
Without structured data, Google sees "R5 000" and has to guess whether that's a price, a reference number, or part of a sentence. With structured data, Google knows: that's the priceOffered for a Service, in ZAR currency.
This isn't theoretical. Structured data directly enables rich results — the enhanced search listings with star ratings, FAQs, prices, and breadcrumbs that get 20–40% higher click-through rates than plain listings.
Why JSON-LD and not Microdata
There are three formats for structured data: JSON-LD, Microdata (HTML attributes), and RDFa. Google recommends JSON-LD. Here's why:
- Clean separation: JSON-LD lives in a
<script>tag, separate from your HTML. Microdata clutters your HTML withitemscope,itempropattributes everywhere. - Easier to generate dynamically: If you're using a CMS or static site generator, JSON-LD is just a JavaScript object that gets serialised. Much cleaner than injecting Microdata into templates.
- Google's preference: Google's documentation consistently uses JSON-LD in examples and explicitly states it's the recommended format.
Template 1: LocalBusiness
This goes on every page of your site, typically in the <head> or just
before </body>. It tells Google who you are, where you are, and how to contact you.
LocalBusiness — Homepage
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Your Business Name",
"description": "Short description of your business in 1-2 sentences.",
"url": "https://yourdomain.co.za",
"telephone": "+27150001234",
"email": "info@yourdomain.co.za",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Ornoco Blvd, Suite 4",
"addressLocality": "Mokopane",
"addressRegion": "Limpopo",
"postalCode": "0600",
"addressCountry": "ZA"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": -26.2041,
"longitude": 28.0473
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
"opens": "08:00",
"closes": "17:00"
},
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": "Saturday",
"opens": "09:00",
"closes": "13:00"
}
],
"priceRange": "R$$",
"image": "https://yourdomain.co.za/img/business-photo.webp",
"logo": "https://yourdomain.co.za/img/logo.webp",
"sameAs": [
"https://www.facebook.com/yourbusiness",
"https://www.instagram.com/yourbusiness",
"https://www.linkedin.com/company/yourbusiness"
]
}
</script>
SA-specific tips for LocalBusiness
- addressCountry must be
"ZA"— this is critical for local search ranking - priceRange uses Rands:
"R$"(budget),"R$$"(mid),"R$$$"(premium) - telephone must include the
+27international format - Include geo coordinates — they're a strong local ranking signal. Get them from Google Maps by right-clicking your location.
Template 2: Service
Place this on each individual service page. It describes what the service is, who provides it, and what it costs.
Service — Service Page
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Service",
"name": "Web Design and Development",
"description": "Custom website design and development for South African businesses, including SEO, performance optimisation, and conversion-focused design.",
"provider": {
"@type": "LocalBusiness",
"name": "Your Business Name",
"url": "https://yourdomain.co.za"
},
"areaServed": {
"@type": "Country",
"name": "South Africa"
},
"offers": {
"@type": "Offer",
"price": "25000",
"priceCurrency": "ZAR",
"priceSpecification": {
"@type": "PriceSpecification",
"price": "25000",
"priceCurrency": "ZAR",
"description": "Starting price for a 5-page system-intelligent website"
}
},
"hasOfferCatalog": {
"@type": "OfferCatalog",
"name": "Website Packages",
"itemListElement": [
{
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "Starter Website",
"description": "5-page static site with SEO and performance optimisation"
},
"price": "15000",
"priceCurrency": "ZAR"
},
{
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "Professional Website",
"description": "10-page site with CMS, blog, and conversion optimisation"
},
"price": "35000",
"priceCurrency": "ZAR"
}
]
}
}
</script>
Template 3: Article
Every blog post needs Article schema. This is the schema that enables rich article results in Google — with title, author, date, and publisher visible directly in search results.
Article — Blog Post
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Your Blog Post Title",
"description": "A compelling 1-2 sentence description of the post.",
"image": "https://yourdomain.co.za/img/post-image.webp",
"author": {
"@type": "Person",
"name": "Author Name",
"url": "https://yourdomain.co.za/who-is-author"
},
"publisher": {
"@type": "Organization",
"name": "Your Business Name",
"logo": {
"@type": "ImageObject",
"url": "https://yourdomain.co.za/img/logo.webp"
}
},
"datePublished": "2026-02-24",
"dateModified": "2026-02-24",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://yourdomain.co.za/blog/your-post-slug"
}
}
</script>
Template 4: FAQPage
FAQ schema is one of the highest-ROI schema types. It enables FAQ expandable results directly in Google search — potentially doubling your search result real estate.
FAQPage — FAQ Section
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "How much does a website cost in South Africa?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Website costs in South Africa range from R3 000 for basic template sites to R150 000+ for enterprise builds. A system-intelligent site typically costs R15 000 - R40 000 and includes SEO, performance optimisation, and conversion design as standard."
}
},
{
"@type": "Question",
"name": "How long does it take to build a website?",
"acceptedAnswer": {
"@type": "Answer",
"text": "A system-intelligent website typically takes 2-4 weeks from brief to launch. This includes planning, content strategy, design, development, testing, and deployment."
}
},
{
"@type": "Question",
"name": "Do you offer ongoing support?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. All builds include 30 days of post-launch support. Ongoing maintenance plans start at R1 500/month and include security updates, content updates, and performance monitoring."
}
}
]
}
</script>
Critical FAQ rule
The questions and answers in your FAQ schema must match the visible FAQ content on the page. If Google finds a mismatch between your schema and your visible content, they'll ignore the schema entirely — and may flag your site for manipulation.
Template 5: BreadcrumbList
Breadcrumb schema enables breadcrumb trails in Google search results. It helps users understand your site hierarchy before they click.
BreadcrumbList — Any Sub-Page
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://yourdomain.co.za/"
},
{
"@type": "ListItem",
"position": 2,
"name": "Services",
"item": "https://yourdomain.co.za/services/"
},
{
"@type": "ListItem",
"position": 3,
"name": "Web Design",
"item": "https://yourdomain.co.za/services/web-design"
}
]
}
</script>
How to validate your structured data
Before going live with any schema, validate it using these tools:
- Google Rich Results Test —
search.google.com/test/rich-results— tests for rich result eligibility and reports errors - Schema Markup Validator —
validator.schema.org— tests against the full Schema.org specification - Google Search Console — after deployment, check the "Enhancements" section for structured data errors
Fix every error and warning before considering the implementation complete. A single error can prevent the entire schema from being processed.
South Africa-specific considerations
- Currency: Always use
"ZAR"for priceCurrency — not "R" or "ZAR/" - Country code: Use
"ZA"for addressCountry, not "SA" or "ZAF" - Phone format: Use
+27XX XXX XXXXformat in schema, even if you display it as "07X XXX XXXX" on the page - Province names: Use the full name in addressRegion: "Gauteng", "Western Cape", "KwaZulu-Natal" — not abbreviations
- Area served: For national businesses, use
"Country": "South Africa". For local businesses, use"City": "Johannesburg"or"AdministrativeArea": "Gauteng"
Next: URL Architecture and Internal Linking Strategy — how to structure your URLs and link graph for maximum SEO impact.