修复自家网站的 SEO 经验教训
我们花了几天时间,像搜索引擎一样阅读自己的网站,找到了六个值得修复的问题。每个页面都声明了两个 FAQ 区块,Google 把一个装饰性的背景光晕当成了我们的缩略图,一组模板页面在为它们没有回答的搜索词排名,而网站的一个新板块在预发布环境中被我们自己的边缘服务拦截了。这些问题都不算戏剧性,但它们都在悄悄地损害我们的可见度。
网站概述
mythex.ai 是一个单页应用,我们在构建时对它进行预渲染:脚本遍历每一个路由,为其生成静态 HTML 文件,并注入页面的标题、描述和结构化数据(即告诉搜索引擎页面是什么的 JSON-LD 代码块,参见 什么是结构化数据)。下面的大多数问题都与这个预渲染步骤有关,因为爬虫真正读取的正是这份 HTML。
1. 每个页面都声称自己是 FAQ 页面
现象。 我们的 HTML 模板在结构化数据中带有一个全站通用的 FAQPage 区块,其 URL 指向 /faq。预渲染随后又在上面为每个页面添加了它自己的 FAQPage。因此网站上的每个页面都输出了两个,而我们的隐私政策还在告诉 Google 它就是 FAQ 页面。
为什么重要。 Google 期望每个页面最多只有一个 FAQPage。多出来的、指向别处的那个,会导致该页面的标记被打折扣,而不只是被忽略。
修复。 全站通用的区块已经删除。每个页面的 FAQ 标记现在都来自同一个地方,包括 /faq 本身,它会根据完整的问题列表生成标记。没有 FAQ 的页面现在不再声明任何 FAQ,这才是诚实的做法。另外,如果任何页面再次出现多于一个 FAQPage,预渲染会让构建失败。只存在于某人记忆中的规则迟早会被打破;由构建强制执行的规则则不会。
2. Google 为我们选错了图片
现象。 在搜索结果中,Mythex 的缩略图是我们首页主视觉背后那个柔和脉动的光晕,这是一张装饰性的背景图,而不是我们的分享卡片。
为什么会这样。 我们从未告诉 Google 哪张图片代表某个页面,于是它选了自己找到的那一张。
修复。 解决这个问题的两个方面:
- 明确页面自己的图片。 首页现在有一个
WebPage节点,其primaryImageOfPage指向分享卡片;每个预渲染页面的结构化数据都带有自己的图片(该页面的分享图,或默认图片)。 - 隐藏装饰性图片。 背景图片现在在
robots.txt中被禁止抓取,并以noindex, noimageindex响应头提供,因此不会出现在图片搜索和缩略图中。
3. 搜索引擎只知道我们的 Logo
我们的 Organization 标记只有名称、Logo 和一些社交链接,只是品牌信息,没有其他内容。搜索引擎会根据登记注册类的事实来构建公司的知识面板,因此我们补充了营业执照上的信息:法定名称、成立日期、创始人和注册地址。我们有意没有填写电话号码。
4. 模板页面回答了错误的问题
现象。 Search Console 显示,有三个模板页面获得了展示但没有点击。其中一个在「content strategist portfolio」及其变体上排名,一个在「best italian restaurant website design」上排名,还有一个在与「agile board」相关的一组词上排名——其中大约一半的搜索词包含「free」这个词。排名在 20 多名到 50 多名之间。
原因。 每个页面回答的都不是用户提出的问题。想看优秀意式餐厅设计长什么样的人,却落在了一个向他们推销建站工具的页面上。
修复。 这三个页面现在各自增加了一个为搜索需求而写、而非为产品而写的章节,标题和描述使用人们实际输入的词语,并提供了值得他们已经输出的标记的 FAQ。
同一次提交还修复了一个更隐蔽的问题。「相关模板」区块取的是某个分类中的前四个模板,因此每个 portfolio 模板都指向同样的四个 portfolio,而该分类的其余模板则完全没有内部链接。我们把它替换为一个按子分类排序的环形结构:每个模板页面现在恰好有四个入链和四个出链。预渲染的 HTML 现在也会输出这些链接——之前它们只在 JavaScript 运行之后才存在,而爬虫可能永远不会运行 JavaScript。
5. 新页面上线时立即通知 Bing
Google 不理会 IndexNow,这是一个在 URL 变化时通知搜索引擎的协议。Bing、Yandex 和 Seznam 使用它,而 Bing 的索引正是 ChatGPT 搜索所读取的内容。一个 AI 应用构建器如果无法被 AI 助手找到,就是一种特别的失败。
显而易见的做法是在每次部署时提交整个 sitemap,但这正是密钥被限流的原因,而且大多数部署并不会改变搜索引擎关心的任何内容。因此,我们编写了一个脚本,它会比较网站当前提供的 sitemap 与刚构建出来的 sitemap,并只提交两者之间的差异。
让它奏效的有两个细节:
- 部署前先快照。 基线必须在新构建上线之前捕获。之后,「线上」的 sitemap 已经是新的,每次比较得到的差异都是空的。
- 目前只提交新页面。 我们的 sitemap 没有
lastmod日期,因此脚本只通知新页面,而不通知内容更新。如果为每个 URL 都打上构建日期的时间戳,每次部署都会把整个网站标记为已变更——这正是我们想避免的垃圾信息。
它只在生产部署时运行,并且从不导致构建失败:运行它时,网站已经上线,而搜索引擎的一次 ping 不值得让部署变红。
6. 我们自己的边缘服务说「未找到」
在推出 /ai 页面时(更多内容参见 为每一种业务准备的落地页),预发布环境对所有这些页面都显示「Not found」,而静态托管服务却能正常提供它们。
营销域名前面的服务只转发允许列表中的路径,其他路径一律返回硬性的 404。/ai 是新增的,还没有出现在列表中。我们添加了 /ai 和 /ai/*,并编写了一个测试来断言它们可以通过。这是个小 bug,但正是那种会让一个新板块对爬虫不可见、却没人注意到的问题。
我们的收获
- 阅读爬虫读取的 HTML。 其中大部分问题在浏览器里是看不见的,但在预渲染的文件中一目了然。
- 把 SEO 规则变成构建检查。 「每个页面只能有一个 FAQPage」现在是强制执行的,而不是靠记忆。
- 明确告诉搜索引擎你的意思。 如果你不说明哪张图片或哪些事实代表你,它们就会自己去猜。
- Search Console 会告诉你人们问的是哪个问题。 有展示没有点击,通常意味着页面回答的是另一个问题。
- 提交差异,而不是全部内容。 只 ping 发生变化的部分,可以让你保持在速率限制之内。
如果你要为自己构建的网站做同样的事,我们关于 AI 构建网站的 SEO 和 设置 Google Search Console 的指南涵盖了基础知识。