WordPress 分页的 canonical 链接为什么缺少 page/?
结论
这个现象可能是 WordPress 将请求当作单篇文章或独立 Page 的内容分页来处理,尤其要检查静态首页的分页。仅凭 URL 和模板文件名,无法确定具体原因。
get_site_url() 不会返回当前分页 URL。把它写进 canonical,通常只会让第 2 页的 canonical 指向 WordPress 安装地址,无法修复分页地址。
为什么会生成 /2/
WordPress 中有两种分页,需要区分:
- 列表分页:例如文章列表的第 2 页,常见地址为
/page/2/,通常使用查询变量paged。 - 内容分页:例如通过
<!--nextpage-->拆分一篇文章或一个 Page,通常使用查询变量page,固定链接可能表现为/article/2/。
静态首页的分页需要特别检查:页码可能通过 page 获取,不能仅因为地址中出现 page 就判断查询变量是 paged。参见 get_query_var() 文档。
核心的 wp_get_canonical_url() 从 get_permalink() 开始生成地址。当当前对象的 page >= 2 且启用了固定链接时,它会直接追加页码,在这一分支中不会插入 page/。因此,如果基础永久链接是 https://example.xy/,页码是 2,这一逻辑可以解释为什么得到 https://example.xy/2/。这只是根据核心逻辑作出的条件性解释,仍需核对站点实际的查询状态。参见 wp_get_canonical_url() 源码。
先确认页面类型和输出来源
建议按以下顺序排查:
- 在 WordPress 的“设置 → 阅读”中,确认该地址对应静态首页、文章列表页,还是其他页面。
- 检查请求中的
page、paged,以及is_singular()、is_front_page()、is_home()、is_archive()的结果。 - 查看页面源代码,确认 canonical 是否重复,并检查主题、SEO 插件及
get_canonical_url过滤器是否修改了输出。 - 检查自定义分页查询和重写规则是否使用了正确的页码变量。
核心的 rel_canonical() 只为 is_singular() 成立的请求输出标签。如果实际请求是分类归档或文章列表,canonical 可能来自主题或插件;header-archivpage.php 这个文件名本身不能证明请求属于归档。参见 rel_canonical() 源码。
如何修正
如果查询或重写规则把列表分页错误地映射为内容分页,应先修正映射,让页面查询、分页导航和 canonical 使用一致的地址规则。如果 canonical 由 SEO 插件管理,应在该插件的配置或过滤接口中修正。
如果已经确认满足以下条件,可以通过核心过滤器做局部修正:
- 问题发生在静态首页,首页模板展示自定义分页列表。
/page/2/等地址能够正常显示对应列表内容。- canonical 确实由核心
rel_canonical()输出。 - 页码已正确出现在
page或paged中,且不是正文的<!--nextpage-->分页。
在这些前提下,可以将以下代码放入子主题的 functions.php 或站点功能插件:
add_filter( 'get_canonical_url', function ( $canonical_url, $post ) {
if ( ! is_front_page() || ! is_page() ) {
return $canonical_url;
}
if ( (int) $post->ID !== get_queried_object_id() ) {
return $canonical_url;
}
$page_number = max(
1,
(int) get_query_var( 'page', 0 ),
(int) get_query_var( 'paged', 0 )
);
if ( $page_number > 1 ) {
return get_pagenum_link( $page_number, false );
}
return $canonical_url;
}, 10, 2 );
get_pagenum_link() 会依据固定链接设置和分页基础路径生成列表分页链接,避免直接硬编码 /page/。它也可能保留请求中的查询参数;如果站点存在跟踪、筛选或排序参数,需要另外明确这些参数的 canonical 策略。参见 get_pagenum_link() 文档。
使用这一方案时,需要恢复核心的 canonical 输出,并移除模板中手写的标签。示例只适用于上述静态首页场景,不能直接覆盖所有归档页和自定义页面。
为什么原来的临时处理不合适
<link rel="canonical" href="<?php echo get_site_url(); ?>">
get_site_url() 返回 WordPress 应用文件所在的地址,不包含当前请求的分页路径。WordPress 安装在子目录时,它还可能与网站对外首页地址不同。参见 get_site_url() 文档。
对于各页展示不同列表内容的分页序列,应让每页使用自己的 canonical URL,而不是统一指向第 1 页或站点根地址。这也符合 Google 的分页建议。
修正后,检查第 1、2、3 页的内容是否随页码变化、canonical 是否只有一个,以及目标地址是否正常返回且无需再次重定向。末尾斜杠应遵循站点的固定链接规则,不能单凭 /page/2 与 /page/2/ 的差异判断错误。
备注:内容仅供参考。
