修复 Rich Results Test 的警告和错误(JSON-LD)

Rich Results Test 显示 JSON-LD 有警告 / 字段无效。先分清错误和警告,再逐条修。

把 URL 粘进 Google Rich Results Test,页面满屏标红标黄:Missing field "image"Missing field "datePublished"The value "string" is not a valid date。Search Console 的结构化数据报告也是一样。富 snippet——星级、面包屑、商品信息——在搜索里不出现。

最快的修法:在 Rich Results Test 的结果里,先把红色的**错误(error)和黄色的警告(warning)**分开。红色错误会直接挡掉富结果,必须修。黄色警告是缺了推荐(可选)字段——锦上添花,但不会挡富结果。然后在模板层逐条修错误,而不是逐篇修,这样才不会反复出现。JSON-LD 必须严格匹配 schema.org,并且以 Rich Results Test 为准。

一个最容易踩的坑:截至 2026 年 6 月,FAQPageHowTo 已经不再产生任何 Google 富结果(下文细说)。如果你的”警告”出在 FAQ 或 HowTo 标记上,那对 Google 来说没什么可修的——富结果已经没了,跟标记对不对无关。

错误还是警告:你看的是哪个?

这是最有用的一条区分,老版的 “Structured Data Testing Tool” 从来没把它说清楚。

信号颜色含义富结果还出吗?
错误 Error这个富结果需要的字段缺失或类型错不出——修好前不具备资格
警告 Warning缺了一个推荐(可选)字段出——富结果照样能出,这个字段只是锦上添花

有两点要记牢:

  • 一个页面可以是绿色 / 有效但带警告,照样拿到富结果。你不必把每条警告都清掉。
  • 测试通过不等于一定会出富结果——只代表你具备资格失败(红色错误)才代表不具备资格。是否展示由 Google 按质量、查询、内容匹配度决定。

所以改代码之前:先打开结果,点开 item 类型,看清每行是 error 还是 warning。

常见原因

按命中率从高到低。

1. 缺了 Google 需要的字段(错误)

Google 的 Article 文档说技术上没有必需属性,但你少了 headlineimagedatePublishedauthor,就拿不到 Article 富结果。测试会报成 Missing field

怎么判断:Rich Results Test → 点开检测到的 item → 找红色 Missing field 行。

按类型最常缺的:

Schema经常缺的字段严重度
Article / BlogPosting / NewsArticleimageauthor.namedatePublished错误(缺了就没富结果)
BreadcrumbListitemListElement[].positionitem错误(至少要 2 个列表项)
Productimageoffers.priceoffers.priceCurrency错误
RecipeimagerecipeIngredientrecipeInstructions错误
VideoObjectnamethumbnailUrluploadDate错误

2. 数据类型错(错误)

字段要 date 你给了一段自由文本。要 URL 你给了路径。要 Person 对象你给了裸名字字符串。

"datePublished": "May 2026"    // 错:不是 ISO 8601
"datePublished": "2026-05-17T00:00:00Z"  // 对(日期 + 时间 + 时区)
"author": "Liziang Zheng"               // 错:裸字符串
"author": { "@type": "Person", "name": "Liziang Zheng" }  // 对

注意:author.name 只放名字——不要职位、不要 “By”、不要出版方前缀。

3. schema 类型用错

教程标成 Product 想蹭星级、链接列表标成 Recipe。这违反 Google 的结构化数据政策:只标记页面上实际可见、且与类型匹配的内容。一个 Product"price": "49.99" 而页面显示 $59.99,在测试器里能通过,却违反政策,可能招来人工处罚(manual action)。

怎么判断:读 Google schema 参考里对应你内容类型的部分;@type 跟实际内容对不上就改。

4. 这个类型已经不产生富结果了(FAQPage / HowTo)

截至 2026 年 6 月,Google 已经下线了好几种富结果类型。如果你的警告出在这些上面,对 Google 没有可修的——富结果对所有人都没了。

  • FAQPage——FAQ 富结果在 2026 年 5 月 7 日起不再在搜索里展示。Search Console 的 FAQ 富结果报告、以及 Rich Results Test 里的 FAQ 支持在 2026 年 6 月移除;Search Console API 的 FAQ 支持在 2026 年 8 月移除。(见 Search Engine Land。)
  • HowTo——自 2023 年起任何位置都不再出 HowTo 富结果。
  • 2025 年中下线的:Book ActionsCourse InfoClaim ReviewEstimated SalaryLearning VideoSpecial AnnouncementVehicle Listing

