搜索结果出现旧部署 URL 而不是自定义域名

Google 在搜索里显示 your-app.vercel.app 或 your-site.web.app,而不是你的自定义域名。原因,以及重定向 + canonical 的精确修法。

你在 Google 搜自己的品牌内容,结果显示的是 your-app.vercel.appyour-site.web.app,而不是 yourdomain.com。点进去是同一个页面。平台域名在你绑定自定义域名之前就被收录了,而 Google 不会自己迁移过去。

最快的修法(截至 2026 年 6 月): 让平台 URL 301 重定向到你的自定义域名,让两者不再互相竞争。在 Vercel 上只需一个设置:Project Settings -> Domains -> 编辑那个 *.vercel.app 域名 -> 把 Redirect to 设成你的自定义域名。再在每个页面吐一个指向自定义域名的 <link rel="canonical"> 兜底,然后回到 Search Console 重新检查一个示例 URL。自定义域名永远不会”自动获胜”——Google 需要一个明确信号(301、canonical 或 noindex)才会放弃旧域名。

为什么会这样(你属于哪一种)

自定义域名和平台域名提供的是逐字节相同的页面。对 Google 来说这就是同一篇文档对应两个 URL,所以它会挑一个 “Google-selected canonical”。如果平台 URL 起步早(有外链、有抓取历史、路径更短),Google 往往就保留它。按”真正原因”的命中率从高到低排:

#原因一行检查命中的结果
1先在平台 URL 上线,后绑自定义域名Google 搜 site:your-app.vercel.app出现已收录页面
2没有 canonical,或 canonical 指向平台 URLcurl -s https://your-app.vercel.app/article | grep canonicalcanonical href 里含 vercel.app
3平台 URL 没做重定向curl -sI https://your-app.vercel.app/第一行是 200,不是 301
4非生产的自定义域名泄漏(预览分支)curl -sI https://staging-branch-domain/ | grep -i robots没有 X-Robots-Tag: noindex
5Firebase web.app / firebaseapp.com 关不掉Google 搜 site:web.app yoursite有结果
6外链还指向平台 URLAhrefs / Search Console “Links” 报告大量引用页指向平台域名

有个细节常让人意外:Vercel 已经会自动给预览和生成的部署 URL 加上 X-Robots-Tag: noindex(也就是 *-git-branch-*.vercel.app 和那些哈希 URL),截至 2026 年 6 月如此。没有被自动保护的,是你那个稳定的生产别名 your-project.vercel.app,以及你绑到非生产分支上的任何自定义域名。所以如果索引里有 vercel.app URL,几乎都是原因 #1 里的生产别名——而不是某个漏网的预览。

最短修复路径

第 1 步:每个页面都吐指向自定义域名的 canonical

每页 <head> 都要有指向自定义域名的 canonical,哪怕请求是从平台域名进来的:

<link rel="canonical" href="https://yourdomain.com/article-path/" />

在 Astro 里从 site 来构造,这样不管请求由哪个别名服务,host 永远是你的域名:

---
// layout 里
const canonicalUrl = new URL(Astro.url.pathname, 'https://yourdomain.com').toString();
---
<link rel="canonical" href={canonicalUrl} />

canonical 是一个提示,不是命令——Google 可以推翻它(你会在 URL Inspection 里看到 “Google-selected canonical” 和你声明的不一致)。这正是第 2 步重要的原因:301 是指令,不是提示。

第 2 步:把平台 URL 重定向到自定义域名(真正的修法)

Vercel。 绑定自定义域名并不会移除或重定向 vercel.app 别名;两个都继续返回 200。在后台修:Project Settings -> Domains,在那个 *.vercel.app 域名上点 Edit,用 Redirect to 下拉框把它指向你的自定义域名(Vercel 会发 308 永久重定向,Google 当成 301 处理)。这就是 Vercel 官方推荐的、用来避免两个域名争抢重复内容的做法。

如果你更想放在代码里,vercel.json 里一条按 host 匹配的规则效果一样:

{
  "redirects": [
    {
      "source": "/:path*",
      "has": [{ "type": "host", "value": "your-app.vercel.app" }],
      "destination": "https://yourdomain.com/:path*",
      "permanent": true
    }
  ]
}

保持 site 设好,canonical 和 sitemap 的 URL 才会正确:

// astro.config.mjs
export default defineConfig({
  site: 'https://yourdomain.com',
});

Netlify。Domain management 里把自定义域名设为 primary;Netlify 会自动把 *.netlify.app 子域名 301 到它。用 curl -sI 确认。

Firebase Hosting。 这个最麻烦。Firebase 设计上同时服务 *.web.app*.firebaseapp.com,而 firebase.json 里的 headers 块会作用于所有绑定的域名——配置里没有 host 匹配,所以你没法只从 firebase.jsonweb.appnoindex。两个真正可行的办法:

  • 运行时判断,只在请求 host 是 Firebase 默认域名时吐 noindex
{(Astro.url.hostname.endsWith('.web.app') || Astro.url.hostname.endsWith('.firebaseapp.com')) && (
  <meta name="robots" content="noindex" />
)}
  • 或者用 Cloud Function / rewrite 在默认 host 前面挡一层重定向,让 web.app 的请求 301 到你的域名。

