Last week a client asked me: "We have a schemas.ts file in our codebase, but nobody remembers why it's there or what each block does." That's not unusual. In at least half the projects I review, there's a stray JSON-LD file somewhere that a developer dropped in years ago — undocumented, with no clear purpose, and often with nobody left who knows whether it's even accurate.
That's a waste, because structured data is exactly the kind of information AI systems such as ChatGPT, Perplexity and Google's AI Overviews are hungry for. It's machine-readable context that says: "this is who we are, this is where we're based, these are the answers to common questions." Without that context, a language model has to guess from unstructured text. With it, the model gets a direct, reliable source.
In this article I'll walk through the three most widely used schema types — Organization, LocalBusiness and FAQPage — with concrete examples you can implement today.
Why structured data still matters in the AI era
Structured data (usually JSON-LD) has existed since 2011, thanks to schema.org, which Google, Bing, Yahoo and Yandex built together. The goal back then was simple: help search engines understand content so they could show rich results — star ratings, opening hours, FAQ accordions in the search results.
What has changed is the reader. The consumer of your structured data is no longer just a crawler indexing pages for a results list. It's also a language model parsing your content to formulate an answer for a user who may never visit your site at all. If someone asks ChatGPT "which agencies in Utrecht offer AI consulting", the odds that your JSON-LD gets picked up in the answer are many times higher than the odds that a chunk of marketing copy gets interpreted correctly.
That's because structured data is unambiguous. A sentence like "We're in the heart of Utrecht" has to be interpreted, and the model has to make assumptions. A PostalAddress object with addressLocality: "Utrecht" needs no interpretation at all — it's a fact that can be extracted directly.
For the broader strategy behind this kind of optimization, it's worth reading what GEO actually means too — structured data is one piece of a much bigger puzzle.
The three schema types you almost always need
Organization: who are you, really?
The Organization schema is the foundation. It answers the question AI systems most often can't resolve: what is this company, and why should I trust it? This schema belongs on your homepage, and ideally you repeat it (or reference it) on every page through your layout.
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "WeArkMedia",
"url": "https://wearkmedia.nl",
"logo": "https://wearkmedia.nl/logo.png",
"description": "AI-native web development and GEO/AEO optimization for businesses that want to be found by ChatGPT, Perplexity and Google AI Overviews.",
"sameAs": [
"https://www.linkedin.com/company/wearkmedia",
"https://twitter.com/wearkmedia"
],
"contactPoint": {
"@type": "ContactPoint",
"email": "hallo@wearkmedia.nl",
"contactType": "customer service"
}
}
What matters here: sameAs is not decoration. This field links your company to external, verifiable sources — your LinkedIn, your Wikipedia page (if you have one), your Crunchbase profile. AI models use these cross-references to decide whether an entity is "real". An Organization schema without sameAs is like a LinkedIn profile with no connections: technically valid, but not very convincing.
Don't copy your description from your meta description. Write a sentence that is specific about what you do and who you do it for — not "we are a leading agency", but concrete: what, for whom, and why you're different.
LocalBusiness: essential if you need to be found locally
If you have a physical location — an office, a shop, a practice — then LocalBusiness (or a more specific subtype such as ProfessionalService, Restaurant or Store) is essential. This schema is the direct reason AI assistants can answer "near me" questions.
{
"@context": "https://schema.org",
"@type": "ProfessionalService",
"name": "WeArkMedia",
"image": "https://wearkmedia.nl/kantoor.jpg",
"address": {
"@type": "PostalAddress",
"streetAddress": "Vredenburg 40",
"addressLocality": "Utrecht",
"postalCode": "3511 BD",
"addressCountry": "NL"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 52.0907,
"longitude": 5.1214
},
"telephone": "+31-30-1234567",
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"opens": "09:00",
"closes": "17:30"
}
],
"priceRange": "€€€"
}
Two things that often go wrong. First: people forget the geo coordinates, even though this is precisely what systems use to calculate distance for "nearest" queries. Second: the @type is often too generic. Don't default to LocalBusiness when a more specific subtype exists — Google and AI systems can match intent far more precisely with a specific type (such as Dentist, Accountant, or MarketingAgency where available).
This is a topic I cover in more depth in GEO for local businesses — including how to handle multiple locations.
FAQPage: the most underrated schema for AEO
If there's one schema type that directly affects whether you get cited in an AI answer, it's FAQPage. Why? Because it literally supplies the question-and-answer structure a language model needs to reuse your content in its own response — often word for word.
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What does an AI-native website cost?",
"acceptedAnswer": {
"@type": "Answer",
"text": "An AI-native website is delivered in phases. What it costs depends on the number of pages, the number of languages and the integrations with existing systems. Ask for a quote based on your own scope, with hours broken down per phase."
}
},
{
"@type": "Question",
"name": "Does structured data work without a technical team?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. Most CMS platforms and frameworks support JSON-LD through plugins or simple code snippets. You don't need a dedicated developer to implement Organization or FAQPage schema."
}
}
]
}
The trap here is that people fill FAQPage schema with marketing questions ("Why choose us?") instead of the questions people actually ask a search engine or AI assistant. Look at the "People Also Ask" section in Google, or test for yourself in ChatGPT and Perplexity to see which questions come up around your topic. Write answers that stand on their own — an answer has to make sense without re-reading the question, because that's exactly how a language model will lift it out.
I've worked this out in more detail in the practical AEO guide, including how to decide which questions are worth answering.
From loose file to working system: practical implementation
Where do you put this in your codebase?
If you already have a lib/schemas.ts (or something similar), the logical structure is to export functions that generate JSON-LD objects from your content, rather than static strings. Something like this:
// lib/schemas.ts
export function generateOrganizationSchema() {
return {
"@context": "https://schema.org",
"@type": "Organization",
name: "WeArkMedia",
url: "https://wearkmedia.nl",
// ...
};
}
export function generateFAQSchema(faqs: { question: string; answer: string }[]) {
return {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: faqs.map((faq) => ({
"@type": "Question",
name: faq.question,
acceptedAnswer: {
"@type": "Answer",
text: faq.answer,
},
})),
};
}
This stops your schemas from drifting away from your content — a very common problem where the FAQ text on the page gets updated but the schema behind it doesn't follow. Inconsistency between visible content and schema data is exactly what you don't want: it undermines trust with both Google and AI crawlers.
Test and validate before you go live
Use Google's Rich Results Test and Schema.org's own validator before you publish anything. A common mistake is a typo in @type (for example Organisation with a British spelling instead of Organization) — the schema then fails silently, with no error on your site, and you only find out when you start wondering why nothing is working.
Also check that your robots.txt isn't blocking the AI crawlers that are supposed to read this data — see the guide to robots.txt and AI crawlers if you're unsure whether your configuration is right.