How to Add Schema Markup to a Website (JSON-LD)
Add schema markup by choosing a schema.org type that matches visible content, writing or generating JSON-LD, placing a script tag in the page head, and validating with Google's Rich Results Test.
To add schema markup to a website, choose a schema.org type that matches what visitors see on the page, build a JSON-LD object with the required fields, insert it as a <script type="application/ld+json"> block in the document head, and validate the live URL with Google's Rich Results Test before merge. JSON-LD keeps structured data separate from your visible HTML, which makes diffs and reviews straightforward on code-heavy sites.
You fixed the title tag and the canonical, but Search Console still lists "No structured data" on a URL that should qualify for rich results. The page reads fine in the browser; the gap is machine-readable context. Schema markup closes that gap by describing the entity on the page in a format crawlers parse without guessing from layout alone.
This guide is a shipping checklist, not a catalog of every schema.org type. It walks through the four steps teams use on SaaS and developer sites, when a free generator beats hand-written JSON, and how BreadcrumbList fits next to page-level types. For crawlability and canonical rules that sit beside markup, see SEO for developers. For FAQ-rich results specifically, see featured snippet optimization, which covers answer blocks and eligibility from a different angle than this markup workflow.
What Schema Markup Does on a Live Page
Schema markup is vocabulary from schema.org that labels entities on a page: an article, a product, an organization, a FAQ pair, or a breadcrumb trail. Search engines use that label together with visible content when they interpret the page and when they evaluate rich-result eligibility.
Google's guidance treats structured data as a way to explicitly describe page meaning (Google structured data introduction). It does not replace good copy, fast rendering, or crawlable links. It gives the crawler a second channel that matches what you already show users.
Practical rule: if a field in JSON-LD is not supported by visible content on the page, do not publish it. Mismatched markup is how valid syntax still fails manual review and rich-result policies.
Step 1: Pick a Schema Type That Matches the Page
Start from the page's job, not from a checklist of every type Google once mentioned in a blog post.
| Page you ship | Typical JSON-LD type | Only use when |
|---|---|---|
| Homepage or about | Organization | Legal name, logo, and site URL are stable |
| Blog post or guide | Article or BlogPosting | Headline, author, and dates match the byline |
| Product or pricing detail | Product or SoftwareApplication | Offers and descriptions match the live UI |
| Visible FAQ section | FAQPage | Each question and answer appears on the page |
| Breadcrumb UI | BreadcrumbList | The trail matches links users can click |
One URL can carry multiple script blocks when each type describes a different aspect of the same page, such as BlogPosting plus BreadcrumbList. Do not stack conflicting types that describe the same entity twice with different facts.
Step 2: Build the JSON-LD Block
A minimal Article block looks like this:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "How to Add Schema Markup to a Website",
"author": {
"@type": "Person",
"name": "Alex Rivera"
},
"datePublished": "2026-10-28",
"image": "https://example.com/blog/schema-guide/hero.jpg"
}
</script>
Use absolute URLs in image and url fields when the validator or Search Console examples expect them. Keep dates in ISO 8601 form. Match the headline to the visible H1 unless your template intentionally separates title tag and heading.
For a FAQ section that users can read without expanding a hidden accordion, FAQPage wraps each pair:
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [{
"@type": "Question",
"name": "Where does JSON-LD go?",
"acceptedAnswer": {
"@type": "Answer",
"text": "In a script tag, usually in the head."
}
}]
}
If the answer text exists only in a CMS field that never renders, the markup is not supported. The answer string should be the same substance a person sees on the page.
Step 3: Add the Script to Your Site
Place the block where every indexable route can inherit or override it:
- Shared layout. Put Organization or WebSite markup in the root layout so the homepage and inner pages share one source of truth.
- Template per page type. Blog layouts emit BlogPosting; product layouts emit SoftwareApplication; FAQ templates emit FAQPage.
- Server output, not client-only injection. Important markup should appear in the HTML response crawlers fetch. If JSON-LD is added only after hydration, verify with
curlthat production still includes the script.
In Laravel, Inertia, or similar stacks, a dedicated Blade partial or head component keeps JSON-LD out of business logic. In Next.js or Astro, a small helper that serializes an array to a script tag avoids hand-escaped strings in every page.
curl -sS https://example.com/blog/your-post | grep -F 'application/ld+json'
If that command returns nothing on a route you care about, fix the template before opening a Search Console ticket.
Step 4: Validate Before You Merge
Validation is a merge gate, not a post-launch chore.
- Rich Results Test. Paste the staging URL or HTML into Google's Rich Results Test. Resolve errors first; treat warnings as a backlog ranked by page priority.
- Schema Markup Validator. Use validator.schema.org when you need schema.org-level detail beyond Google's feature reports.
- Compare to rendered content. Open the page in a browser and confirm every marked-up field has a visible counterpart.
- Re-run after deploy. Cache and CDN layers can lag; test the production URL once the release is live.
Wire the Rich Results Test into your release checklist for template changes the same way you run lint on pull requests. One broken JSON comma should fail the build when the route is business-critical.
When to Use a Generator vs Hand-Written Markup
Hand-written JSON-LD in a shared component is the right default for types your site emits on every deploy: Organization, BlogPosting, BreadcrumbList. You control the fields, code review sees the diff, and generators do not drift from your design system.
A generator helps when you prototype an unfamiliar type, ship a one-off landing page, or teach stakeholders which fields matter. Orchory's free schema markup generator builds JSON-LD for Organization, LocalBusiness, Article, Product, FAQ, Video, and related types from form fields, so you copy a block into your template without memorizing schema.org property names.
For breadcrumb trails that must match visible navigation, use the dedicated breadcrumb schema generator so ListItem order, names, and URLs stay aligned with the UI. Generators do not replace deployment; they shorten the blank-page step before your layout component owns the output.
More free utilities live on the Orchory tools hub. When you want pages that ship markup as part of a reviewed pull request workflow, send your site and Orchory sets up your first page with you on a call before you choose a plan.
BreadcrumbList and Sitewide Organization Markup
BreadcrumbList is easy to get wrong because the JSON order does not match how designers draw trails. Each ListItem needs a position integer, a name users recognize, and an item URL that resolves with HTTP 200. The last item may omit item when it represents the current page, but the visible breadcrumb should still label it consistently.
Organization belongs on the entity that owns the site: legal name, logo URL, and canonical site URL. Pair it with WebSite on the homepage when you publish a sitelinks search box, only if search is real and the target URL works.
Keep Organization in one place. Inner pages reference the publisher in BlogPosting or Article blocks instead of duplicating a full Organization object on every route unless your template system requires it for clarity.
Common Schema Markup Mistakes
- FAQPage without visible answers. Hidden accordions that never show full text in HTML fail the content parity rule.
- Product offers that do not match checkout. Price and currency in JSON-LD must match the price a buyer can pay.
- Article dates that never update. If the body changes materially, update visible dates and JSON-LD together.
- Invalid JSON. Trailing commas and unescaped quotes break the entire block, not one field.
- Markup only in Tag Manager. Client-injected JSON-LD may lag or fail; prefer server-rendered script tags for core types.
- Chasing every type at once. Ship accurate Organization plus one page-type schema before expanding.
Visit Orchory when you want keyword research, page briefs, and coding-agent prompts that include schema requirements in the acceptance criteria your team merges like any other engineering change.