LIVE MONITORINGChatGPT · Claude · Gemini · Grok · DeepSeek · Mistral · Perplexity · AI Overviews (Google) · AI Mode (Google) · Copilot (Microsoft) · Meta AI11 ENGINESv.2026.04 / build 47GENERATIVE ENGINE OPTIMIZATIONLISBON · PORTUGAL
Technical standards9 min read

Schema.org for B2B SaaS: the minimum viable in JSON-LD

The five schema types every B2B SaaS company needs, with JSON-LD snippets ready to paste: Organization, Service, FAQPage, BreadcrumbList and Article.

PTLer em português →

Photo by Nangialai Stoman on Unsplash

For a B2B SaaS company, there are five schema types worth more than all the others combined: Organization, Service, FAQPage, BreadcrumbList and Article. Implemented in JSON-LD, with stable @ids and links between them, they are the minimum viable to start being citable by AI. This piece has the snippet for each one, ready to adapt.

Key takeaways

Why schema matters for GEO

Schema.org is the standard vocabulary for structured data. In HTML, describing something as an organisation is implicit (from tags like header, from CSS classes, from context). In schema, it is explicit: @type: Organization.

For traditional engines, schema unlocks rich results (stars, expanded FAQ, visible breadcrumbs). For LLMs, schema is the only reliable way to know, without ambiguity, what each thing is. When ChatGPT cites "Acme is a cybersecurity consultancy in Lisbon", it is inferring three things, what it is, what it does, where, and schema narrows the room for error.

The five types, one per tab

The @graph idea (and why it matters)

If you have several entities on the same page, you can wrap them in a @graph instead of scattering multiple application/ld+json script blocks:

{
  "@context": "https://schema.org",
  "@graph": [
    { "@type": "Organization", "@id": "https://acme.com/#organization", ... },
    { "@type": "WebSite",      "@id": "https://acme.com/#website",     ... },
    { "@type": "WebPage",      "@id": "https://acme.com/#webpage",     ... },
    { "@type": "Service",      "@id": "https://acme.com/#service-inv", ... },
    { "@type": "FAQPage",      "@id": "https://acme.com/#faq",         ... }
  ]
}

The advantage: less parsing, shared context, explicit links through @id. For LLMs, a coherent graph is significantly more legible than five loose scripts.

How the five link up through @id

Type@idLinks to
Organization#organizationReferenced by the others as provider, author, publisher
Service#service-inventoryprovider → #organization
FAQPage#faqisPartOf → #website
BreadcrumbList/product/inventory#breadcrumbNone in the example
BlogPosting/blog/integrate-sap#articleauthor, publisher → #organization; mainEntityOfPage → /blog/integrate-sap#webpage

Validation is not optional

Schema without validation is a trap. Before deploying, three tools:

Typical mistakes we see

The minimum viable, before deploying

Frequently asked questions

Microdata, RDFa or JSON-LD?

JSON-LD. It is the only one Google explicitly recommends, it is the cleanest to maintain (it separates semantic markup from presentation HTML), and it is what LLMs extract with the highest fidelity. Microdata and RDFa are still supported for compatibility, but they are not worth starting with in 2026.

Where should the JSON-LD go: head or body?

Either works, the specification does not require one. In the Next.js App Router, the typical pattern is to inject it with a JsonLd component inside the page's return (in the body, before the content). In static sites, the head is cleaner. In both cases, one script tag per semantic block avoids duplication.

Do I have to have @id on every entity?

It is not mandatory, but it is the difference between having a set of loose entities and having a coherent graph. With stable @ids (like https://example.com/#organization) you can reference the same entity from several pages without duplicating it. Engines and LLMs strongly prefer linked graphs.

How much schema is too much?

Irrelevant or invented schema is worse than no schema. Each type should correspond to something real on the page. Marking a pricing page as Recipe is plainly wrong; marking it as AggregateOffer makes sense. Rule: if you cannot defend why you put it there, take it out.

Sources