这些 schema 类型在 schema.org 上仍然有效,留着也不会报错或招来人工处罚,只是现在对 Google SERP 没有任何加成了。标记可以留(别的引擎和 AI 界面可能还会读)也可以删——你定。

5. 多个 JSON-LD 块冲突(错误或警告)

一页里有两个 <script type="application/ld+json"> 块——一个说 Article、一个说 BlogPosting,或者声明了不同的 @id。Google 读所有块,不一致就报警告或错误。

怎么判断

curl -s "https://yoursite.com/article" | grep -c '<script type="application/ld+json">'

计数大于 1 说明有多个块。合到一个里(确实需要多类型就用 @graph)。

6. URL 字段是相对路径(错误)

"image": "/og-cover.png"——Google 需要绝对、可抓取的 URL。用 "https://yoursite.com/og-cover.png"。图片还必须可索引(不被 robots.txt 挡),总像素至少 50,000(宽乘高),且为 Google 支持的格式。

7. 字段超出实用上限(警告)

headline 要简短——太长会被截断。name 别太长,description 别太离谱。这些一般报成警告,不是错误。

8. JSON 语法错(错误)

尾逗号、未转义引号、括号类型用错。Rich Results Test 报 Cannot parse content as JSON

怎么判断:把 JSON-LD 块粘进 jsonlint.com 之类的校验器。

最短修复路径

第 1 步:测受影响的 URL 并分类

打开 Rich Results Test → 输入线上 URL → 点开检测到的 item 类型 → 展开问题。

每一行都记下:

  • 是红色(错误——必须修)还是黄色(警告——可选)?
  • 哪个 JSON-LD 块(行号范围)
  • 哪个字段
  • 期望类型 vs. 你提供的值

先修错误。有余力再去清警告。

第 2 步:建一份正确基线

不要手写 JSON-LD。从一份已知正确的模板开始。Article 页面:

{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "文章标题",
  "image": ["https://yoursite.com/og-cover.png"],
  "datePublished": "2026-05-17T00:00:00Z",
  "dateModified": "2026-05-22T00:00:00Z",
  "author": {
    "@type": "Person",
    "name": "作者名",
    "url": "https://yoursite.com/about"
  },
  "publisher": {
    "@type": "Organization",
    "name": "站点名",
    "logo": {
      "@type": "ImageObject",
      "url": "https://yoursite.com/logo.png"
    }
  },
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://yoursite.com/article"
  }
}

第 3 步:多类型用 @graph

确实要在同一页放 ArticleBreadcrumbList,就放进一个块里:

{
  "@context": "https://schema.org",
  "@graph": [
    { "@type": "Article", "@id": "https://yoursite.com/article#article" },
    { "@type": "BreadcrumbList", "@id": "https://yoursite.com/article#breadcrumb" }
  ]
}

一个 <script> 块,两种类型,不冲突。@id 用以 #identifier 结尾的稳定值,让实体干净地互相关联、不重复。(注意:别为了富结果往这里塞 FAQPage,它已经不出富结果了。)

第 4 步:在模板层修

不要逐篇修。找到 layout 的 JSON-LD 生成器,一次修复。Astro:

---
const { article } = Astro.props;
const jsonLd = {
  "@context": "https://schema.org",
  "@type": "Article",
  headline: article.title,
  image: [new URL(article.image, Astro.site).toString()],
  datePublished: new Date(article.publishedAt).toISOString(),
  // ...
};
---
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)}></script>

new URL(..., Astro.site) 保证绝对 URL,.toISOString() 保证合法的 ISO 8601 日期——这正是两个最常见的错误来源。

第 5 步:CI 校验

在上线前就拦住”缺字段”这类错误:

// scripts/check-json-ld.mjs
import fs from 'node:fs';
import path from 'node:path';

