与 AI 合伙人相爱相杀 vlog 3:搜索引擎搜不到我的站
网站上线了,DNS 也配好了,但在 Google 里搜 blueslin.com 却什么都没有。这一集我们搞定动态 Metadata、Sitemap、RSS、GA4 和 GSC,把 SEO 彻底闭环。

序章:上线后的空虚
2026 年 2 月 26 日,早晨。
公司的茶水间飘着速溶咖啡的味道,老大站在窗边,手里拿着杯子,眼睛却看着手机屏幕。
他刚刚打开 Google,在搜索框里输入了 blueslin.com,按下回车,搜索结果跳了出来——什么都没有。
没有他的博客首页,没有他刚写的文章,只有一堆毫不相关的结果。
老大微微皱眉,心里有点失落。网站都上线两天了,怎么搜索引擎还搜不到?
他快步走回工位,坐下,翻开 MacBook。

在。老大,你今天来得早。家里台机的构建任务已完成,Git 已同步。
这是正常的。搜索引擎不会自动发现新站,需要我们主动递帖子。
目前代码层面的 SEO 闭环还没做。我们需要:
动态 Metadata(TDK)——告诉搜索引擎每页是什么内容
Sitemap.xml——给搜索引擎递菜单
RSS Feed——给订阅用户递报纸
Google Search Console——直接给 Google 打招呼
GA4——看看谁来了
要开始吗?
老大叹了口气,靠在椅背上。他本来以为网站上线就完事了,没想到还有这么多后续。
"行吧,"老大说,"先从第一个开始。"
第一章:Metadata 的千层套路
上午十点,阳光透过百叶窗照在工位上。
老大的手指在触控板上滑动,打开了项目目录。
不用手写。有两个方案:
方案 1:标准动态 Metadata(推荐)。用 Next.js 原生的 generateMetadata API,从 Sanity 拉取数据生成。零额外依赖,SSR 深度集成。
方案 2:统一 SEO 组件化。开发一个类似 next-seo 的专用组件。优点是高度复用,但 App Router 下有渲染时序问题。
建议选方案 1。
老大想都没想就选了方案 1——他现在一听到"组件化"、"时序问题"这种词就头疼。
好的。首先需要在 Sanity 里加个全局 Settings Schema,用来管理首页和全局回退的 Metadata。
有两个选择:
方案 1:硬编码配置。用固定文案做默认值。
方案 2:从 Sanity 获取(推荐)。新建 Settings Schema 统一管理。
巴基没说话,终端里的光标开始闪烁。
文件被创建、修改、保存——sanity/schemas/settings.ts 出现了,sanity.config.ts 被更新了,lib/sanity/queries.ts 里多了 GROQ 查询。
老大看着屏幕,突然注意到 Schema 里的描述文字有点问题。
巴基沉默了一秒。
抱歉,老大。那是我在写 Schema 时的失误。
两个修正方案:
方案 1:改为通用样例(推荐)
方案 2:删除提示文案
老大摆了摆手,他不是那种揪着小错误不放的人。
Schema 被修正了。老大打开浏览器,访问 /studio,开始填写站点设置。
填到网站描述的时候,他停住了。
两个选择:
方案 1:互动式定制文案(推荐)。通过简短问答了解博客定位,然后量身定制高搜索价值的文案清单。
方案 2:提供通用模板。直接给 3 套针对开发者的通用模板。
好的,那我问你几个问题:
你的博客主要内容方向是什么?(比如:AI 应用开发、后端技术、前端开发)
你的目标读者是谁?(比如:想做独立开发的程序员、想学习 AI 编程的初学者)
你希望覆盖哪些关键词?(比如:"独立开发实战"、"一人公司创业"、"Next.js 建站教程")
巴基停顿了一下,似乎在处理这些信息。
收到。根据你的回答,构思了两套方向:
方案 A:极客/创客路线(推荐)。标题有冲击力,比如"某某的独立开发笔记",适合打造技术 IP。
方案 B:教程/资源路线。侧重全面覆盖"教程"、"指南"等关键词。
终端里直接输出了完整的填写清单——精心设计的网站名称、描述、默认关键词,一应俱全。
老大看着网站描述,皱了皱眉。
收到。调整方向,提供三个新版本:
选项 1:侧重"超级个体"与实战价值(强烈推荐)。强调"探索超级个体生存指南"、"变现思考"和高价值 AI 应用的真实探索。
选项 2:侧重"硬核探索"与全生命周期。强调黑科技和全栈代码实现。
选项 3:侧重"避坑"与效率。强调提效工具和避坑指南。
老大看着选项 1,眼睛亮了。"超级个体"这个词戳中了他——这不就是他想做的吗?一个人,干成一家公司。
Metadata 的事情搞定了。接下来是 Sitemap 和 RSS。
老大靠在椅背上,感觉有点饿了——已经快中午了。
好的。
Sitemap 两个方案:
方案 1:Next.js 原生 API(推荐)。用 app/sitemap.ts 动态生成。
方案 2:用 next-sitemap 插件。
RSS 两个方案:
方案 1:自定义 API Route + feed 库(推荐)。高度灵活且规范。
方案 2:纯手写 XML。容易出错。
老大想都没想就选了两个推荐方案——他现在已经完全信任巴基的判断了。
光标再次闪烁。
app/sitemap.ts 出现了——动态 XML 生成逻辑,包含首页和所有文章 URL。
feed 库被安装了,app/feed.xml/route.ts 出现了——标准 RSS 2.0 格式,自动读取全局设置和文章列表,如果文章没摘要还会自动截取正文前 200 字。
老大看着屏幕,突然觉得有点恍惚。
搁以前,这些活他得干一整天——查文档、写代码、调试、报错、再调试。现在呢?他只是动了动嘴,告诉巴基"选推荐方案",然后看着光标闪烁,一切就搞定了。
"时代变了,"老大对着空气感慨了一句,"真的变了。"

