Old Deployment URL Appears in Search Instead of Custom Domain

Google shows your-app.vercel.app or your-site.web.app in search instead of your custom domain. Why it happens and the exact redirect + canonical fix.

You search Google for your branded content and the result shows your-app.vercel.app or your-site.web.app instead of yourdomain.com. Click through and it’s the same page. The platform hostname got indexed before you attached a custom domain, and Google never migrated on its own.

Fastest fix (as of June 2026): make the platform URL 301-redirect to your custom domain so the two stop competing. On Vercel that’s one setting: Project Settings -> Domains -> Edit the *.vercel.app domain -> set Redirect to your custom domain. Emit a <link rel="canonical"> to the custom domain on every page as a backstop, then re-inspect a sample URL in Search Console. A custom domain never “wins” automatically — Google needs an explicit signal (301, canonical, or noindex) to drop the old host.

Why this happens (and which bucket you’re in)

A custom domain and the platform hostname serve byte-identical pages. To Google that’s two URLs for one document, so it picks one “Google-selected canonical.” If the platform URL had a head start (links, crawl history, a shorter path), Google often keeps it. Ordered by how often each cause is the real one:

#CauseOne-line checkResult that confirms it
1Launched on the platform URL, added the domain latersite:your-app.vercel.app in GoogleIndexed pages show up
2No canonical, or canonical points at the platform URLcurl -s https://your-app.vercel.app/article | grep canonicalCanonical href contains vercel.app
3Platform URL not redirectedcurl -sI https://your-app.vercel.app/First line is 200, not 301
4A non-production custom domain leaks (preview branch)curl -sI https://staging-branch-domain/ | grep -i robotsNo X-Robots-Tag: noindex
5Firebase web.app / firebaseapp.com can’t be turned offsite:web.app yoursiteResults appear
6External backlinks still point at the platform URLAhrefs / Search Console “Links” reportMany referring pages cite the platform host

One detail that surprises people: Vercel already sets X-Robots-Tag: noindex automatically on preview and generated deployment URLs (the *-git-branch-*.vercel.app and hash URLs), as of June 2026. What is not auto-protected is your stable production alias your-project.vercel.app, and any custom domain you attach to a non-production branch. So if a vercel.app URL is in the index, it’s almost always the production alias from cause #1 — not a stray preview.

Shortest path to fix

Step 1 — Emit a canonical to the custom domain on every page

Every page’s <head> needs the canonical pointing at the custom domain, even when the request arrived on the platform host:

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

In Astro, build it from site so the host is always your domain regardless of which alias served the request:

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

Canonical is a hint, not a command — Google can override it (you’ll see this in URL Inspection as a “Google-selected canonical” that differs from yours). That’s why Step 2 matters: a 301 is an instruction, not a hint.

Step 2 — Redirect the platform URL to the custom domain (the real fix)

Vercel. Adding a custom domain does not remove or redirect the vercel.app alias; both keep serving 200. Fix it in the dashboard: Project Settings -> Domains, click Edit on the *.vercel.app domain, and use the Redirect to dropdown to point it at your custom domain (Vercel issues a 308 permanent redirect, which Google treats like a 301). This is Vercel’s own recommended way to avoid duplicate-content competition between the two hosts.

If you’d rather keep it in code, a host-matched rule in vercel.json does the same thing:

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

Keep site set so canonical and sitemap URLs stay correct:

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

Netlify. Set the custom domain as primary under Domain management; Netlify then 301-redirects the *.netlify.app subdomain to it automatically. Confirm with curl -sI.

Firebase Hosting. This is the awkward one. Firebase serves both *.web.app and *.firebaseapp.com by design, and a firebase.json headers block applies to all connected domains — there is no host-matching in the config, so you can’t noindex only the web.app host from firebase.json. Two options that actually work:

  • Decide at runtime and emit noindex only when the request host is a Firebase default domain:
{(Astro.url.hostname.endsWith('.web.app') || Astro.url.hostname.endsWith('.firebaseapp.com')) && (
  <meta name="robots" content="noindex" />
)}
  • Or front Firebase with a redirect on the default host via a Cloud Function / rewrite so web.app requests 301 to your domain.

Either way, your canonical tag (Step 1) is doing the heavy lifting on Firebase.

Step 3 — Confirm previews are already noindexed (don’t over-engineer this)

