本文约 4,408 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:RSS 上那条”首页 › 分类 › 标题”到底被谁用
在搜索结果里看到”example.com › 博客 › WordPress”这种把域名换成层级路径的展示,就是面包屑富媒体结果。它是 SEO 领域少有的”投入产出比仍为正”的结构化数据类型:写一次,全站生效,Google 的接受度长期稳定,且它还能顺带帮助 Google 理解你的站点层级与归属关系——SEO 的收益不只来自搜索结果外观。但它的实现并不总是顺利:不少站点上线三个月,Search Console 的 Breadcrumbs 报表里照样躺着”缺少字段 ‘item'”或”item 无效”的错误,原因往往只是最后一级多加了一个 item、或者 position 从 0 开始写。细节虽小,报错却不会被跳过。
原理分析:三字段模型与 Google 的判定口径
BreadcrumbList 的模型极简:一个 BreadcrumbList,itemListElement 是一个 ListItem 数组,每个 ListItem 含 position(从 1 开始)、name(当前层级显示名)、item(该层级对应的 URL)。Google 的规则里有两条容易踩:一是 item 必须是绝对 URL;二是最后一个 ListItem 代表当前页面本身,Google 允许省略其 item(若没有对应的可见链接),但如果写了就必须是可访问的有效地址。
关于层级设计,还有几个与 SEO 收益直接相关的点:
| 层级设计 | 建议 | 原因 |
|---|---|---|
| 首页作为第 1 级 | 建议 | 强化入口关系 |
| 类目路径取完整层级还是短链 | 保持与页面可见面包屑一致 | 不一致会被判虚假标记 |
| 单篇博客要不要带类目 | 建议带一级主类目 | 帮助 Google 理解栏目归属 |
| 分页、标签归档页 | 不建议标 | 层级不稳定,容易生成重复面包屑 |
在 WordPress 上还有两个现实选择:一是让 SEO 插件(Yoast/Rank Math/SEOPress)统一输出,二是自己接烘焙 导航到主题并输出 JSON-LD。无论哪种,都必须保证”页面可见的面包屑”与”JSON-LD 里的面包屑”层级完全一致,否则属于标记与内容不符。插件与主题双输出的冲突处理思路同避免结构化数据重复输出的方案,评测做法见Rich Results Test 与 Schema Markup Validator 校验流程。
保姆级实操
第一步:先在前端渲染可见面包屑(先有 SE,再有 JSON)
在主题的 header.php 或块模板里渲染,注意最后一级用 span 而非链接:
function mimangfei_breadcrumb_html() {
if ( is_front_page() ) {
return '';
}
$crumbs = [ [ get_bloginfo( 'name' ), home_url( '/' ) ] ];
if ( is_singular( 'post' ) ) {
$cat = get_the_category();
if ( $cat ) {
$crumbs[] = [ $cat[0]->name, get_category_link( $cat[0]->term_id ) ];
}
$crumbs[] = [ get_the_title(), '' ];
} elseif ( is_category() ) {
$crumbs[] = [ single_cat_title( '', false ), '' ];
} elseif ( is_page() ) {
$crumbs[] = [ get_the_title(), '' ];
}
$out = '<nav class="mimangfei-crumbs" aria-label="面包屑"><ol>';
foreach ( $crumbs as $i => $c ) {
$out .= '<li>';
$out .= $c[1] && $i < count( $crumbs ) - 1
? '<a href="' . esc_url( $c[1] ) . '">' . esc_html( $c[0] ) . '</a>'
: '<span>' . esc_html( $c[0] ) . '</span>';
$out .= '</li>';
}
return $out . '</ol></nav>';
}
第二步:从同一份数据生成 JSON-LD,杜绝两处不一致
关键做法是把上面的 $crumbs 抽出来复用,让 HTML 与 JSON-LD 读同一数据源。
add_action( 'wp_head', function () {
if ( is_front_page() ) {
return;
}
$parts = mimangfei_breadcrumb_data();
if ( empty( $parts ) ) {
return;
}
$items = [];
foreach ( $parts as $i => $p ) {
$node = [
'@type' => 'ListItem',
'position' => $i + 1,
'name' => $p['name'],
];
if ( ! empty( $p['url'] ) ) {
$node['item'] = $p['url'];
}
$items[] = $node;
}
$graph = [
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => $items,
];
echo '<script type="application/ld+json">' . wp_json_encode( $graph, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ) . '</script>';
}, 25 );
第三步:接管 Yoast 的面包屑数据而不是另写一份
如果已经在用 Yoast,别在主题里重复输出。用 wpseo_schema_graph_pieces 去掉默认 breadcrumb 片段后,再挂自己的实现;或者更简单——直接改 Yoast 的面包屑数据。
add_filter( 'wpseo_breadcrumb_links', function ( $links ) {
if ( is_singular( 'post' ) && count( $links ) > 2 ) {
// 去掉中间的分类层级,只保留 首页 > 文章标题
return [ $links[0], end( $links ) ];
}
return $links;
} );
第四步:hreflang 与多语言站点要逐语言各自输出
面包屑的 item 必须是该语言版本的 URL,name 也应是对应语言,不能全部指到默认语言。多语言站点建议把面包屑生成放进逐语言渲染的钩子中。
第五步:GSC 面包屑报表验证
进入 Search Console → 富媒体结果 → 面包屑,检查两类状态:错误(阻断展示)与警告(展示但缺字段)。常见错误”缺少字段 ‘item'”对应的是最后一级以外的 ListItem 没写 URL;”item 无效”多为相对路径或 404。
常见踩坑
- position 从 0 开始:必须 1 起算,否则 Google 判定层级错乱。
- 最后一级写了 item 却指向首页:会污染层级结构,建议直接省略。
- 面包屑 HTML 显示三级,JSON-LD 里写四级:这是典型的”标记与内容不符”。
- 分类名被拼音化:
name应该与页面显示的中文一致,不要走 slug。 - AMP/小程序同步页重复输出:多端各有一份会造成”重复字段”警告。
- 案例:一家用 Genesis 老框架的站点,主题带 pasted schema 输出,同时又装了 Yoast,两边都输出面包屑,Yoast 那一份层级是”首页 › 博客 › 标题”,主题那一份是”首页 › 标题”。结果 Google 随机挑一份,SERP 上同一个站的面包屑忽长忽短,用户点击后产生认知不一致。整改时他们禁用了主题内置 JSON-LD,只留插件输出,两周后 GSC 报表的”重复字段”警告清零。
- 改版后旧栏目 URL 变了但面包屑还在用旧链接:Sitemap 与面包屑要一起更新。
总结
判断标准:页面上肉眼看到的面包屑层级,必须和 JSON-LD 里的一字不差,且最后一级可省略 item。行动清单:抽出统一的 $crumbs 数据源 → HTML 与 JSON-LD 共用 → position 从 1 开始 → 最后一级不写 item → 多语言逐版本输出 → GSC 报表修复后点”验证”等待复检。面包屑是全站 ROI 最高的结构化数据之一,值得把它做成模板里最稳的一块。顺着往下看,可以看BreadcrumbList 之外的 Organization / WebSite 站点级结构化数据与GSC 结构化数据报表的错误修复流程。