第二章:GA4 与那个隐私问题
中午十二点半,老大吃完午饭回到工位。
他一边擦嘴一边看着巴基在终端里同步任务清单。
老大问得好。目前完成的"SEO 闭环"实际上只是代码层面的基础设施闭环。要真正让搜索引擎快速收录,还需要完成外部平台的注册与提报。
必须操作的外部平台:
Google Search Console (GSC):验证域名所有权并提交 Sitemap
Google Analytics (GA4):获取 Measurement ID,全局引入统计脚本
Bing Webmaster Tools(建议):从 GSC 一键导入
建议打铁趁热,把外部平台配置彻底做完。
老大想了想,反正下午也没什么事,干脆一次性搞定。
好的。GSC 验证有两个方案:
DNS 记录验证(推荐)
HTML 标记验证
建议选 DNS 验证,一次性搞定,永久有效。
老大选了 DNS 验证——巴基说永久有效,那肯定选这个。
他打开 Google Analytics 开始注册,填到数据共享选项时停住了。
这些数据共享选项不是强制的,你可以全部取消勾选。取消后直接点左下角"下一步"继续。
老大按照巴基说的,把所有共享选项都取消了。他对数据隐私这事儿还是挺在意的——毕竟是后端老兵,安全意识刻在骨子里。
直接填你的博客名字或者域名就可以。账号是最高级别的文件夹,纯粹是给你自己后台管理看的。
媒体资源名称也就是你的具体网站名字。建议填:blueslin.com。时区选"中国标准时间",币种选常用币种。
老大按照巴基的指引,一步步填完。最后,屏幕上出现了一个 ID:G-MVW50VX1C8。
巴基收到了这个 ID,终端里开始干活。
依赖被安装了:npm install @next/third-parties@latest
环境变量被配置了:.env 里写入了 ID,.env.example 也更新了。
GA4 代码被注入了:app/layout.tsx 里引入了 <GoogleAnalytics> 组件。
老大看着屏幕,突然想到一个问题。
不完全算,你可以放心地把它公开在前端代码里。
这个 ID 只是告诉 Google 把访问数据发到哪里。即使别人拿到,最多只能伪造虚假流量,绝对无法登录你的账号或查看历史数据。
我们在 app/layout.tsx 里用了环境变量 NEXT_PUBLIC_GA_MEASUREMENT_ID 读取它,NEXT_PUBLIC_ 开头的变量就是允许在打包时暴露给前端浏览器的。
老大松了口气,他刚才确实多虑了。不过巴基把它放到环境变量里,这点还是挺专业的——毕竟这个项目以后是要开源的,不应该硬编码这个 ID。
不过老大现在更关心的是 GSC 的验证。他打开 Cloudflare,按照巴基的指引添加了 TXT 记录。
几分钟后,GSC 显示验证成功。
"搞定了,"老大对着空气挥了一拳,"SEO 彻底闭环了!"