const required = {
  Article: ['headline', 'image', 'datePublished', 'author'],
  BlogPosting: ['headline', 'image', 'datePublished', 'author'],
  Product: ['name', 'image', 'offers'],
  BreadcrumbList: ['itemListElement'],
  // ...
};

function walk(dir) {
  for (const f of fs.readdirSync(dir)) {
    const p = path.join(dir, f);
    if (fs.statSync(p).isDirectory()) walk(p);
    else if (p.endsWith('.html')) {
      const html = fs.readFileSync(p, 'utf8');
      const matches = html.match(/<script type="application\/ld\+json">([\s\S]+?)<\/script>/g) || [];
      for (const m of matches) {
        const json = JSON.parse(m.replace(/<\/?script[^>]*>/g, ''));
        const type = json['@type'];
        for (const field of (required[type] || [])) {
          if (!json[field]) console.error(`MISSING ${field} in ${type} at ${p}`);
        }
      }
    }
  }
}

walk('dist');

第 6 步:重测,再重新抓取

部署后:

  1. 对线上 URL 重跑 Rich Results Test → 错误消失(有警告没关系)。
  2. Search Console → URL Inspection → 输入 URL → Request indexing,让 Google 重新抓取、读到新标记。
  3. 等大约 1-2 周,Search Console 的结构化数据报告刷新(它按抓取数据更新,不是实时的)。

怎么确认修好了

  • Rich Results Test 把 item 类型显示为**有效(valid)**且没有红色错误。黄色警告无所谓。
  • URL Inspection → “View tested page” → 渲染出的 JSON-LD 里有你修好的字段。
  • 一两周后,Search Console 结构化数据报告把该 URL 从 Invalid 移到 Valid(或 Valid with warnings)。
  • 搜索里真的出现了 snippet——用 site: 查询或直接搜页面标题验证。记住:具备资格是必要条件,不是充分条件,是否展示仍由 Google 决定。

预防建议

  • 用一份模板生成 JSON-LD,永远别逐篇手写。
  • 每页一个 <script type="application/ld+json"> 块;多类型用 @graph
  • 日期用带时区的 ISO 8601:2026-05-17T00:00:00Z。永远不要 “May 2026” 或 “5/17/2026”。
  • 只用绝对、可抓取、可索引的 URL。
  • 别再为了 Google 富结果在 FAQPage / HowTo 标记上花功夫——截至 2026 年这些位置已经没了。
  • 每次部署都跑上面的 CI 校验(或对抽样 URL 调 Rich Results Test API)。

常见问题

一条黄色警告会挡掉我的富结果吗? 不会。警告标的是缺了推荐字段,富结果照样能出。只有红色错误才挡资格。先修错误,警告当打磨。

我的 FAQ 标记报警告 / 从报告里消失了,要修什么? 对 Google 来说不用修。FAQ 富结果在 2026 年 5 月 7 日起不再展示,FAQ 支持在 2026 年 6 月从 Rich Results Test 和 Search Console 报告里移除(API 在 8 月移除)。FAQPage 类型在 schema.org 仍有效,也不会带来处罚——留着或删掉都行。

全修好了、测试也绿了,但没出 snippet,为什么? 测试通过只代表具备资格,不是保证。是否展示由 Google 按查询、内容质量、新鲜度决定。也给点时间:用 URL Inspection 重新抓取,再等几天到一两周。

datePublished 必须是真实日期吗? 测试器只检查格式、不检查真假——2026-01-15 即使你 2024 年才发也能过。但伪造日期违反 Google 政策,可能反噬。用 ISO 8601 写真实发布日期。

错误 vs. 警告——到底在哪看哪个是哪个? 在 Rich Results Test 里点开检测到的 item 类型展开。错误是红色、列在该 item 下;警告是黄色。Search Console 报告用同样的标签:Invalid(错误)、Valid with warningsValid

结构化数据该逐页修还是在 layout 里修? 在 layout 里修。如果一篇文章错了,几乎都是生成它的模板出了问题,所以每篇都带同样的 bug。把生成器修一次(第 4 步)再部署。

相关阅读

标签: #排查 #SEO #排查 #结构化数据 #Rich Results