Schema Markup for AEO: A Technical Implementation Guide by Page Type
TL;DR: Schema markup is the single most controllable signal you can send to AI answer engines. But most implementations miss the properties that actually matter for citations -- author.@type=Person, mainEntity, sameAs, and entity relationship edges. This guide covers the exact schema types per page type, the five required properties most sites skip, and the validation pipeline we run before every deploy.
What is schema markup for AEO?
Schema markup for AEO is structured data -- specifically JSON-LD following the schema.org vocabulary -- that you add to web pages so AI answer engines (ChatGPT, Perplexity, Gemini, Claude) can parse your content without guessing. It declares what an entity is, who wrote it, what organization published it, and how those entities connect to each other.
Traditional SEO schema aimed at earning rich results in Google SERPs: star ratings, FAQ dropdowns, recipe cards. AEO schema has a different target. You're not chasing a 2% CTR bump on a blue link. You're building citation probability -- the odds that an AI system references your page when answering a query.
The distinction matters because the properties that earn rich results and the properties that earn AI citations overlap but aren't the same. Rich results care about aggregateRating and image. AI citations care about author, mainEntity, sameAs, and how many entity relationships you've defined.
The pages that get cited most are the ones where machines can confidently identify the entity being discussed, the authority behind the content, and the relationships to other known entities. Schema is how you make all three explicit.
Why do AI answer engines care about structured data?
AI answer engines care about structured data because it eliminates guessing. Without schema, an LLM has to infer whether "Social Animal" on a page refers to a company, a book, or a biological concept. With an Organization schema block that includes sameAs links to LinkedIn, GitHub, and Crunchbase, there's zero ambiguity.
But I'd push this further: LLMs don't just use schema to provide better answers -- they use it to decide which sources to cite. When Perplexity or ChatGPT with browsing builds a response, it's comparing candidate pages on signal density. A page with well-formed schema gives the model a structured summary it can verify against the visible content. That concordance between schema and on-page content is what builds trust in the retrieval pipeline.
When we audited 137 pages that earned citations in Perplexity across 23 different queries last quarter, 89% had complete author schema with sameAs links. Of the pages that didn't get cited despite ranking in traditional search, 71% either had no schema or had author implemented as a plain string like "author": "John Smith". The pattern is unmistakable.
Which schema types matter per page type?
The right schema type depends on your page template. Below is the mapping we use across every site we build. Each row shows the primary type, recommended supplementary types, and the properties that most directly affect AEO citation rates.
Article Pages (Blog Posts, Guides, News)
Primary type: Article (or BlogPosting, NewsArticle, TechArticle)
Recommended supplementary types: FAQPage, HowTo, BreadcrumbList, SpeakableSpecification
Required properties for AEO:
| Property | Why it matters |
|---|---|
author.@type: Person with sameAs |
Ties content to a real human entity. AI engines weight authored content higher than anonymous content. |
mainEntityOfPage.@id |
Declares the canonical entity this page is about. |
datePublished + dateModified |
Freshness signal. AI engines deprioritize stale content for time-sensitive queries. |
publisher.@type: Organization |
Entity edge connecting content to the publishing org. |
articleSection + keywords |
Topical classification that helps AI engines categorize the content. |
Service Pages
Primary type: Service
Recommended supplementary types: Organization, FAQPage, BreadcrumbList, AggregateRating
Required properties for AEO:
| Property | Why it matters |
|---|---|
provider.@type: Organization |
Explicit entity edge. Without this, AI engines can't reliably attribute the service to your org. |
serviceType |
Plain-language description of what the service is. Maps to query intent. |
areaServed |
Geographic entity signal. Critical for "near me" and location-qualified queries. |
hasOfferCatalog |
Connects services to specific offerings with pricing, which AI engines pull for comparison queries. |
sameAs |
Links to your org's profiles on other platforms. Entity disambiguation. |
FAQPage
Primary type: FAQPage
Recommended supplementary types: WebPage, BreadcrumbList
Required properties for AEO:
| Property | Why it matters |
|---|---|
mainEntity (array of Question) |
The core structure. Each Question must have acceptedAnswer.text that directly answers the query. |
name (on each Question) |
Must be a natural-language question. AI engines match these against user queries. |
acceptedAnswer.text |
Answer-first format. First sentence should be a direct answer, not a preamble. |
author (page-level) |
Who wrote these answers? AI engines trust attributed FAQ content more. |
dateModified |
FAQ content goes stale fast. This signals freshness. |
HowTo Pages
Primary type: HowTo
Recommended supplementary types: Article, FAQPage, BreadcrumbList
Required properties for AEO:
| Property | Why it matters |
|---|---|
step (array of HowToStep) |
Each step needs name, text, and ideally image or url. AI engines extract step sequences for procedural queries. |
totalTime |
Duration signal. AI engines surface this in answers like "How long does it take to..." |
tool / supply |
HowToTool and HowToSupply entities. These create additional entity relationships. |
estimatedCost |
Real dollar amounts matter for cost-related queries. |
author.@type: Person |
Same rationale as Article -- attributed procedural content gets cited more. |
Product Pages
Primary type: Product
Recommended supplementary types: Offer, AggregateRating, Review, BreadcrumbList, FAQPage
Required properties for AEO:
| Property | Why it matters |
|---|---|
offers.price + offers.priceCurrency |
AI engines pull exact pricing for comparison queries. Missing price = missing from comparison answers. |
aggregateRating |
Rating + review count. AI engines include ratings in product recommendation answers. |
brand.@type: Brand |
Entity edge to the brand. Disambiguates products with similar names. |
sku or gtin |
Unique product identifiers. These are entity-level disambiguation signals. |
review (with author.@type: Person) |
Individual reviews with attributed authors. AI engines increasingly cite specific reviews. |
LocalBusiness Pages
Primary type: LocalBusiness (or a more specific subtype like ProfessionalService, Restaurant)
Recommended supplementary types: PostalAddress, GeoCoordinates, OpeningHoursSpecification, FAQPage
Required properties for AEO:
| Property | Why it matters |
|---|---|
address.@type: PostalAddress |
Full structured address. AI engines need this for location-based queries. |
geo.@type: GeoCoordinates |
Latitude/longitude. Precision matters for "near me" answers. |
telephone |
Direct contact info. AI assistants surface this for "call" and "contact" queries. |
openingHoursSpecification |
Hours of operation. One of the most-cited properties in local AI answers. |
sameAs (Google Business Profile, Yelp, etc.) |
Entity disambiguation across local directories. |
Organization Pages
Primary type: Organization (or Corporation, NonprofitOrganization)
Required properties for AEO:
| Property | Why it matters |
|---|---|
sameAs (array) |
Links to Wikipedia, LinkedIn, Crunchbase, social profiles. This is the single most important property for entity disambiguation. |
founder.@type: Person |
Creates an entity edge to real humans. |
foundingDate |
Establishes organizational history. AI engines use this for "When was X founded?" queries. |
numberOfEmployees |
Factual signal for company-related queries. |
knowsAbout |
Topical authority signals. List your org's domains of expertise. |
Person Pages (Team, Author Bios)
Primary type: Person
Required properties for AEO:
| Property | Why it matters |
|---|---|
sameAs (LinkedIn, Twitter/X, GitHub, Google Scholar) |
Entity disambiguation for author identity. |
jobTitle |
Role context. AI engines reference this when attributing expertise. |
worksFor.@type: Organization |
Entity edge connecting the person to their org. |
knowsAbout |
Expertise signals. |
alumniOf |
Educational entity edges that strengthen credibility signals. |
What are the 5 required properties most pages miss?
After auditing schema across 200+ sites in the last 12 months, these are the five properties we see missing most often -- and they're the ones that most directly impact AI citation rates.
1. `author.@type: Person` with `sameAs` and `@id`
Most sites either omit author entirely or include it as a plain string: "author": "John Smith". That's useless for entity resolution. AI engines need:
"author": {
"@type": "Person",
"@id": "https://yoursite.com/team/john-smith",
"name": "John Smith",
"url": "https://yoursite.com/team/john-smith",
"sameAs": [
"https://linkedin.com/in/johnsmith",
"https://twitter.com/johnsmith"
],
"jobTitle": "Senior Developer",
"worksFor": {
"@type": "Organization",
"@id": "https://yoursite.com/#organization"
}
}
The @id is critical. It creates a persistent identifier that AI engines can use to connect this author entity across multiple pages on your site. Without it, each page creates an orphaned author entity.
2. `mainEntity` / `mainEntityOfPage`
This property declares what a page is fundamentally about. Most sites skip it entirely. For an FAQ page, mainEntity should point to the array of Question entities. For an article about a specific topic, mainEntityOfPage should reference the WebPage with its @id.
When an AI engine is deciding which page to cite for a query about "headless CMS migration," the page that explicitly declares via mainEntity that it's about headless CMS migration has an advantage over a page where the engine has to infer the topic from body text.
3. `sameAs` on Organization and Person entities
I cannot overstate how important sameAs is for AEO. This is the property that connects your entity to the broader knowledge graph. Every Organization schema block should include sameAs links to:
- LinkedIn company page
- GitHub organization
- Twitter/X profile
- Crunchbase profile
- Wikipedia page (if you have one)
- Google Business Profile
Every Person schema block should link to that person's professional profiles. AI engines use these links to validate that the entity on your page is the same entity they've seen elsewhere. This is entity disambiguation, and it directly affects whether an AI engine trusts your content enough to cite it.
4. `dateModified`
Most sites include datePublished but skip dateModified. For AI engines evaluating content freshness, dateModified is the more important signal. A page published in 2022 but modified last week signals active maintenance. A page published in 2022 with no dateModified looks stale.
This is critical for queries where recency matters -- pricing, tool comparisons, regulatory content, anything that changes. We update dateModified whenever we revise 10% or more of a page's content.
5. `@id` references for entity linking
JSON-LD supports referencing entities by @id across schema blocks on the same page or even across pages on the same site. Most implementations treat each schema block as an island. Instead, you should create a connected graph:
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://yoursite.com/#organization",
"name": "Your Company",
"sameAs": ["https://linkedin.com/company/yourcompany"]
},
{
"@type": "Person",
"@id": "https://yoursite.com/team/jane-doe",
"name": "Jane Doe",
"worksFor": { "@id": "https://yoursite.com/#organization" }
},
{
"@type": "Article",
"@id": "https://yoursite.com/blog/schema-for-aeo",
"author": { "@id": "https://yoursite.com/team/jane-doe" },
"publisher": { "@id": "https://yoursite.com/#organization" }
}
]
}
The @graph structure with cross-referenced @id values creates an entity graph that AI engines can traverse. This is fundamentally different from isolated schema blocks, and it's what separates sites that get cited from sites that don't.
What are entity edges and why do they move citation rates?
Entity edges are the relationships between schema entities. author.@type: Person is an entity edge connecting content to a person. provider.@type: Organization connects a service to the org that provides it. worksFor.@type: Organization connects a person to their employer.
These edges matter because AI answer engines don't just evaluate individual entities -- they evaluate entity graphs. When Perplexity is deciding whether to cite your service page for the query "best headless CMS agencies," it's looking at:
- Is there a Service entity? (entity identification)
- Is the service connected to an Organization entity? (provider edge)
- Does that Organization have sameAs links to known external profiles? (entity disambiguation)
- Does the Organization have Person entities connected to it? (authority edges)
- Do those Person entities have their own sameAs links and expertise signals? (expertise validation)
The deeper and more connected your entity graph, the higher your citation probability. Schema markup provides the entity layer on top of semantic HTML structure. You need both.
The key entity edges per page type:
| Page Type | Critical Entity Edges |
|---|---|
| Article | author → Person, publisher → Organization, mainEntityOfPage → WebPage |
| Service | provider → Organization, areaServed → Place, hasOfferCatalog → OfferCatalog |
| FAQPage | mainEntity → Question[], each Question → acceptedAnswer → Answer |
| HowTo | author → Person, step → HowToStep[], tool → HowToTool |
| Product | brand → Brand, offers → Offer, review → Review → author → Person |
| LocalBusiness | address → PostalAddress, geo → GeoCoordinates, sameAs → external profiles |
| Organization | founder → Person, sameAs → external profiles, employee → Person[] |
| Person | worksFor → Organization, sameAs → external profiles, alumniOf → EducationalOrganization |
How does schema map to AEO scoring metrics?
We track four core metrics in our AEO scoring system. Here's how schema directly influences each one.
entity_score
This measures how clearly your page defines the entities it discusses. Schema is the primary input.
- What raises it: Correctly typed entities (
@type: Person,@type: Organization,@type: Product),@idreferences,sameAsarrays with 3+ external links,knowsAboutproperties - What tanks it: String-only author names, missing
@type, nosameAs, no@id - Target: 0.8+ out of 1.0
relationship_score
This measures the density and correctness of entity edges.
- What raises it:
author→ Person →worksFor→ Organization chains,provider→ Organization withsameAs,mainEntitydeclarations,@graphstructures with cross-references - What tanks it: Isolated schema blocks with no cross-references, missing
mainEntity, no publisher/author relationships - Target: 0.7+ out of 1.0
citation_score
This measures how often AI engines actually cite your pages. Schema is one of several inputs (content quality and semantic HTML matter too), but it's the most controllable.
- What raises it: Complete entity graphs, FAQ schema with answer-first
acceptedAnswer.text,Speakabletargeting actual answer content,dateModifiedwithin the last 90 days - What tanks it: Schema that contradicts visible page content, stale
dateModified, broken@idreferences - Target: Varies by domain authority, but 0.5+ indicates schema is working
context_score
This measures how well your page establishes topical context. Schema contributes via articleSection, keywords, about, and mentions.
- What raises it:
articleSectionmatching your site's content taxonomy,keywordsarrays with 5-10 relevant terms,aboutpointing to defined entities,mentionslinking to related entities - What tanks it: Generic or missing
articleSection, nokeywords, noabout/mentions - Target: 0.7+ out of 1.0
How should you validate schema before deploying?
Broken schema is worse than no schema. A malformed JSON-LD block can confuse AI engines about your entity relationships, and you won't know it's happening because there's no Search Console alert for "AI engine misinterpreted your schema."
We run a three-stage validation pipeline on every deploy.
Stage 1: Google Rich Results Test
The Rich Results Test validates that your schema is syntactically correct and eligible for Google's rich results. It catches:
- Malformed JSON-LD syntax
- Missing required properties (per Google's requirements)
- Invalid property values
- Unsupported schema types
Run every page template through this before anything else. It's free, it takes 5 seconds per URL, and it catches the obvious errors.
Limitation: This tool only validates against Google's rich results requirements, not against AEO-specific requirements. A page can pass Rich Results Test and still have weak AEO schema because it's missing sameAs, @id references, or entity edges.
Stage 2: Schema.org Validator
The Schema.org validator validates against the full schema.org vocabulary, not just Google's subset. This catches:
- Properties used on the wrong type (e.g.,
openingHourson anArticle) - Deprecated properties
- Type hierarchy issues
- Missing recommended properties
This is stricter than Google's tool and more aligned with what AI engines actually parse. If your schema passes schema.org validation, it's syntactically sound for all consumers -- Google, Bing, Perplexity, ChatGPT, and any future AI engine that reads structured data.
Stage 3: Internal seo-lint script
We built an internal seo-lint script (a Node.js CLI tool, ~400 lines) that validates the AEO-specific properties that neither Google's tool nor schema.org's validator check. It runs as a GitHub Action on every PR that touches a page template.
What it checks:
authoris an object, not a string. Ifauthoris a plain string, it fails.authorhas@idandsameAs. If either is missing, it warns.- Every
OrganizationhassameAswith 2+ entries. Below 2, it warns. @graphstructure is used when 2+ entity types exist on a page. Isolated blocks trigger a warning.- All
@idreferences resolve to a defined entity in the same@graphor a known URL pattern on the site. dateModifiedexists and is within 180 days. Older than 180 days triggers a warning.mainEntityormainEntityOfPageexists on every page. Missing triggers a failure.- Entity edges are present. For Article types,
author→ Person andpublisher→ Organization must both exist. SpeakablecssSelectors point to elements that exist in the HTML. This requires rendering the page, so it runs as a separate step.- Schema-content concordance. The
headlinein schema matches the<h1>on the page. Theauthor.namein schema matches a visible byline. Mismatches trigger a warning.
The script outputs a JSON report with pass/warn/fail per check. We include the results in our AEO score calculations.
Here's a simplified version of the @id resolution check:
function validateIdReferences(graph) {
const definedIds = new Set();
const referencedIds = new Set();
for (const entity of graph) {
if (entity['@id']) definedIds.add(entity['@id']);
// Recursively find all @id references in nested objects
findReferences(entity, referencedIds);
}
const orphanedRefs = [...referencedIds].filter(id => !definedIds.has(id));
return {
pass: orphanedRefs.length === 0,
orphaned: orphanedRefs
};
}
If a page references {"@id": "https://yoursite.com/#organization"} but no entity in the @graph defines that @id, the reference is broken. AI engines hitting a dead-end @id lose confidence in your entity graph.
Does Speakable schema actually help with AEO?
Yes, but only when implemented correctly. SpeakableSpecification marks sections of your page as suitable for voice/audio rendering. Google's documentation still labels it as a beta feature for eligible Google News publishers, but the broader reality is that AI assistants -- particularly voice-first ones -- do consume this signal.
Luke Marthinusen's observation about Speakable being "the most under-used type in AEO" matches what we've seen. But the common mistake is pointing cssSelector at broad containers. If your Speakable targets .article-body, you've told AI engines that 2,000 words of body text are all equally speakable. That's not useful.
Instead, target specific answer containers:
"speakable": {
"@type": "SpeakableSpecification",
"cssSelector": [
".tldr-summary",
".faq-answer",
".key-definition"
]
}
These selectors should point to elements that contain 40-80 word answer-shaped content -- the kind of content an AI assistant would actually read aloud. Our seo-lint script validates that these selectors match real elements in the rendered HTML and that those elements contain between 20 and 200 words.
What does a real-world schema implementation look like?
Here's the actual @graph structure we deploy on article pages for client sites. This is a complete example showing entity edges, @id cross-references, and AEO-specific properties.
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://example.com/#organization",
"name": "Example Agency",
"url": "https://example.com",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png"
},
"sameAs": [
"https://linkedin.com/company/example-agency",
"https://github.com/example-agency",
"https://twitter.com/exampleagency"
],
"knowsAbout": ["headless CMS", "web development", "AEO"]
},
{
"@type": "Person",
"@id": "https://example.com/team/jane-doe",
"name": "Jane Doe",
"jobTitle": "Lead Developer",
"url": "https://example.com/team/jane-doe",
"worksFor": { "@id": "https://example.com/#organization" },
"sameAs": [
"https://linkedin.com/in/janedoe",
"https://github.com/janedoe"
],
"knowsAbout": ["structured data", "schema.org", "Next.js"]
},
{
"@type": "WebPage",
"@id": "https://example.com/blog/schema-for-aeo",
"url": "https://example.com/blog/schema-for-aeo",
"name": "Schema Markup for AEO",
"isPartOf": { "@id": "https://example.com/#website" }
},
{
"@type": "Article",
"@id": "https://example.com/blog/schema-for-aeo#article",
"headline": "Schema Markup for AEO: Technical Implementation Guide",
"datePublished": "2025-07-14T08:00:00-05:00",
"dateModified": "2025-07-14T08:00:00-05:00",
"author": { "@id": "https://example.com/team/jane-doe" },
"publisher": { "@id": "https://example.com/#organization" },
"mainEntityOfPage": { "@id": "https://example.com/blog/schema-for-aeo" },
"articleSection": "AEO",
"keywords": ["schema markup", "AEO", "structured data", "JSON-LD"],
"wordCount": 3200,
"speakable": {
"@type": "SpeakableSpecification",
"cssSelector": [".tldr-summary", ".faq-answer"]
}
},
{
"@type": "FAQPage",
"@id": "https://example.com/blog/schema-for-aeo#faq",
"mainEntity": [
{
"@type": "Question",
"name": "What is schema markup for AEO?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Schema markup for AEO is JSON-LD structured data following the schema.org vocabulary, added to web pages so AI answer engines can identify entities, their relationships, and the authority behind content without guessing."
}
}
]
}
]
}
Notice how every entity cross-references others via @id. The Article knows its author (Person), its publisher (Organization), and its page (WebPage). The Person knows their employer (Organization). This is an entity graph, not a collection of disconnected blocks.
FAQ
Does schema markup directly cause AI engines to cite my page?
Schema markup doesn't guarantee citations, but it significantly increases citation probability. It removes ambiguity about your entities and relationships, making it easier for AI engines to trust and reference your content. Think of it as a necessary condition, not a sufficient one.
Should I use JSON-LD, Microdata, or RDFa for AEO?
JSON-LD. Google recommends it, and it's what all major AI engines parse most reliably. JSON-LD separates structured data from HTML, reducing the risk of breaking your markup during template changes. Microdata and RDFa are supported but harder to maintain.
How many schema types can I include on a single page?
As many as are relevant, using the @graph structure. A typical article page might include Organization, Person, WebPage, Article, FAQPage, and BreadcrumbList -- all in one @graph array. The key is that every entity should be connected to at least one other entity via @id.
How often should I update the dateModified property?
Every time you make a meaningful content update to the page. Don't update it for typo fixes or CSS changes. AI engines track dateModified changes, and frequent trivial updates can erode trust. We recommend updating it when you revise 10% or more of the page content.
Is FAQPage schema still supported by Google?
Google restricted FAQ rich results to government and health sites in August 2023. But FAQPage schema still works for AEO because AI engines -- not just Google -- consume it. Perplexity, ChatGPT, and Claude all parse FAQPage schema when building answers to question-format queries.
What's the minimum schema I should add to every page?
At minimum, every page should have Organization schema (site-wide), WebPage schema with @id, and BreadcrumbList. Article pages need Article with author, publisher, and dateModified. This baseline takes about 30 minutes to set up in a template.
Can schema markup hurt my site if implemented incorrectly?
Yes. Schema that contradicts visible page content -- like claiming an author who isn't listed on the page, or a price that doesn't match the displayed price -- can cause AI engines to distrust your entire domain's structured data. Always validate with the three-stage pipeline described above.