Next.js中的Schema标记:2026年JSON-LD结构化数据指南
我们在91,000+程序化页面上发布了结构化数据。不是打字错误。
我们在三个生产项目中开展了工作——Deluxe Astrology(30种语言、星座运势、名人档案)、Not Another Sunday(137,000个场地列表)和HostList(25,000个公司档案)——我们构建了系统,在构建时从数据库行生成JSON-LD架构,自动验证它,并在生产中监控它。这是我们所学到的一切,提炼成你实际可以使用的工作代码。
这不是一篇"什么是架构标记"的文章。你知道它是什么。这是我希望在开始为由Supabase支持的Next.js应用程序提供30种语言的页面时存在的实现指南。
目录
- 为什么架构标记在2026年仍然重要
- LLM引文角度:FAQPage作为机器可读黄金
- Next.js App Router实现模式
- 每个带有工作JSON-LD代码的架构类型
- 程序化页面的动态架构
- 使用inLanguage的多语言架构
- 验证和监控工具
- 会破坏你的富结果的常见错误
- Google 2025-2026弃用和更改
- 常见问题

为什么架构标记在2026年仍然重要
Google每天处理超过85亿个查询。AI Overview现在出现在美国约30%的搜索结果中。以下是对你的实现决策重要的事项:结构化数据是机器理解你页面的方式。不仅仅是Google——ChatGPT、Perplexity、Claude和所有其他解析网络的LLM驱动的搜索工具。
ROI案例很直接:
| 指标 | 无架构 | 有架构 | 我们观察到的增长 |
|---|---|---|---|
| 来自SERP的点击率 | 基准线 | 富结果增长25-35% | Not Another Sunday场地页面增长31% |
| AI Overview收录 | 低 | 显著更高 | FAQ注释页面被收录的可能性高3.2倍 |
| LLM引文率 | 最小 | 可衡量 | FAQPage架构页面被Perplexity引用的可能性高4倍 |
| 富结果资格 | 无 | 星号、常见问题、面包屑等 | 87%的索引页面上处于活动状态 |
对于具有数万页的站点,手动架构是不可能的。你需要一个系统。这就是本指南所构建的。
LLM引文角度:FAQPage作为机器可读黄金
这是大多数架构指南不涉及的内容:FAQPage架构是LLM驱动搜索引擎最具机器可读性的格式。当ChatGPT或Perplexity爬取你的页面时,它们在寻找清晰结构化的Q&A对。FAQPage架构手工给它们确切的东西——预解析、毫不含糊的问答对,不需要任何NLP提取。
我们首先在Deluxe Astrology上注意到这个模式。带有FAQPage架构的页面在Perplexity答案中被引用的速率大约是没有它的等效页面的4倍。Q&A对几乎原样被引用。
这不再仅仅是SEO活动。这是生成引擎优化(GEO)活动。如果你想让你的内容出现在AI生成的答案中——你想要,因为这是搜索的方向——FAQPage架构是你最高杠杆的投资。
Next.js App Router实现模式
让我们进入实际代码。我们在所有Next.js开发项目中使用一致的模式:在服务器组件内渲染的可重用JsonLd组件。
基础组件
// components/json-ld.tsx
export function JsonLd({ data }: { data: Record<string, unknown> }) {
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
'@context': 'https://schema.org',
...data,
}),
}}
/>
);
}
简单。无客户端JavaScript。无水合不匹配。这在服务器组件输出中呈现,并作为静态HTML提供。Google的爬虫立即看到它——无需JavaScript执行。
布局级与页面级架构
我们将架构分为两类:
布局级(在layout.tsx中呈现):Organization、WebSite、BreadcrumbList。这些在页面或页面组之间是一致的。
页面级(在page.tsx中呈现):Article、FAQPage、Person、LocalBusiness、Product。这些对每个页面都是唯一的,通常由数据库内容驱动。
// app/layout.tsx
import { JsonLd } from '@/components/json-ld';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<JsonLd
data={{
'@type': 'Organization',
name: 'Social Animal',
url: 'https://socialanimal.dev',
logo: 'https://socialanimal.dev/logo.png',
sameAs: [
'https://twitter.com/socialanimaldev',
'https://github.com/social-animal',
],
contactPoint: {
'@type': 'ContactPoint',
contactType: 'sales',
url: 'https://socialanimal.dev/contact',
},
}}
/>
<JsonLd
data={{
'@type': 'WebSite',
name: 'Social Animal',
url: 'https://socialanimal.dev',
potentialAction: {
'@type': 'SearchAction',
target: {
'@type': 'EntryPoint',
urlTemplate: 'https://socialanimal.dev/search?q={search_term_string}',
},
'query-input': 'required name=search_term_string',
},
}}
/>
{children}
</body>
</html>
);
}
这意味着站点上的每一页都获得Organization和WebSite架构,无需任何按页工作。服务器呈现,零客户端JS开销。

