The short answer
sameAs.Key takeaways
- Schema markup is structured data; JSON-LD is the format Google recommends and the practical default.
- It’s not a ranking factor — it earns rich-result eligibility and makes your meaning machine-readable.
- A small set of types does most of the work: Organization, WebSite, Article, BreadcrumbList, FAQPage, Product, Review, Person, LocalBusiness.
- Always validate with the Rich Results Test and the Schema Markup Validator, and tie every entity to one canonical identity via sameAs.
- Copy-ready examples below for the three types people ask about most: Event, LocalBusiness and FAQPage, with the properties each one actually requires.
Schema markup (also called structured data) is a standardized way to describe a page’s contents to machines. Instead of leaving a search engine to infer that a string of text is a price, an author or a review rating, you label it explicitly using the shared vocabulary at schema.org. That matters for two audiences at once: classic search engines deciding whether your page qualifies for a richer listing, and the AI answer engines covered in our GEO guide, which parse the same structured signals when deciding what a page means and whether to cite it. This guide is the schema-focused spoke of our technical SEO automation pillar.
Why does schema markup help search and AI engines?
Search engines can read your page without any markup — but structured data removes ambiguity. It explicitly states the type of thing on the page and its properties, which is what makes a page eligible for rich results: review stars, FAQ accordions, breadcrumb trails, product pricing, and more. Structured data is not a direct ranking signal; its value is eligibility and clarity. The same machine-readable clarity helps AI engines resolve what your page is about and which entity it belongs to, which supports the entity work covered in our entity SEO guide.
Why JSON-LD instead of Microdata or RDFa?
Schema.org markup can be expressed three ways — JSON-LD, Microdata and RDFa — and all are valid vocabularies. JSON-LD wins on practicality: it sits in a single self-contained <script type="application/ld+json"> block rather than being woven through your visible HTML, so it’s easy to add, template and update without touching the rest of the page. Google explicitly recommends JSON-LD, and it’s the format you’ll see across most modern sites — including the JSON-LD that this very guide emits for its Article, Breadcrumb and FAQ data.
What is the recommended format for implementing schema markup?
The recommended format is JSON-LD. Google’s structured data documentation supports three formats (JSON-LD, Microdata and RDFa) and explicitly recommends JSON-LD for new implementations. All three describe the same schema.org vocabulary, so the choice is about how the data is attached to the page, not what it can say.
| Format | How it attaches to the page | Practical trade-off |
|---|---|---|
JSON-LD (recommended) | One <script> block, separate from your visible HTML | Easy to template, diff and delete. Editing it can’t break your layout. |
Microdata | itemscope / itemprop attributes woven into your HTML tags | Still valid and still read by Google, but every markup change means touching rendered markup, and a refactor of the template silently drops properties. |
RDFa | typeof / property attributes on existing HTML elements | Same coupling problem as Microdata, with a smaller ecosystem of tooling and examples. |
Two placement notes that matter in practice. First, JSON-LD can live in the <head> or anywhere in the <body>; Google reads it from either, so put it wherever your templating system keeps it closest to the content it describes. Second, Google can pick up JSON-LD that JavaScript injects after load because it renders pages before extracting structured data, but that adds a rendering dependency for no benefit. If you can output the markup server-side or at build time, do that instead.
Which schema types actually matter?
Schema.org defines hundreds of types, but a small core covers the majority of real-world use. Match the type to what the page genuinely is — don’t mark up a thing that isn’t on the page. The table below maps the high-value types to when you’d use them and the properties that carry the weight.
| Schema type | Use it for | Key properties |
|---|---|---|
Organization | Your brand identity, usually once site-wide | name, url, logo, sameAs |
WebSite | The site as a whole; enables a sitelinks search box | name, url, potentialAction (SearchAction) |
Article | Blog posts, guides and news content | headline, author, datePublished, image |
BreadcrumbList | The navigation path to the page | itemListElement (position, name, item) |
FAQPage | Pages with a list of question/answer pairs | mainEntity (Question → acceptedAnswer) |
Product | Product detail pages in e-commerce | name, image, offers (price, availability) |
Review / AggregateRating | Ratings on a product, service or business | reviewRating, author, ratingValue, reviewCount |
Person | Author and team-member identity | name, jobTitle, url, sameAs |
LocalBusiness | A physical or service-area business | name, address, telephone, openingHours |
How do you add JSON-LD to a page?
Add a single <script type="application/ld+json"> tag containing one JSON object (or a @graph array of connected objects). Every object needs @context set to https://schema.org and an @type. The markup should describe content that’s actually visible on the page. Here’s a minimal, valid Article example:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Schema Markup (JSON-LD): A Practical 2026 Guide",
"datePublished": "2026-06-14",
"dateModified": "2026-06-14",
"author": {
"@type": "Person",
"name": "Christopher Taylor",
"url": "https://www.blackandgoldseo.com/about/"
},
"publisher": {
"@type": "Organization",
"name": "Black & Gold SEO",
"url": "https://www.blackandgoldseo.com/"
},
"mainEntityOfPage": "https://www.blackandgoldseo.com/guides/schema-markup-json-ld/"
}
</script>Keep the JSON valid (straight double quotes, no trailing commas), match each property to what the page really contains, and place the script in the page’s <head> or body. On a static site you can template these blocks so the structured data stays in sync with the rendered content automatically — which is exactly the kind of repetitive, error-prone task worth handing to automation.
Event schema markup: what to include and a working example
Use Event on any page that describes a single scheduled happening: a webinar, a conference, a class, a concert, a fundraiser, a store opening. Mark up the event, not the listing page around it. If one page lists many events, output one Event object per event (an array of objects in a single script block is fine) and give each one its own canonical URL if it has one.
Three properties are required for Google’s event experiences: name, startDate and location. Everything else is optional but usually worth adding, because it’s the difference between an entry that shows a date and one that shows a date, a venue, a price and a ticket link.
- Required:
name,startDate(ISO 8601, including the time-zone offset so an evening event doesn’t drift a day in another region), andlocation. - Location depends on the event type. Physical events use a
Placewith aPostalAddress. Online events use aVirtualLocationwith aurl. Hybrid events use both, in an array. - Strongly recommended:
endDate,description,image,eventAttendanceMode,eventStatus,organizer,performer, andofferswithprice,priceCurrency,availabilityand the ticketurl. - Keep
eventStatuscurrent. When something is cancelled, postponed or moved online, update the enum value (EventCancelled,EventPostponed,EventMovedOnline) rather than deleting the markup. That’s how engines learn the event changed instead of just disappearing.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Structured Data Workshop 2026",
"description": "A two-hour hands-on workshop on writing and validating JSON-LD.",
"startDate": "2026-09-17T18:30:00-05:00",
"endDate": "2026-09-17T20:30:00-05:00",
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
"eventStatus": "https://schema.org/EventScheduled",
"image": ["https://www.example.com/img/workshop-2026.jpg"],
"location": {
"@type": "Place",
"name": "Riverfront Conference Center",
"address": {
"@type": "PostalAddress",
"streetAddress": "400 Poydras St",
"addressLocality": "New Orleans",
"addressRegion": "LA",
"postalCode": "70130",
"addressCountry": "US"
}
},
"organizer": {
"@type": "Organization",
"name": "Example Events Co",
"url": "https://www.example.com/"
},
"performer": {
"@type": "Person",
"name": "Dana Whitfield"
},
"offers": {
"@type": "Offer",
"url": "https://www.example.com/events/structured-data-workshop/",
"price": "49.00",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"validFrom": "2026-08-01T09:00:00-05:00"
}
}
</script>For an online event, swap the location block and the attendance mode:
"eventAttendanceMode": "https://schema.org/OnlineEventAttendanceMode",
"location": {
"@type": "VirtualLocation",
"url": "https://www.example.com/live/structured-data-workshop/"
}Local business schema markup: LocalBusiness JSON-LD that validates
LocalBusiness describes a business people can physically visit or that serves a defined area. It belongs on the page that represents that specific location: the homepage for a single-location business, and the individual location page for each branch of a multi-location one. Never repeat the same address block across every page of a multi-location site; give each location its own page, its own markup and its own stable @id.
Use the most specific subtype schema.org offers instead of the generic parent. Restaurant, Dentist, Plumber, HVACBusiness, AutoRepair, LegalService and dozens more all inherit every LocalBusiness property, and the extra precision helps engines classify you. If nothing fits, LocalBusiness itself is a valid answer.
- Required in practice:
nameandaddress(a fullPostalAddress, not a single string). - Add these or you’re leaving detail on the table:
telephonein international format,url,image(a real photo of the business, not a logo),geocoordinates,priceRange, andopeningHoursSpecification. - Service-area businesses: if you travel to customers and have no storefront, use
areaServedto state the coverage area and consider omitting a public street address that customers can’t actually visit. - Keep it identical to your Google Business Profile. Name, address and phone should match character for character across your site, your profile and your citations. Contradictory NAP data is the most common reason local markup fails to help.
- Be careful with ratings. Only include
aggregateRatingif the reviews are genuine and collected by you. Reviews a business writes about itself aren’t eligible for review rich results, and inventing them is a guideline violation with real penalties attached.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "HVACBusiness",
"@id": "https://www.example.com/#localbusiness",
"name": "Crescent Air Services",
"url": "https://www.example.com/",
"image": "https://www.example.com/img/shop-front.jpg",
"telephone": "+1-504-555-0142",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "1820 Magazine St",
"addressLocality": "New Orleans",
"addressRegion": "LA",
"postalCode": "70130",
"addressCountry": "US"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 29.9285,
"longitude": -90.0755
},
"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"
}
],
"areaServed": {
"@type": "City",
"name": "New Orleans"
},
"sameAs": [
"https://www.facebook.com/example",
"https://www.linkedin.com/company/example"
]
}
</script>Closed on Sunday? Leave it out entirely, or state it explicitly with an OpeningHoursSpecification whose opens and closes are both "00:00". Both are valid; what you must not do is list hours you don’t actually keep. If you’re assembling the wider local stack around this markup, our roundup of local SEO tools covers the profile and citation side.
FAQ schema markup: FAQPage JSON-LD (and what it does in 2026)
FAQPagemarks up a list of questions and their single accepted answers, both written by you. It’s the type with the most changed value of any on this page, so be clear about what it buys. In August 2023 Google restricted FAQ rich results (the expandable Q&A dropdowns under a listing) to well-known, authoritative government and health sites. For everyone else the dropdowns are gone and they aren’t coming back.
What FAQPage markup still does is label each question and its answer unambiguously for AI answer engines, which is exactly the passage-level structure they parse, quote and cite. It costs a few minutes and nothing to maintain, so it remains worth shipping. Just don’t expect a visual change in Google’s results.
- Structure: one
FAQPagewith amainEntityarray ofQuestionobjects, each holding exactly oneacceptedAnswerof typeAnswer. - Required properties:
nameon each Question (the full question, phrased the way a person would ask it) andtexton each Answer. - FAQPage vs QAPage: use
FAQPagewhen your site writes both the question and the one answer. UseQAPagewhen users submit competing answers, as on a forum thread. Mixing them up is a guideline violation. - Every Q and A must be visible on the page. Markup that describes content a visitor can’t see is the fastest way to get structured data ignored, and one question should appear only once per page.
- Write answers that survive extraction: two to four complete sentences that resolve the question without needing the rest of the page for context.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "How long does shipping take?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Orders placed before 2pm CT ship the same business day. Standard delivery inside the US takes 3 to 5 business days; expedited takes 2."
}
},
{
"@type": "Question",
"name": "Do you ship internationally?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. We ship to 40 countries. International orders take 7 to 14 business days and any customs duties are the responsibility of the recipient."
}
}
]
}
</script>If you’d rather not hand-write the JSON, our free FAQ schema generatorbuilds it live from your Q&A pairs (with proper escaping, duplicate detection, and a copy-ready <script> tag), and the broader schema markup generator covers Organization, LocalBusiness, Article, Product, FAQPage and BreadcrumbList. Both run entirely in your browser, free, with no signup. Event markup isn’t in the generator yet, so start from the example above for those.
How do you tie schema to one canonical entity?
Markup is most powerful when it’s consistent. Use the same name and url for your Organization everywhere, and use the sameAs property to link each entity (your brand, your authors) to its authoritative profiles — your Wikidata entry, LinkedIn, Crunchbase, official social accounts. That helps engines collapse all your references into a single, well-understood entity rather than several fuzzy ones. Reusing a stable @id across your graph reinforces the same effect. This is the schema-side of the broader entity SEO work that helps you become an unambiguous entity in the Knowledge Graph and in AI models.
How do you validate and test your markup?
Never ship structured data unvalidated. Use two complementary tools:
- Google’s Rich Results Test. Tells you whether a page is eligible for a specific Google rich result and flags errors that block it. Run it on a live URL or pasted code.
- The Schema Markup Validator (validator.schema.org). Checks your markup against the full schema.org vocabulary — broader than Google’s supported subset — so it catches structural and syntax issues the Rich Results Test ignores.
Remember the limit: Google only displays rich results for its supported structured-data features, and only when the page qualifies and follows the guidelines. Valid markup for an unsupported type is still useful for machine readability — it just won’t change how the listing looks. Fix errors before warnings, and re-test after every change.
How do you check schema markup on a page that’s already live?
Checking markup on a live page (yours or a competitor’s) takes about a minute. Work through these in order, because each one catches a different class of problem.
- Look at the source. Open the page, view source, and search for
application/ld+json. That tells you instantly whether any structured data exists and what types it declares. If the site injects markup with JavaScript you won’t see it in view-source, so check the Elements panel in DevTools instead, which shows the rendered DOM. - Run the Rich Results Test on the URL. Testing the live URL (rather than pasted code) is the honest test, because Google fetches and renders the page the way Googlebot would, including anything added by script. It reports which rich-result types the page is eligible for and which errors block them.
- Run the Schema Markup Validator. The Rich Results Test only knows Google’s supported features, so it stays silent about valid types Google doesn’t surface. The validator at validator.schema.org checks the full vocabulary and catches misspelled property names, wrong value types and broken nesting that the other tool skips.
- Check Search Console for the site-wide picture. Both tools test one page at a time. Search Console’s enhancement reports show every URL with a given markup type and how many are erroring, and the Unparsable structured data report catches syntax failures that never made it into a report at all. This is where you find the template bug that broke 400 pages.
- Re-check after content edits. The most common real-world failure isn’t invalid markup, it’s drifted markup: the visible price, hours, author or FAQ answer changed in the CMS while the JSON-LD kept serving last quarter’s values. Nothing in the browser makes that visible, which is why it survives for months.
If you’re building markup rather than auditing it, our free schema markup generator and FAQ schema generator produce valid JSON-LD you can paste straight into a page, then verify with the two validators above.
Schema markup is foundational technical SEO: low-risk, high-clarity, and increasingly important as AI engines lean on structured signals to understand and cite pages. For the wider picture, see our pillar on technical SEO automation, the entity groundwork in entity SEO, and how machine-readable content feeds AI answer engines in the GEO guide. When you’re ready to put it on autopilot, compare plans.
Sources & further reading
- schema.org — the structured-data vocabulary
- Google Search Central — Intro to structured data markup
- Google — Rich Results Test
- Schema Markup Validator (validator.schema.org)
- Google Search Central — Event structured data
- Google Search Central — Local business (LocalBusiness) structured data
- Google Search Central — FAQ (FAQPage) structured data
Keep reading
Pillar guide
Technical SEO automation
What technical SEO covers in 2026, which checks and fixes can be safely automated (and which can't), and how to keep a site crawlable, fast and machine-readable for search and AI engines.
Technical · How-to
Entity SEO
How search engines and AI models understand the world through entities — and how to make your brand, authors and topics unambiguous, well-connected entities they trust and cite.
Pillar guide
Generative Engine Optimization
What GEO is, how AI answer engines choose what to cite, and the exact method to get your site quoted by ChatGPT, Google AI Overviews, Perplexity and Gemini — without fabricating anything.