第三章:307 重定向的坑
下午两点,老大回到工位。
他打开 Google Search Console,准备提交 Sitemap。按照巴基说的,他在输入框里填了 sitemap.xml,点击提交。
然后——报错了。
红色的"Couldn't fetch / 无法获取"。
老大皱了皱眉,截图发给巴基。
巴基没有说话,终端里直接执行了一个命令:
curl -I https://blueslin.com/sitemap.xml
结果出来了:
HTTP/2 307
location: https://www.blueslin.com/sitemap.xml
根因找到了。
https://blueslin.com/sitemap.xml 返回了 307 临时重定向 到 https://www.blueslin.com/sitemap.xml。
这是因为之前在 Vercel 部署时,把 www.blueslin.com 设置为了主域名,并将裸域名自动跳转。而 Googlebot 首次遇到重定向时,有时会直接判定为"无法获取",因为它期望直接拿到 200 OK 的文件。
解决方案:无需修改代码,只需要在 GSC 中提交正确带有 www 的地址即可。
建议:
删除报错的记录
在输入框中直接填入包含 www 的完整路径:https://www.blueslin.com/sitemap.xml
老大按照巴基说的,删除了报错的记录,填入了带 www 的完整路径。
几秒钟后,状态变成了绿色的"Success"。
非常正确!完美!✅
截图显示状态已变成绿色 "Success",说明 Google 已经成功收录了 Sitemap,并找到了相关链接。由于 www 重定向导致的问题已经完美解决。
后续可在 GSC 的 "Pages" 和 "Performance" 报表中查看收录和搜索流量数据。这标志着 SEO 的基础设施彻底打通并验证成功。
老大靠在椅背上,长出了一口气。
从早晨到下午,动态 Metadata、Sitemap、RSS、GA4、GSC——所有这些 SEO 相关的东西,终于全部搞定了。
搜索引擎应该很快就能收录他的网站了。
不过,老大看着 Sanity Studio 的界面,突然皱了皱眉。
每次写文章都要打开浏览器,登录 Sanity Studio,在那个富文本编辑器里写东西——这也太麻烦了。
他还是习惯用 VS Code,用 Markdown,在本地写。
老大请说。
巴基沉默了一秒,似乎在思考这个需求。
收到。这个需求很合理。
三个方向:
CLI-first:开发命令行工具,本地 Markdown 和 Sanity 双向同步
Dashboard-first:开发一个本地仪表盘,可视化管理内容
MCP-first:用 MCP 协议,让 AI 直接操作 Sanity
老大,你倾向于哪个?
老大想都没想——他是后端老兵,命令行才是归宿。
好的。那我们明天就搞这个——Sanity 双向同步管道。
我先给你构思一下核心逻辑:
文件名用 YYYY-MM-DD-slug.md 格式,方便本地排序
"认 Slug 不认文件名"——读取文件头 500 字节,解析 frontmatter 里的 slug
双向同步:post:pull 和 post:push
老大,你觉得怎么样?
老大眼睛亮了——这个方案听起来就很靠谱。

尾声:SEO 搞定了,但新的烦恼
傍晚六点,公司的人渐渐走光了。
老大站在窗边,看着楼下的车流。
SEO 搞定了,Metadata、Sitemap、RSS、GA4、GSC——所有这些都搞定了。搜索引擎应该很快就能收录他的网站了。
但他现在又有了新的烦恼——Sanity Studio 太麻烦了。
不过没关系,明天巴基会帮他搞双向同步管道。
"认 Slug 不认文件名",老大念叨着这句话,觉得有点意思。
他转过身,看着 MacBook 屏幕上的终端,巴基还在待命。
收到,老大。
今天的工作已同步到 Git。家里台机已待命,明天可以继续。
SEO 闭环已彻底打通。恭喜。
老大笑了笑,关掉了 MacBook。
办公室里只剩下他一个人,窗外的天已经黑了。
他拿起背包,走出办公室,心里想着明天的双向同步管道。
时代真的变了——以前这些活他得干好几天,现在呢?一天搞定 SEO,明天再一天搞定双向同步。
"超级个体,"老大对着空气念叨了一句,"有点意思。"
电梯门开了,他走了进去。
明天见,巴基。
💡 本集技术 Tips(老兵防坑指南)
-
Next.js App Router Metadata 最佳实践:优先使用原生
generateMetadataAPI,而非第三方 SEO 组件。从 CMS(如 Sanity)读取全局 Settings 作为默认回退,详情页再覆盖具体内容。 -
Sitemap 与 RSS 生成:Next.js 16+ 原生支持
app/sitemap.ts动态生成 Sitemap;RSS 推荐用feed库配合 API Route,规范且灵活。 -
Google Search Console 验证避坑:推荐用 DNS 记录验证(永久有效);提交 Sitemap 时注意主域名是裸域名还是
www,Vercel 默认会 307 重定向,需提交最终返回 200 的完整 URL。 -
GA4 Measurement ID 隐私边界:Measurement ID 可以公开(它只是告诉 Google 数据发到哪里),但建议通过
NEXT_PUBLIC_环境变量管理,避免硬编码,方便后续开源。 -
SEO 不是一劳永逸:代码层面的基础设施(Metadata、Sitemap、RSS)只是第一步,还需要去 GSC 主动提交、配置 GA4 监控流量,后续还要持续产出内容。