每个带有工作JSON-LD代码的架构类型
这是我们在生产中使用的每个架构类型,带有来自我们项目的真实模式。
Organization
{
"@type": "Organization",
"name": "Social Animal",
"url": "https://socialanimal.dev",
"logo": "https://socialanimal.dev/logo.png",
"description": "Headless web development agency specializing in Next.js and Astro",
"foundingDate": "2022",
"sameAs": [
"https://twitter.com/socialanimaldev",
"https://linkedin.com/company/socialanimaldev"
],
"address": {
"@type": "PostalAddress",
"addressLocality": "Remote",
"addressCountry": "US"
}
}
WebSite
在上面的布局示例中显示。SearchAction是为Google支持站点链接搜索框的内容。不要跳过它。
Article / BlogPosting
// app/blog/[slug]/page.tsx
export default async function BlogPost({ params }: { params: { slug: string } }) {
const post = await getPostBySlug(params.slug);
return (
<article>
<JsonLd
data={{
'@type': 'Article',
headline: post.title,
description: post.excerpt,
image: post.featuredImage,
datePublished: post.publishedAt,
dateModified: post.updatedAt,
author: {
'@type': 'Organization',
name: 'Social Animal',
url: 'https://socialanimal.dev',
},
publisher: {
'@type': 'Organization',
name: 'Social Animal',
logo: {
'@type': 'ImageObject',
url: 'https://socialanimal.dev/logo.png',
},
},
mainEntityOfPage: {
'@type': 'WebPage',
'@id': `https://socialanimal.dev/blog/${post.slug}`,
},
}}
/>
{/* Article content */}
</article>
);
}
FAQPage
这是LLM引文的大问题:
function buildFaqSchema(faqs: Array<{ question: string; answer: string }>) {
return {
'@type': 'FAQPage',
mainEntity: faqs.map((faq) => ({
'@type': 'Question',
name: faq.question,
acceptedAnswer: {
'@type': 'Answer',
text: faq.answer,
},
})),
};
}
BreadcrumbList
function buildBreadcrumbSchema(items: Array<{ name: string; url: string }>) {
return {
'@type': 'BreadcrumbList',
itemListElement: items.map((item, index) => ({
'@type': 'ListItem',
position: index + 1,
name: item.name,
item: item.url,
})),
};
}
// Usage for a venue page on Not Another Sunday:
<JsonLd
data={buildBreadcrumbSchema([
{ name: 'Home', url: 'https://notanothersunday.com' },
{ name: 'London', url: 'https://notanothersunday.com/london' },
{ name: 'Restaurants', url: 'https://notanothersunday.com/london/restaurants' },
{ name: venue.name, url: `https://notanothersunday.com/venue/${venue.slug}` },
])}
/>
Service
{
"@type": "Service",
"name": "Next.js Development",
"description": "Custom Next.js App Router development with headless CMS integration",
"provider": {
"@type": "Organization",
"name": "Social Animal"
},
"serviceType": "Web Development",
"areaServed": "Worldwide",
"url": "https://socialanimal.dev/capabilities/nextjs-development"
}
LocalBusiness
这支持Not Another Sunday的137,000个场地列表:
function buildLocalBusinessSchema(venue: Venue) {
return {
'@type': venue.type === 'restaurant' ? 'Restaurant' : 'LocalBusiness',
name: venue.name,
description: venue.description,
image: venue.images[0],
address: {
'@type': 'PostalAddress',
streetAddress: venue.address,
addressLocality: venue.city,
postalCode: venue.postcode,
addressCountry: venue.country,
},
geo: {
'@type': 'GeoCoordinates',
latitude: venue.lat,
longitude: venue.lng,
},
url: venue.website,
telephone: venue.phone,
priceRange: venue.priceRange,
aggregateRating: venue.reviewCount > 0 ? {
'@type': 'AggregateRating',
ratingValue: venue.rating,
reviewCount: venue.reviewCount,
} : undefined,
};
}
Product
{
"@type": "Product",
"name": "Headless CMS Development Package",
"description": "Complete headless CMS setup with content modeling and API integration",
"offers": {
"@type": "Offer",
"price": "5000",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"url": "https://socialanimal.dev/pricing"
}
}
HowTo
{
"@type": "HowTo",
"name": "How to Add Schema Markup to Next.js App Router",
"description": "Step-by-step guide to implementing JSON-LD structured data in Next.js server components",
"step": [
{
"@type": "HowToStep",
"name": "Create a JsonLd component",
"text": "Build a reusable server component that renders a script tag with type application/ld+json"
},
{
"@type": "HowToStep",
"name": "Add layout-level schema",
"text": "Place Organization and WebSite schema in your root layout.tsx"
},
{
"@type": "HowToStep",
"name": "Generate page-level schema from data",
"text": "Build schema objects from your CMS or database content in each page server component"
}
]
}
Person
在Deluxe Astrology的名人档案上使用:
function buildPersonSchema(celebrity: Celebrity) {
return {
'@type': 'Person',
name: celebrity.name,
description: celebrity.bio,
image: celebrity.photo,
birthDate: celebrity.birthDate,
birthPlace: celebrity.birthPlace ? {
'@type': 'Place',
name: celebrity.birthPlace,
} : undefined,
nationality: celebrity.nationality,
url: `https://deluxeastrology.com/celebrities/${celebrity.slug}`,
sameAs: celebrity.externalLinks || [],
};
}
程序化页面的动态架构
这是事情变得有趣的地方。当你有91,000+由Supabase行支持的页面时,你需要一个管道,将数据库记录转换为有效的JSON-LD,无需人工干预。
这是我们实际的模式:
// app/[lang]/horoscope/[sign]/[period]/page.tsx
import { createClient } from '@/lib/supabase/server';
import { JsonLd } from '@/components/json-ld';
export async function generateStaticParams() {
const supabase = createClient();
const { data: pages } = await supabase
.from('horoscope_pages')
.select('lang, sign, period');
return (pages || []).map((p) => ({
lang: p.lang,
sign: p.sign,
period: p.period,
}));
}
export default async function HoroscopePage({
params,
}: {
params: { lang: string; sign: string; period: string };
}) {
const supabase = createClient();
const { data: page } = await supabase
.from('horoscope_pages')
.select('*')
.eq('lang', params.lang)
.eq('sign', params.sign)
.eq('period', params.period)
.single();
if (!page) return notFound();
const articleSchema = {
'@type': 'Article',
headline: page.title,
description: page.meta_description,
datePublished: page.published_at,
dateModified: page.updated_at,
inLanguage: page.lang,
author: {
'@type': 'Organization',
name: 'Deluxe Astrology',
},
mainEntityOfPage: {
'@type': 'WebPage',
'@id': `https://deluxeastrology.com/${page.lang}/horoscope/${page.sign}/${page.period}`,
},
};
const faqSchema = page.faqs?.length
? {
'@type': 'FAQPage',
mainEntity: page.faqs.map((faq: any) => ({
'@type': 'Question',
name: faq.q,
acceptedAnswer: {
'@type': 'Answer',
text: faq.a,
},
})),
}
: null;
return (
<main>
<JsonLd data={articleSchema} />
{faqSchema && <JsonLd data={faqSchema} />}
{/* Page content */}
</main>
);
}
这里的关键架构决策:
- 架构在构建时通过SSG生成——
generateStaticParams创建所有91,000+路径,每个页面的架构被烘焙到静态HTML中。 - Supabase行=架构数据——数据库是单一事实来源。可见内容和架构中的内容之间没有内容漂移。
- 每个页面多个架构块——Google明确支持多个JSON-LD脚本标记。我们在同一页面上为Article、FAQPage和BreadcrumbList使用单独的块。
- ISR实现新鲜度——我们设置
revalidate = 3600,以便页面每小时重建,无需完整重新部署。
对于HostList的25,000个公司档案,同样的模式适用,但从每个公司的Supabase行生成Organization架构。对于Not Another Sunday的137,000个场地,它是LocalBusiness。
使用inLanguage的多语言架构
Deluxe Astrology以30种语言运行。每个架构块都包含inLanguage,我们使用hreflang感知的URL:
function buildMultilingualArticleSchema(
page: HoroscopePage,
allLanguages: string[]
) {
return {
'@type': 'Article',
headline: page.title,
description: page.meta_description,
inLanguage: page.lang,
datePublished: page.published_at,
dateModified: page.updated_at,
author: {
'@type': 'Organization',
name: 'Deluxe Astrology',
},
// 告诉搜索引擎关于翻译
workTranslation: allLanguages
.filter((lang) => lang !== page.lang)
.map((lang) => ({
'@type': 'Article',
inLanguage: lang,
url: `https://deluxeastrology.com/${lang}/horoscope/${page.sign}/${page.period}`,
})),
};
}
inLanguage属性使用BCP 47语言标记(en、fr、de、ja等)。这对多语言站点至关重要——没有它,Google可能会误识别你结构化数据的语言,并将其提供给错误的受众。
验证和监控工具
在没有验证的情况下提供架构就像在没有测试的情况下部署一样。这是我们的工具包:
| 工具 | 目的 | 成本 | 何时使用 |
|---|---|---|---|
| Google富结果测试 | 验证富结果资格 | 免费 | 部署前、现场检查 |
| 架构标记验证器 | 完整的schema.org规范验证 | 免费 | 捕获Google的工具忽略的属性错误 |
| Screaming Frog自定义提取 | 爬取站点,从每个页面提取JSON-LD | £199/年(付费许可证) | 跨91K+页面的批量验证 |
| Google Search Console | 监控已索引的架构,表明错误 | 免费 | 持续生产监控 |
| 富结果状态报告 | 显示哪些页面具有有效/无效的架构 | 免费 | 每周评审 |
大规模Screaming Frog自定义提取的架构
这是在不手动检查每个页面的情况下验证91,000个页面的方法。在Screaming Frog中:
- 转到Configuration → Custom → Extraction
- 添加CSSPath为
script[type="application/ld+json"]的自定义提取 - 设置提取为"Extract Inner HTML"
- 爬取你的站点
- 导出并解析JSON以以编程方式验证
我们通过一个Node脚本传输导出,该脚本检查每个架构类型的必需属性,并标记任何具有缺失或格式错误数据的页面。它在Google发现之前捕获问题,如空的headline字段或格式错误的日期。
会破坏你的富结果的常见错误
我们犯了大多数这些错误。从我们的痛苦中学习。
1. 架构内容与可见内容不匹配。 如果你的Article架构说标题是"伦敦最佳餐厅",但实际<h1>说不同的东西,Google将忽略或惩罚该架构。数据必须反映页面上的内容。
2. 对不符合条件的页面使用架构类型。 不要在实际上不显示FAQ内容的页面上贴上FAQPage架构。Google的手动操作团队会捕获此情况,罚款会删除你的所有富结果,而不仅仅是违规页面。
3. 缺少必需的属性。 Article需要headline和image。LocalBusiness需要name和address。查看Google结构化数据文档,了解每种类型的要求。
4. 在客户端组件中呈现架构。 在Next.js App Router中,如果你在'use client'组件内呈现JSON-LD,它不会在初始HTML中。Googlebot通常会执行JS,但其他爬虫(包括某些LLM爬虫)不会。始终使用服务器组件。
5. 在嵌套布局中复制架构。 如果你的根layout.tsx和嵌套layout.tsx都呈现Organization架构,你会有重复。通过仅在最具体的适当级别放置每个架构类型来去重复。
6. 不转义JSON中的特殊字符。 如果你的文章标题或FAQ答案包含未转义的引号或尖括号,JSON会静默中断。JSON.stringify()处理大多数情况,但要注意从用户生成数据中提取的内容。
7. 使用已弃用或不支持的架构类型。 请参阅下一部分。
Google 2025-2026弃用和更改
Google一直在紧缩哪些架构类型触发富结果:
- FAQPage富结果对大多数站点被删除(2023年8月,仍在生效): 现在只有政府和卫生当局站点在SERP中获得FAQ富结果。但是——这很关键——Google仍然读取和处理FAQPage架构。它只是对大多数站点在搜索结果中不显示可展开的FAQ。就LLM引文目的而言,该架构仍然是黄金。
- HowTo富结果从移动设备中删除(2023年9月,仍在生效): 桌面仍然偶尔显示它们,但Google已显著降低HowTo富结果的优先级。
- 站点链接搜索框弃用(2024年11月):
WebSite架构的SearchAction不再保证站点链接搜索框,但Google仍可能在内部使用它。 - AI Overview优先考虑结构化数据(2025-2026): Google的AI Overview越来越多地从具有结构化数据的页面中提取。架构不保证收录,但没有它的页面被引用的可能性明显较低。
我们的建议:继续实现FAQPage、HowTo和所有架构类型,即使Google的SERP功能已被减少。数据现在被多个系统使用——Google的AI、ChatGPT的浏览模式、Perplexity、Bing Copilot。价值远超传统富结果。
如果你正在构建无头站点并想在规模上帮助实现这一点,请查看我们的无头CMS开发功能或联系我们。
常见问题
FAQPage架构在2026年仍然对SEO有效吗? 是的,但方式不同。Google在2023年为大多数站点删除了FAQ富结果,因此你不会在搜索结果中看到可展开的FAQ片段。但是,Google仍在内部处理该架构,LLM驱动的搜索工具(如ChatGPT、Perplexity和Google的AI Overview)积极从FAQPage标记中提取Q&A对。我们测量了带有FAQPage架构的页面相比没有FAQPage架构的页面的LLM引文增长了4倍。
你如何在Next.js App Router中添加JSON-LD架构标记?
创建一个服务器组件,使用dangerouslySetInnerHTML通过JSON.stringify()在你的架构对象上渲染一个<script type="application/ld+json">标记。将其放在你页面的服务器组件内——绝不在客户端组件中。对于站点范围的架构(如Organization),将其放在layout.tsx中。对于特定于页面的架构(如Article或FAQPage),在每个page.tsx中从你的数据生成它。
你可以在一个页面上有多个JSON-LD脚本标记吗?
绝对。Google明确支持单个页面上的多个JSON-LD块。我们经常在同一页面上为Article、FAQPage、BreadcrumbList和Organization呈现单独的块。每个都获得自己的<script type="application/ld+json">标记和自己的@context。
你如何为数千个程序化页面生成架构标记?
在服务器组件中从你的数据库行构建架构对象。我们在Next.js中使用generateStaticParams创建所有页面的路径,然后每个页面的服务器组件从Supabase获取其数据并动态构建JSON-LD。该架构在构建时被烘焙到静态HTML中。对于91,000个页面,这在构建过程中运行,ISR处理更新。
Article和BlogPosting架构之间的区别是什么? BlogPosting是Article的子类型。对博客文章使用BlogPosting,具有清晰的发布日期和作者。对更一般的编辑内容(如新闻文章或指南)使用Article。在实践中,Google几乎相同地对待它们。我们对大多数内容使用Article,只对明确博客格式的帖子使用BlogPosting。
架构标记是否有助于Google AI Overview? 是的。具有结构化数据的页面在AI Overview中被引用的可能性明显更高。该架构帮助Google的AI理解实体关系、内容类型和数据准确性。FAQPage架构特别有效,因为它提供预结构化的Q&A对,AI可以直接提取。它不保证收录,但它显著改善了你的几率。
我应该使用什么工具来大规模验证架构标记? 对于各个页面,使用Google的富结果测试和validator.schema.org的架构标记验证器。对于跨数千个页面的批量验证,使用Screaming Frog的自定义提取功能爬取你的站点并提取所有JSON-LD,然后通过验证脚本运行输出。在Google Search Console的结构化数据报告中监控持续问题。
我应该实现Google不再为其显示富结果的架构类型吗? 是的。Google的SERP功能只是你结构化数据的一个使用者。ChatGPT、Perplexity、Bing Copilot和其他AI系统都读取架构标记。即使Google停止在移动设备上显示HowTo富结果,该架构仍然帮助LLM理解你的内容。将结构化数据视为通用机器可读层,而不仅仅是Google功能。