Breadcrumb JSON-LD 与可见面包屑不一致

Rich Results Test 过但 Search Console 报 breadcrumb 不一致,或 SERP 面包屑看起来不对——如何让 JSON-LD 与可见 UI 对齐。

页面显示面包屑 “首页 → AI 工具 → ChatGPT 问题”。Rich Results Test 说 BreadcrumbList JSON-LD 有效。但 Search Console Enhancements 报警告,或者 SERP 面包屑显示的层级 / 措辞跟你页面不一样。原因通常是 JSON-LD 跟可见 UI 独立生成——不同数据源、不同标签规则、不同 locale 处理。Google 的规则:JSON-LD 必须跟可见面包屑在标签、URL、顺序上都匹配。即使各自有效,错配也会降权 rich result。

常见原因

按命中率从高到低。

1. JSON-LD 用 slug 但 UI 用展示名

{ "name": "ai-tools", "item": "https://site.com/category/ai-tools/" }

可见 UI 显示 “AI 工具”(大小写 + 空格)。JSON-LD 写 ai-tools(slug)。Google 检测到不一致。

怎么判断:精确对比可见标签与 JSON-LD name。大小写算、空格算。

2. URL 大小写或尾斜杠差异

JSON-LD:https://site.com/Category/AI-Tools。可见链接:https://site.com/category/ai-tools/。逻辑同目标、字符串不同。

怎么判断:检查 anchor 标签的 href 跟 JSON-LD item。必须字节级相同。

3. UI 省略首页、JSON-LD 包含(或反过来)

UI 显示 “AI 工具 → ChatGPT 问题”(无 Home)。JSON-LD 位置 1 是 Home。或 UI 有 Home 但 JSON-LD 没。

怎么判断:数可见面包屑数量 vs. JSON-LD itemListElement.length。应相等。

4. 本地化:JSON-LD 没翻译

ZH 页 UI 显示 “首页 → AI 工具 → ChatGPT 问题”。JSON-LD 仍写 “Home → AI Tools → ChatGPT issues”(英文标签)。Google 报错。

怎么判断:打开非默认语言的页,对比 JSON-LD name 字段跟可见 UI 标签。

5. 加”假的”层级”做 SEO”

有人在 JSON-LD 加了幻影中间层(“Home → AI → Tools → AI Tools → ChatGPT”)以为能加分。UI 显示更少层。Google 视为误导,降权。

怎么判断:数 JSON-LD 位置数。> 可见 UI 数量 + 1 就是有幻影层。

6. BreadcrumbList 顺序错

position: 1, 2, 3 应该从根映射到叶子。反转或乱序会破坏 rich result。

怎么判断:看每项的 position。位置 1 应是 Home(或根)、逐层加 1、终点是当前页。

最短修复路径

第 1 步:对比可见面包屑与 JSON-LD

单页手动 diff:

# 抽可见面包屑的锚文本和 href
curl -s "https://site.com/article/" | grep -oP '<nav[^>]*aria-label="breadcrumb[^>]*>[\s\S]+?</nav>'

# 抽 JSON-LD breadcrumb
curl -s "https://site.com/article/" | grep -oP '"@type":"BreadcrumbList[\s\S]+?</script>'

逐位置对比。

第 2 步:两层从同一源生成

重构 layout,把面包屑算一次、同时生成 UI 和 JSON-LD:

---
const breadcrumb = [
  { name: '首页', url: '/' },
  { name: 'AI 工具', url: '/category/ai-tools/' },
  { name: article.title, url: Astro.url.pathname },
];

const jsonLd = {
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": breadcrumb.map((b, i) => ({
    "@type": "ListItem",
    "position": i + 1,
    "name": b.name,
    "item": new URL(b.url, Astro.site).toString(),
  })),
};
---
<nav aria-label="breadcrumb">
  <ol>
    {breadcrumb.map((b, i) => (
      <li>
        {i < breadcrumb.length - 1
          ? <a href={b.url}>{b.name}</a>
          : <span>{b.name}</span>}
      </li>
    ))}
  </ol>
</nav>
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)}></script>

一个 breadcrumb 数组 → 两种表示。保证一致。

第 3 步:正确本地化

用你的翻译 helper:

const breadcrumb = [
  { name: t('breadcrumb.home'), url: lang === 'en' ? '/' : `/${lang}/` },
  { name: t(`category.${article.category}`), url: `/${lang}/category/${article.category}/` },
  { name: article.title, url: Astro.url.pathname },
];

UI 和 JSON-LD 都用翻译后的标签。

第 4 步:用 Rich Results Test 校验

修后打开 Rich Results Test 测 URL。所有面包屑项都应跟可见面包屑 1:1 对齐。

第 5 步:CI 校验

// scripts/check-breadcrumb.mjs
import fs from 'node:fs';
import { parse } from 'node-html-parser';

for (const file of getDistHtmlFiles()) {
  const root = parse(fs.readFileSync(file, 'utf8'));
  const visibleLabels = root.querySelectorAll('nav[aria-label="breadcrumb"] a, nav[aria-label="breadcrumb"] span')
    .map(el => el.text.trim());
  const jsonLd = JSON.parse(root.querySelector('script[type="application/ld+json"]').text);
  const jsonLdLabels = jsonLd.itemListElement.map(i => i.name);

  if (JSON.stringify(visibleLabels) !== JSON.stringify(jsonLdLabels)) {
    console.error(`MISMATCH in ${file}\n  visible: ${visibleLabels}\n  jsonLd:  ${jsonLdLabels}`);
  }
}

第 6 步:提交给 Google

修后 Search Console → URL Inspection 对代表性 URL 提交。等 1-2 周 Enhancement 报告清。

哪些情况可能不是你操作错了

Search Console “Breadcrumbs” 警告会延迟几天。先信源码对齐,报告会追上。

容易误判的情况

有些团队在 JSON-LD 加额外层级”优化” SEO。Google 视为误导,会压制 rich result。匹配可见的——不多、不少。

预防建议

  • 可见面包屑和 JSON-LD 用同一 helper 生成。
  • 双语站两层都用同一翻译源。
  • CI 断言:可见面包屑文本与 JSON-LD name 数组完全一致。
  • 不要给 SEO 加幻影层——Google 看得穿。
  • 改 URL 结构时同时重新生成两层,不要手动 patch JSON-LD。

FAQ

  • 可以省略首页吗? 允许但 UX 不一致。通常作为位置 1 保留。
  • 最后一项要链到当前页吗? 可选——Google 两种格式都接受,但站内一致性更重要。

相关阅读

标签: #SEO #排查 #排查 #结构化数据 #面包屑 #JSON-LD