On Vercel, preview and old production deployment URLs already carry X-Robots-Tag: noindex automatically (June 2026), so a manual rule is usually redundant. The one gap is a custom domain attached to a non-production branch — Vercel does not noindex that. If you have a staging.yourdomain.com on a preview branch, add the header yourself, gated on environment so production is never touched:

// vercel.json — only for the non-production alias
{
  "headers": [
    {
      "source": "/(.*)",
      "has": [{ "type": "host", "value": "staging.yourdomain.com" }],
      "headers": [{ "key": "X-Robots-Tag", "value": "noindex" }]
    }
  ]
}

Verify with curl -sI https://staging.yourdomain.com/ | grep -i robots.

Step 4 — Re-inspect, don’t mass-request

In Search Console, run URL Inspection on a few of your custom-domain URLs and read the Google-selected canonical field. If it now reads yourdomain.com, consolidation is working and you mostly just wait. If it still reads the platform host, your 301/canonical isn’t reaching Google yet — recheck Step 2 with curl.

You can click Request Indexing on the custom-domain URLs, but it’s capped at roughly 10-12 URLs/day per property (Google doesn’t publish the exact number, and it varies by site, as of June 2026), so spend it on your most important pages and let the rest reconsolidate from the 301. Do not add the platform URL as its own property and request indexing on it — that tells Google to keep tracking it as a separate site.

Step 5 — Remove the platform URL’s old GSC property (if you made one)

If you verified https://your-app.vercel.app/ as a Search Console property at launch, remove it from the property list. Export any data you want first; the goal is to stop feeding it as an independent site.

Step 6 — Wait for consolidation

Once the 301 and canonical are live, Google drops the platform URL gradually as it re-crawls. site:your-app.vercel.app counts typically fall over 2-8 weeks; head pages move first because they’re crawled most often.

How to confirm it’s fixed

  1. curl -sI https://your-app.vercel.app/ returns 301 or 308 with a location: of your domain.
  2. curl -s https://your-app.vercel.app/article | grep canonical shows the canonical pointing at yourdomain.com.
  3. In Search Console URL Inspection, Google-selected canonical on a custom-domain URL reads yourdomain.com.
  4. Over the following weeks, site:your-app.vercel.app returns fewer results, and the branded SERP starts showing your domain.

Easy to misdiagnose as

People assume the custom domain takes over the moment it’s added. It doesn’t — both hosts stay live and Google keeps whichever it already trusts. The cure is always an explicit signal: a 301 from the platform host, a canonical to the custom domain, or noindex on the platform host. Adding the domain alone changes nothing.

When this is not on you

Firebase makes it impossible to fully retire web.app / firebaseapp.com — they’re load-bearing defaults. The noindex-by-host workaround is the cleanest option available, but it’s a meta-tag signal, not a hard 301, so consolidation can be slower than on Vercel or Netlify where you control the redirect directly.

Prevention

  • Day one of any project: set the custom domain as primary and redirect the platform host to it before you publish or share links.
  • Build the canonical tag from your domain in every template, regardless of which host served the request.
  • Never verify a platform URL in Search Console as a separate property.
  • For any non-production custom domain (staging/preview), add X-Robots-Tag: noindex yourself — Vercel only auto-protects the default preview hostnames.
  • Audit site:platform-url once a quarter to catch newly indexed pages early.

FAQ

  • Can I disable the platform URL entirely? Depends on the host. Vercel and Netlify let you 301 the platform subdomain to your custom domain, which effectively retires it for users and crawlers. Firebase’s web.app and firebaseapp.com stay accessible by design — you can only noindex them, not remove them.
  • Will Google figure it out on its own? Eventually, and unreliably. With no 301 or canonical, the platform URL can linger for months. Explicit signals cut that to weeks.
  • My canonical points at the right domain but Google still shows the platform URL — why? Canonical is a hint Google can override, usually because the platform URL has more links or crawl history. Add the 301 (Step 2); a redirect is an instruction, not a suggestion.
  • Does the 301 hurt my rankings or lose link equity? No. A permanent redirect passes ranking signals to the target, which is exactly what you want — it consolidates the platform URL’s authority onto your domain.
  • How long until the old URL disappears from search? Typically 2-8 weeks after the 301 and canonical go live, fastest for frequently crawled head pages. You can nudge top pages with Request Indexing, but the redirect does the bulk of the work on its own.

Tags: #Domain #DNS #SSL #Troubleshooting #Deploy URL