JSON-LD for AI search is the structured-data format that AI engines like ChatGPT, Perplexity, and Google AI Overviews use to identify entities, extract answers, and decide whom to cite. This guide gives you 8 ready-to-paste, validator-passing JSON-LD blocks for the page types every B2B SaaS site has: homepage, pricing, features, integrations, blog post, comparison, tool, and customer story. Each block uses the right combination of Article, FAQPage, HowTo, Product, SoftwareApplication, Organization, and Person. Copy, paste, swap your values, ship.
Where should JSON-LD live in your HTML for AI parsing?
Place every JSON-LD block inside a <script type="application/ld+json"> tag in the <head> of the server-rendered HTML response. AI crawlers do not run JavaScript, so client-side injection is invisible to them.
This is the single most common reason valid schema fails to drive AI citations. According to a Vercel/Next.js discussion on AI crawler behavior, GPTBot, ClaudeBot, and PerplexityBot fetch raw HTML and do not execute scripts. As Elie Berreby notes, JSON-LD pushed via Google Tag Manager without SSR is invisible to LLM crawlers.
Quick checklist before publish:
- JSON-LD lives in
<head>, not after a hydration boundary - The block returns in the initial HTML when you
curlthe URL - The user agent does not matter for delivery, but you should test with
curl -A 'GPTBot/1.0' https://yoursite.com/page - Schema is valid against validator.schema.org and the Google Rich Results Test
Pages with valid schema markup are 2-4x more likely to appear in Google AI Overviews and featured snippets, per Stackmatix's 2026 structured data report. Pages that combine FAQPage + Article + ItemList schema hit a 47% Top-3 citation rate vs 28% with no structured data.
What JSON-LD should a B2B SaaS homepage use?
Use a single @graph block containing Organization and WebSite. Organization is the canonical entity for your brand. WebSite enables the sitelinks search box and gives AI engines a stable site root to reference.
AI engines weight Organization heavily because it grounds your brand to a single entity across the web. Always include sameAs pointing to your LinkedIn, Crunchbase, Wikipedia (if you have it), and any official Wikidata entry.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://acme.com/#org",
"name": "Acme",
"url": "https://acme.com",
"logo": "https://acme.com/logo.png",
"description": "Acme is a B2B revenue intelligence platform for sales teams.",
"foundingDate": "2021-03-12",
"sameAs": [
"https://www.linkedin.com/company/acme",
"https://www.crunchbase.com/organization/acme",
"https://twitter.com/acme",
"https://www.wikidata.org/wiki/Q123456789"
],
"contactPoint": {
"@type": "ContactPoint",
"contactType": "sales",
"email": "sales@acme.com"
}
},
{
"@type": "WebSite",
"@id": "https://acme.com/#website",
"url": "https://acme.com",
"name": "Acme",
"publisher": { "@id": "https://acme.com/#org" },
"potentialAction": {
"@type": "SearchAction",
"target": "https://acme.com/search?q={search_term_string}",
"query-input": "required name=search_term_string"
}
}
]
}
</script>
Why this is structured this way: every other page on the site can reference https://acme.com/#org as the publisher, which de-duplicates the brand entity across the whole graph.
What JSON-LD should a B2B SaaS pricing page use?
Use Product with one or more Offer entries(or an AggregateOffer for a price range), plus a nested FAQPage for pricing-objection questions. Pricing pages exist to sell, so Product is the right primary type, not SoftwareApplication.
Per Singularity Digital's SaaS schema guide, using Product schema everywhere is one of the most common SaaS schema mistakes. Use it where pricing is the focus.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Product",
"@id": "https://acme.com/pricing#product",
"name": "Acme Revenue Intelligence",
"description": "AI-powered revenue intelligence for B2B sales teams.",
"brand": { "@id": "https://acme.com/#org" },
"offers": [
{
"@type": "Offer",
"name": "Starter",
"price": "49",
"priceCurrency": "USD",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": "49",
"priceCurrency": "USD",
"unitText": "per user per month"
},
"availability": "https://schema.org/InStock",
"url": "https://acme.com/pricing#starter"
},
{
"@type": "Offer",
"name": "Growth",
"price": "149",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"url": "https://acme.com/pricing#growth"
},
{
"@type": "Offer",
"name": "Enterprise",
"priceSpecification": {
"@type": "PriceSpecification",
"priceCurrency": "USD",
"price": "0",
"description": "Custom pricing"
},
"availability": "https://schema.org/InStock"
}
]
},
{
"@type": "FAQPage",
"@id": "https://acme.com/pricing#faq",
"mainEntity": [
{
"@type": "Question",
"name": "Is there a free trial?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. All plans include a 14-day free trial, no credit card required."
}
},
{
"@type": "Question",
"name": "Can I cancel any time?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. Monthly plans cancel any time. Annual plans are non-refundable after 30 days."
}
}
]
}
]
}
</script>
Why this is structured this way: Product carries the commercial intent, and the FAQPage block adds extractable answers AI engines pull verbatim into pricing-related queries.
Should I use Product schema for a SaaS feature page?
No. Feature pages should use SoftwareApplication because the page describes the product itself, not a purchase. Reserve Product for pricing.
Per Schema.org's SoftwareApplication spec, this type is purpose-built for software with applicationCategory, operatingSystem, featureList, and aggregateRating. Pair it with FAQPage to surface feature-specific Q&A.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "SoftwareApplication",
"@id": "https://acme.com/features/forecasting#app",
"name": "Acme Forecasting",
"applicationCategory": "BusinessApplication",
"applicationSubCategory": "Sales Forecasting",
"operatingSystem": "Web",
"url": "https://acme.com/features/forecasting",
"description": "AI-driven sales forecasting that ingests CRM data and predicts pipeline outcomes.",
"featureList": [
"AI pipeline scoring",
"Deal-level commit/best-case/worst-case forecasts",
"Salesforce + HubSpot two-way sync",
"Slack alerts on at-risk deals"
],
"screenshot": "https://acme.com/features/forecasting/screenshot.png",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "312"
},
"offers": {
"@type": "Offer",
"price": "49",
"priceCurrency": "USD"
},
"publisher": { "@id": "https://acme.com/#org" }
},
{
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "How accurate is Acme's AI forecasting?",
"acceptedAnswer": {
"@type": "Answer",
"text": "In 2025 customer benchmarks, Acme forecasts landed within 4% of actual quarterly closed-won revenue across 200+ B2B SaaS teams."
}
}
]
}
]
}
</script>
Why this is structured this way: SoftwareApplication tells the LLM 'this is a product of type X with capabilities Y', which is exactly the entity profile AI engines cite when answering 'what tool does X?'.
What JSON-LD should an integrations page use?
Use SoftwareApplication for the host product, plus an ItemList of named integration entities. Each integration is its own SoftwareApplication referenced by name, so AI engines can match queries like 'tools that integrate with Salesforce' to your page.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "SoftwareApplication",
"@id": "https://acme.com/integrations#app",
"name": "Acme",
"applicationCategory": "BusinessApplication",
"operatingSystem": "Web",
"publisher": { "@id": "https://acme.com/#org" }
},
{
"@type": "ItemList",
"@id": "https://acme.com/integrations#list",
"name": "Acme Integrations",
"numberOfItems": 4,
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"item": {
"@type": "SoftwareApplication",
"name": "Salesforce",
"url": "https://acme.com/integrations/salesforce",
"applicationCategory": "CRM"
}
},
{
"@type": "ListItem",
"position": 2,
"item": {
"@type": "SoftwareApplication",
"name": "HubSpot",
"url": "https://acme.com/integrations/hubspot",
"applicationCategory": "CRM"
}
},
{
"@type": "ListItem",
"position": 3,
"item": {
"@type": "SoftwareApplication",
"name": "Slack",
"url": "https://acme.com/integrations/slack",
"applicationCategory": "Communication"
}
},
{
"@type": "ListItem",
"position": 4,
"item": {
"@type": "SoftwareApplication",
"name": "Snowflake",
"url": "https://acme.com/integrations/snowflake",
"applicationCategory": "DataWarehouse"
}
}
]
}
]
}
</script>
Why this is structured this way: ItemList is the schema type that drives 74% of AI listicle citations per G2's 2025 AEO research. Naming each integration as a SoftwareApplication lets the LLM extract a clean list when asked 'what does Acme integrate with?'.
What JSON-LD should a blog post use?
Use Article with a Person author, an Organization publisher, and a nested FAQPage for any Q&A in the post. This is the highest-citation combo for editorial content.
Per Frase's FAQ schema research, pages with FAQPage markup are 3.2x more likely to appear in Google AI Overviews. Adding a real Person author with jobTitle and sameAs reinforces E-E-A-T signals.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Article",
"@id": "https://acme.com/blog/aeo-guide#article",
"headline": "The 2026 Guide to AEO for B2B SaaS",
"description": "How to get cited by ChatGPT, Perplexity, and Google AI Overviews.",
"image": "https://acme.com/blog/aeo-guide/cover.png",
"datePublished": "2026-04-15T09:00:00-04:00",
"dateModified": "2026-05-03T11:00:00-04:00",
"author": {
"@type": "Person",
"@id": "https://acme.com/team/peter-foy#person",
"name": "Peter Foy",
"jobTitle": "Head of Growth",
"url": "https://acme.com/team/peter-foy",
"sameAs": [
"https://www.linkedin.com/in/peterfoy",
"https://twitter.com/peterfoy"
]
},
"publisher": { "@id": "https://acme.com/#org" },
"mainEntityOfPage": "https://acme.com/blog/aeo-guide"
},
{
"@type": "FAQPage",
"@id": "https://acme.com/blog/aeo-guide#faq",
"mainEntity": [
{
"@type": "Question",
"name": "What is AEO?",
"acceptedAnswer": {
"@type": "Answer",
"text": "AEO is Answer Engine Optimization: structuring content so AI engines cite it."
}
}
]
}
]
}
</script>
Why this is structured this way: dateModified is one of the strongest freshness signals AI engines use, and Person + Organization references via @id build a single coherent entity graph the LLM can ground to.
What JSON-LD should an 'X vs Y' comparison page use?
Use Article as the wrapper, ItemList to rank the two products as structured items, and FAQPage for the comparison's most-asked questions. This combo maps directly to how AI engines summarize 'X vs Y' queries.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Article",
"@id": "https://acme.com/compare/acme-vs-rival#article",
"headline": "Acme vs Rival: 2026 Comparison for B2B Sales Teams",
"datePublished": "2026-03-01T09:00:00-05:00",
"dateModified": "2026-05-03T11:00:00-04:00",
"author": { "@id": "https://acme.com/team/peter-foy#person" },
"publisher": { "@id": "https://acme.com/#org" }
},
{
"@type": "ItemList",
"@id": "https://acme.com/compare/acme-vs-rival#list",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"item": {
"@type": "SoftwareApplication",
"name": "Acme",
"applicationCategory": "BusinessApplication",
"url": "https://acme.com",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "312"
}
}
},
{
"@type": "ListItem",
"position": 2,
"item": {
"@type": "SoftwareApplication",
"name": "Rival",
"applicationCategory": "BusinessApplication",
"url": "https://rival.com",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.4",
"reviewCount": "205"
}
}
}
]
},
{
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Is Acme cheaper than Rival?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Acme starts at $49/user/month vs Rival's $69/user/month for comparable feature sets."
}
}
]
}
]
}
</script>
Why this is structured this way: ItemList with two SoftwareApplications gives the LLM a clean head-to-head structure. Including aggregateRating for both makes the comparison falsifiable and citable.
What JSON-LD should a tool or calculator page use?
Use WebApplication for the tool itself plus HowTo for the steps to use it. WebApplication signals 'this is interactive software running in a browser', which is what calculators and free tools are.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "WebApplication",
"@id": "https://acme.com/tools/roi-calculator#app",
"name": "Sales ROI Calculator",
"url": "https://acme.com/tools/roi-calculator",
"applicationCategory": "BusinessApplication",
"browserRequirements": "Requires JavaScript",
"operatingSystem": "Web",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
"publisher": { "@id": "https://acme.com/#org" }
},
{
"@type": "HowTo",
"@id": "https://acme.com/tools/roi-calculator#howto",
"name": "How to calculate sales ROI with Acme",
"totalTime": "PT2M",
"step": [
{
"@type": "HowToStep",
"position": 1,
"name": "Enter your average deal size",
"text": "Type your average closed-won deal size in USD."
},
{
"@type": "HowToStep",
"position": 2,
"name": "Enter your win rate",
"text": "Enter your sales team's win rate as a percentage."
},
{
"@type": "HowToStep",
"position": 3,
"name": "Read your projected ROI",
"text": "The calculator returns your projected 12-month revenue lift."
}
]
}
]
}
</script>
Why this is structured this way: free tools earn citations because LLMs love linking to interactive resources. Marking the steps with HowTo gives Perplexity and ChatGPT a ready-made answer to 'how do I calculate X?'.
What JSON-LD should a customer story or case study use?
Use Article as the container, Review to capture the customer's verdict (the citable quote), and a nested Organization for the customer entity. Naming the customer as a real Organization lets AI engines cite the case in queries like 'who uses Acme?'.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Article",
"@id": "https://acme.com/customers/initech#article",
"headline": "How Initech cut sales cycle time 38% with Acme",
"datePublished": "2026-02-10T09:00:00-05:00",
"author": { "@id": "https://acme.com/team/peter-foy#person" },
"publisher": { "@id": "https://acme.com/#org" },
"about": { "@id": "https://initech.example.com/#org" }
},
{
"@type": "Organization",
"@id": "https://initech.example.com/#org",
"name": "Initech",
"url": "https://initech.example.com",
"industry": "FinTech",
"numberOfEmployees": "450"
},
{
"@type": "Review",
"@id": "https://acme.com/customers/initech#review",
"reviewBody": "Acme cut our average sales cycle from 47 days to 29 days in the first quarter.",
"author": {
"@type": "Person",
"name": "Sarah Chen",
"jobTitle": "VP of Sales",
"worksFor": { "@id": "https://initech.example.com/#org" }
},
"itemReviewed": { "@id": "https://acme.com/#org" },
"reviewRating": {
"@type": "Rating",
"ratingValue": "5",
"bestRating": "5"
}
}
]
}
</script>
Why this is structured this way: AI engines treat third-party validation as higher-trust than first-party claims. Marking the customer as a real Organization with industry and numberOfEmployees, and the testimonial as a Review with a named Person from that company, gives the LLM the entity graph it needs to cite Initech's outcome by name.
How do I validate JSON-LD for AI search, not just Google rich results?
Validate twice. First, run the Schema.org Validator for spec compliance. Second, run the Google Rich Results Test for Google-specific eligibility. Then confirm the JSON-LD is server-rendered.
The two validators do different jobs:
- Schema.org Validator: catches spec violations (wrong property types, invalid enums, missing required fields). It validates everything, including types Google does not show as rich results.
- Google Rich Results Test: only flags types that produce rich results in Google search. It will silently ignore valid types like
OrganizationorWebApplication.
Then run a third check most teams skip:
curl -A 'GPTBot/1.0' https://yoursite.com/page | grep 'application/ld+json'
If grep returns nothing, your schema is JavaScript-injected and invisible to AI crawlers. Move the block to server-rendered HTML before you publish.
For ongoing governance, Schema App and Digispot's free schema visualizer crawl your site and flag drift over time. The 5,000-site schema audit by Digital Applied (2026) found that 41% of B2B sites have schema that validates but is not visible to AI crawlers because it ships client-side. Don't be in that 41%.
| B2B Page Type | Primary Schema | Supporting Schema | Why This Combo |
|---|---|---|---|
| Homepage | Organization | WebSite + SearchAction | Establishes brand entity + sitelinks search box |
| Pricing | Product | Offer + AggregateOffer + FAQPage | Surfaces tier pricing + answers buying questions |
| Features | SoftwareApplication | FAQPage | Describes the product itself, not a purchase |
| Integrations | SoftwareApplication | ItemList of integrations | Lists named third-party apps as entities |
| Blog post | Article | FAQPage + Person (author) | Article body + extractable Q&A + E-E-A-T |
| Comparison (X vs Y) | Article | ItemList + FAQPage | Ranks competing products as a structured list |
| Tool / Calculator | WebApplication | HowTo | Marks the app + explains how to use it |
| Customer Story | Article | Review + Organization (customer) | Third-party validation + named customer entity |