无论哪种,在 Firebase 上真正出力的还是你的 canonical 标签(第 1 步)。

第 3 步:确认预览已经被 noindex(别过度折腾)

在 Vercel 上,预览和旧的生产部署 URL 已经自动带 X-Robots-Tag: noindex(2026 年 6 月),所以手动加规则通常是多余的。唯一的缺口是绑到非生产分支上的自定义域名——Vercel 不会给它加 noindex。如果你有个跑在预览分支上的 staging.yourdomain.com,自己加上这个 header,并按环境收口,确保生产环境永远不被碰到:

// vercel.json —— 只针对非生产别名
{
  "headers": [
    {
      "source": "/(.*)",
      "has": [{ "type": "host", "value": "staging.yourdomain.com" }],
      "headers": [{ "key": "X-Robots-Tag", "value": "noindex" }]
    }
  ]
}

curl -sI https://staging.yourdomain.com/ | grep -i robots 验证。

第 4 步:重新检查,别批量提交

在 Search Console 里,对几个你的自定义域名 URL 跑 URL Inspection,看 Google-selected canonical 这一栏。如果它现在显示 yourdomain.com,说明合并在生效,你基本只要等就行。如果还显示平台域名,说明你的 301 / canonical 还没传到 Google——用 curl 回头复查第 2 步。

你可以对自定义域名 URL 点 Request Indexing,但每个 property 每天大约只能提交 10-12 个 URL(Google 不公布确切数字,而且因站而异,截至 2026 年 6 月),所以把它花在最重要的页面上,其余的让它们靠 301 自己重新合并。不要把平台 URL 加成独立 property 再对提交索引——那会告诉 Google 继续当成独立站追踪。

第 5 步:删掉平台 URL 的旧 GSC property(如果你建过)

如果你在上线时把 https://your-app.vercel.app/ 验证成了 Search Console property,把它从 property 列表里删掉。需要的话先导出数据;目的是不再把它当成独立站去喂养。

第 6 步:等待合并

301 和 canonical 上线后,Google 会在重新抓取时逐步丢弃平台 URL。site:your-app.vercel.app 的计数通常在 2-8 周内下降;头部页面最先动,因为它们被抓得最勤。

如何确认修好了

  1. curl -sI https://your-app.vercel.app/ 返回 301308,且 location: 是你的域名。
  2. curl -s https://your-app.vercel.app/article | grep canonical 显示 canonical 指向 yourdomain.com
  3. Search Console URL Inspection 里,某个自定义域名 URL 的 Google-selected canonical 显示 yourdomain.com
  4. 接下来几周内,site:your-app.vercel.app 的结果变少,品牌词 SERP 开始显示你的域名。

容易误判的情况

很多人以为加上自定义域名的那一刻它就接管了。并没有——两个域名都还活着,Google 会继续用它已经信任的那个。解药永远是一个明确信号:从平台域名发 301、指向自定义域名的 canonical、或平台域名上的 noindex。光绑域名什么都不会变。

哪些情况不怪你

Firebase 让你没法彻底退役 web.app / firebaseapp.com——它们是承重的默认域名。按 host 加 noindex 的 workaround 是现有最干净的办法,但它只是个 meta 标签信号,不是硬 301,所以合并可能比 Vercel 或 Netlify 慢——后两者你能直接控制重定向。

预防建议

  • 任何项目第一天:把自定义域名设为 primary,并在发布或分享链接之前就把平台域名重定向过去。
  • 每个模板里都从你的域名构造 canonical 标签,不管请求由哪个 host 服务。
  • 绝不要在 Search Console 把平台 URL 验证成独立 property。
  • 对任何非生产的自定义域名(staging / preview),自己加上 X-Robots-Tag: noindex——Vercel 只自动保护默认的预览域名。
  • 每季度审一次 site:platform-url,尽早发现新收录的页面。

常见问题

  • 能彻底禁用平台 URL 吗? 看平台。Vercel 和 Netlify 允许你把平台子域名 301 到自定义域名,对用户和爬虫来说就等于退役了。Firebase 的 web.appfirebaseapp.com 设计上保持可访问——你只能 noindex 它们,删不掉。
  • Google 会自己搞清楚吗? 最终会,但不可靠。没有 301 或 canonical,平台 URL 可能滞留好几个月。明确信号能把这缩短到几周。
  • 我的 canonical 指向对的域名,但 Google 还是显示平台 URL,为什么? canonical 是 Google 可以推翻的提示,通常是因为平台 URL 外链或抓取历史更多。加上 301(第 2 步);重定向是指令,不是建议。
  • 301 会伤排名或丢链接权重吗? 不会。永久重定向会把排名信号传给目标域名,这正是你要的——它把平台 URL 的权威合并到你的域名上。
  • 旧 URL 多久会从搜索里消失? 一般是 301 和 canonical 上线后 2-8 周,抓取频繁的头部页面最快。你可以用 Request Indexing 推一把头部页面,但大头还是靠重定向自己完成。

相关阅读

标签: #域名 #DNS #SSL #排查 #部署 URL