JSON-LD Recipes
aeo.js auto-generates WebSite, Organization, and WebPage schemas when schema.enabled: true. For richer page-type-specific schemas, drop these into your page templates.
The safe serializer
Section titled “The safe serializer”JSON.stringify(...) does not escape </script>. A schema value containing </script> (or U+2028 / U+2029) breaks out of the script block and executes as JavaScript. Always run JSON-LD payloads through this helper before injection:
export function serializeJsonForHtml(value: unknown): string { return JSON.stringify(value) .replace(/</g, '\\u003C') .replace(/>/g, '\\u003E') .replace(/&/g, '\\u0026') .replace(/\u2028/g, '\\u2028') .replace(/\u2029/g, '\\u2029');}FAQ Page
Section titled “FAQ Page”const faqSchema = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: [ { '@type': 'Question', name: 'What is Answer Engine Optimization?', acceptedAnswer: { '@type': 'Answer', text: 'AEO is the practice of making your content discoverable and citable by AI-powered answer engines like ChatGPT, Claude, and Perplexity.', }, }, ],};aeo.js auto-detects FAQ patterns (heading ending with ? + answer paragraph) and emits this schema for you when schema.enabled: true.
const howToSchema = { '@context': 'https://schema.org', '@type': 'HowTo', name: 'How to deploy a Next.js site to Vercel', totalTime: 'PT5M', step: [ { '@type': 'HowToStep', position: 1, name: 'Install CLI', text: 'Run `npm install -g vercel`.' }, { '@type': 'HowToStep', position: 2, name: 'Login', text: 'Run `vercel login`.' }, { '@type': 'HowToStep', position: 3, name: 'Deploy', text: 'Run `vercel --prod`.' }, ],};aeo.js auto-detects Step 1: / Step 2: heading patterns.
Article / BlogPosting
Section titled “Article / BlogPosting”const articleSchema = { '@context': 'https://schema.org', '@type': 'BlogPosting', headline: 'Optimizing your site for AI search engines in 2026', image: 'https://mysite.com/og/article-cover.png', datePublished: '2026-05-14T10:00:00Z', dateModified: '2026-05-14T10:00:00Z', author: { '@type': 'Person', name: 'Jane Author' }, publisher: { '@type': 'Organization', name: 'My Site', logo: { '@type': 'ImageObject', url: 'https://mysite.com/logo.png' }, },};Product
Section titled “Product”const productSchema = { '@context': 'https://schema.org', '@type': 'Product', name: 'Acme Espresso Machine', description: 'A semi-automatic espresso machine with built-in grinder.', image: ['https://mysite.com/products/espresso/cover.jpg'], sku: 'ACM-ESP-001', brand: { '@type': 'Brand', name: 'Acme' }, offers: { '@type': 'Offer', url: 'https://mysite.com/products/espresso', priceCurrency: 'USD', price: '899.00', availability: 'https://schema.org/InStock', }, aggregateRating: { '@type': 'AggregateRating', ratingValue: '4.7', reviewCount: '142', },};BreadcrumbList
Section titled “BreadcrumbList”const breadcrumbSchema = { '@context': 'https://schema.org', '@type': 'BreadcrumbList', itemListElement: [ { '@type': 'ListItem', position: 1, name: 'Home', item: 'https://mysite.com/' }, { '@type': 'ListItem', position: 2, name: 'Blog', item: 'https://mysite.com/blog' }, { '@type': 'ListItem', position: 3, name: 'Article Title' }, ],};Injecting safely — per framework
Section titled “Injecting safely — per framework”import { serializeJsonForHtml } from '@/lib/serialize-json-ld';
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: serializeJsonForHtml(faqSchema) }}/>---import { serializeJsonForHtml } from '../lib/serialize-json-ld';---
<script type="application/ld+json" set:html={serializeJsonForHtml(faqSchema)} /><script setup lang="ts">import { serializeJsonForHtml } from '~/utils/serialize-json-ld';
useHead({ script: [{ type: 'application/ld+json', children: serializeJsonForHtml(faqSchema), }],});</script><script lang="ts"> import { serializeJsonForHtml } from './lib/serialize-json-ld'; const schema = serializeJsonForHtml(faqSchema);</script>
<svelte:head> <script type="application/ld+json">{@html schema}</script></svelte:head>Validation
Section titled “Validation”After deploying, paste your URL into one of these:
- Schema Markup Validator — official, quickest
- Google Rich Results Test — Google rich-result eligibility
- Bing Webmaster URL Inspection — Bing/Copilot-specific feedback