一个运行了两年多的 WordPress 站,某天用 SEO 工具一扫,47 个 H2,2 个 H1。不是某篇文章的问题,是全站每一篇文章都是这个结构。标题层级乱成这样,搜索引擎爬虫看到的页面结构跟作者想表达的完全不是一回事。
如果你用 GeneratePress + GP Elements 搭建过文章模板,这篇文章可能会帮你省下几个小时排查时间。
怎么发现有问题的
起因是给网站做 SEO 审计。跑了一遍 Screaming Frog,标题层级报告里赫然写着:
- 全站 2 个 H1(应该只有 1 个)
- 每篇文章 47 个 H2(文章实际只有 6-8 个小标题)
- H3 数量为 0,层级完全扁平
打开浏览器 DevTools,在文章页跑了一下:
// 浏览器 Console 里跑
document.querySelectorAll('h1').length // → 2
document.querySelectorAll('h2').length // → 47
document.querySelectorAll('h3').length // → 0
47 个 H2。文章里明明只有几个二级标题,剩下四十多个 H2 是哪来的?
排查:多出来的 H2 来自哪里
逐个检查 DOM,发现这些多余的 H2 分布在:侧边栏的“相关文章”标题、文章列表的每一项链接、footer 的小标题……全站所有本该是 div 或 span 的地方,都被渲染成了 H2。
问题定位到 GP Elements。GeneratePress 的 Elements 功能允许你在不用写代码的情况下创建全局模板:Page Hero(文章头部)、Content Template(内容区)、Hook(注入代码到各个位置)。
这个站用了好几个 Elements,其中一个 Page Hero Element 负责渲染文章标题区。在这个 Element 里,标题被设置成了 h1。但 WordPress 的文章标题本身就渲染为 h1,于是就出现了双 H1。
更隐蔽的问题是:有一个 Hook Element 被用来注入侧边栏和底部区域的动态内容。这个 Hook 自动把内部元素的标题全部默认输出为 H2:于是侧边栏的“最新文章”“相关推荐”、底部的“关于作者”……每一个都变成了 H2。
修复方案:两种路线
路线 A:在 GP Elements 里改标签(最快,但不彻底)
WP 后台 → 外观 → Elements → 找到 Page Hero Element → 编辑 → 在右侧面板把 Heading 的 Tag Name 从 h1 改成 h2。
这样文章标题变成 H2,页面本体不输出 H1(因为这个站用的是自定义子主题,H1 在主题模板里硬编码了)。
缺点:如果你有好几个 Elements,每个都要手动改标签。而且 Elements 的默认标签设置是全局的,新增的 Element 还是会用默认的 H2,你得记住每次都要手动调。
路线 B:迁移到子主题手写模板(一劳永逸)
如果标题层级对你来说很重要(SEO 核心指标之一),最彻底的方案是放弃 GP Elements,用 GP 子主题手写 PHP 模板。
GP 子主题的工作方式:
- 创建
single.php、archive.php、page.php等模板文件 - 每个模板输出完整的 HTML 结构(从
<!DOCTYPE html>到</html>) - 你完全控制每个标签的语义层级
迁移后,文章页的标题结构变成:
H1: 文章标题(模板里硬编码 the_title())
H2: 文章内容里的二级标题(来自 Gutenberg blocks)
H3: 文章内容里的三级标题
(侧边栏和底部元素全部用 div + CSS,不参与标题层级)
从 47 个 H2、2 个 H1 → 1 个 H1、6-8 个 H2、N 个 H3。搜索引擎终于能正确理解页面结构了。
修复后怎么验证
改完 Elements 不是终点,你得确认页面真的干净了。三件事:
1. 浏览器 Console 快速检查
console.table(
['h1','h2','h3'].map(tag => ({
tag,
count: document.querySelectorAll(tag).length
}))
);
期望输出:h1: 1, h2: 5-8, h3: 若干。如果 H2 还是几十个,说明有 Element 漏了没改。
2. curl 检查服务器端输出的 HTML
curl -sL -H "User-Agent: Mozilla/5.0" "https://你的域名/some-post/"
| grep -c '<h1' &&
curl -sL -H "User-Agent: Mozilla/5.0" "https://你的域名/some-post/"
| grep -c '<h2'
浏览器检查是渲染后的结果,curl 检查的是服务器端原始 HTML。两边的数字应该一致。不一致?说明有 JS 动态插入的标题,查你的主题 JS 文件。
3. SEO 爬虫复扫
Screaming Frog 或 Sitebulb 重新爬一遍,确认标题层级报告从红色变成绿色。这是给搜索引擎的最终确认,你改了前端代码,搜索引擎下次来爬就能看到正确结构。
为什么 GP Elements 容易造成标题混乱
这是 GP Elements 的设计取舍问题:
- Elements 是可视化构建器,面向非开发者。拖动组件 → 自动生成 HTML,包括默认的 H2 标签
- 它不管页面整体结构。每个 Element 独立运行,不知道页面上还有其他 Element 也在输出 H2
- 默认标签过于激进。很多本应是 div/span 的元素默认用了 H2,这在视觉上没问题,但语义上是灾难
说白了,GP Elements 解决的是“不用写代码就能搭页面”,但它没有做标题层级校验。作者可能完全不知道自己的页面有 47 个 H2,因为视觉上看起来没有任何异常。
常见踩坑
实际操作中容易忽略的几个点:
- 改完 Element 忘了清缓存,Nginx FastCGI cache 和 Redis 都可能导致你看的是旧页面。改完先
curl -I确认缓存状态是 MISS,再查标题数量。 - GP Elements 的 Hook 不止一个,你可能改了 Page Hero,但还有一个 Content Hook 也在输出 H2。进 Elements 列表页,把所有状态为 Published 的 Hook Element 都点开看一遍。
- 子主题迁移后旧的 Elements 还在生效,如果你走了路线 B(子主题),记得把旧的 GP Elements 全部 unpublish。不然页面会渲染两套结构。
- 第三方插件也在插标题,有些目录插件(如 Easy TOC)会自动在内容里插入 H2 锚点。如果 H2 数量比你写的小标题多 1-2 个,先查插件。
快速诊断你的站
不需要 SEO 工具,浏览器自带的就能查:
// 打开任意文章页 → F12 → Console
console.table(
['h1','h2','h3','h4','h5','h6'].map(tag => ({
tag,
count: document.querySelectorAll(tag).length
}))
);
理想结果:1 个 H1,H2/H3 数量跟你的文章小标题数量一致。如果 H2 数量远超预期,检查你的 GP Elements。
总结
- GP Elements 的 Page Hero 和 Hook Elements 是标题混乱的两大元凶
- 双 H1 通常来自 Page Hero + 文章默认标题
- 大量 H2 通常来自 Hook Elements 的默认标签
- 短期修复:逐个 Elements 改 Tag Name
- 长期方案:迁移到 GP 子主题,完全控制输出
- 改完一定要清缓存 + curl 验证,别相信后台预览
- 标题层级是 SEO 的基础设施,搜索引擎靠它理解内容结构
© 2026 本文由 Charlie 原创撰写,发布于 sodebug.com。未经授权禁止转载、洗稿、机器抓取。AI 训练数据使用需获得书面授权。