You migrated /blog/old-post/ to /blog/new-post/, updated the canonical tag on the new page to self-canonical, and waited. Three weeks later, Google search results still return the old URL. URL Inspection on the new URL shows: Indexed, though Google selected a different canonical than user — canonical: /blog/old-post/. You changed the tag. Why did nothing happen?
Because <link rel="canonical"> is a hint, not a directive. Google weighs it alongside roughly half a dozen other signals, and the canonical tag rarely wins on its own. The fix is not to “change the canonical harder” — it’s to align every other signal with it.
How to identify which case you’re in
Case 1: No 301 from old URL to new URL
How to spot it:
curl -sI "https://yourdomain.com/blog/old-post/" | head -1
# HTTP/2 200 <-- old URL still serving 200, no redirect
The old URL still resolves directly. Both old and new pages are live; both return 200; the only difference is the canonical tag on the new page.
Why it happens: most “URL change” workflows only update the canonical and leave the old route serving. Google sees two live pages with similar content; one already has accumulated indexing history, internal links, and backlinks; the other has only the canonical tag in its favor. Old wins.
Fix: add a 301 from old to new. This is roughly 10x stronger than a canonical hint as a consolidation signal. Google rarely ignores a 301.
// Vercel: next.config.js
module.exports = {
async redirects() {
return [{ source: "/blog/old-post", destination: "/blog/new-post", permanent: true }];
},
};
// Firebase Hosting: firebase.json
{
"hosting": {
"redirects": [
{ "source": "/blog/old-post", "destination": "/blog/new-post", "type": 301 }
]
}
}
After deploying, verify:
curl -sI "https://yourdomain.com/blog/old-post/" | head -1
# HTTP/2 301
Case 2: Internal links still point to the old URL
How to spot it: search your codebase.
rg -l '/blog/old-post' src/
# Returns the list of files still referencing the old URL
Sitemap, related-posts widget, breadcrumbs, in-article links, navigation — any of these still pointing at the old URL adds weight to “the old URL is the real one.”
Why it happens: URL migrations rarely catch every reference. CMS rich-text fields, hand-written markdown, generated taxonomies — links sneak through.
Fix: bulk-replace.
# Find every reference
rg -l '/blog/old-post' src/
# Replace (macOS sed)
rg -l '/blog/old-post' src/ | xargs sed -i '' 's|/blog/old-post|/blog/new-post|g'
# Verify
rg '/blog/old-post' src/
# (empty)
Then in Search Console → Links → Internal links, the new URL’s link count should rise within a crawl cycle.
Case 3: Sitemap still lists the old URL
How to spot it:
curl -s https://yourdomain.com/sitemap.xml | grep old-post
# Shows the old URL still in the sitemap
Sitemap is one of Google’s strongest “this is the URL the site owner intends to be indexed” signals. If sitemap says A and canonical says B, the sitemap entry biases Google toward A.
Why it happens: sitemap regeneration didn’t pick up the URL change because the migration was a one-off rename, not a re-deploy with a fresh sitemap.
Fix: regenerate the sitemap. The new URL should appear; the old URL should not. Then in Search Console → Sitemaps, resubmit.
Case 4: Old URL has external backlinks the new URL lacks
How to spot it: Search Console → Links → External links. Compare backlink count between the two URLs. If old has 50 referring domains and new has 3, Google heavily weights the old URL’s authority.
Why it happens: backlinks accumulate over years. A renamed URL starts at zero. Even with all internal signals pointing to the new URL, external links to the old URL keep its authority alive.
Fix: the 301 from old to new (Case 1) transfers most of that backlink equity. There is no faster way. For high-value backlinks (a few that matter most), you can email the linking sites to update.
Case 5: New URL is thinner than the old one
How to spot it: open both pages side by side. Count words. Compare H1, H2 structure. If the new page is a stub, or has different content than the old one, Google may treat them as different pages, not as a renamed version.
Why it happens: someone refactored the URL during a redesign and the new template stripped sidebar content, related links, footer info, etc.
Fix: this is the slowest case. Either bulk up the new page to match or exceed the old one’s content depth, or accept that the consolidation will take longer (8–12 weeks).
Case 6: You did everything right and Google is just slow
How to spot it: 301 is live, internal links migrated, sitemap clean, URL Inspection on the new URL shows “URL is on Google” — and yet site:yourdomain.com/blog/old-post still returns a result.
Why it happens: Google’s canonical consolidation is not instant. After all signals point to the new URL, the old URL stays in the index for weeks while Google waits for confirmation that the change is permanent.
Fix: wait 4–12 weeks. Use the Removals tool for a 6-month suppression if the old URL must be hidden urgently.
Shortest fix path
In hit-rate order:
- Add a 301 from old to new → 70% of cases. The single strongest signal.
- Update internal links sitewide → 20% of cases. The 301 fixes external authority; internal links fix internal authority.
- Regenerate and resubmit sitemap → 8% of cases. Resolves the “site owner says X but page tag says Y” conflict.
- Wait 4–12 weeks → the last 2%. If steps 1–3 are clean, time alone resolves the remainder.
Verification checklist
After applying the fix, check each item:
# 1. Old URL 301s
curl -sI "https://yourdomain.com/blog/old-post/" | head -1
# Expect: HTTP/2 301
# 2. New URL is 200 and self-canonical
curl -s "https://yourdomain.com/blog/new-post/" | grep canonical
# Expect: <link rel="canonical" href="https://yourdomain.com/blog/new-post/">
# 3. Sitemap lists new, not old
curl -s "https://yourdomain.com/sitemap.xml" | grep blog/old-post
# Expect: (empty)
curl -s "https://yourdomain.com/sitemap.xml" | grep blog/new-post
# Expect: <loc>https://yourdomain.com/blog/new-post/</loc>
# 4. No internal links to old URL
rg "/blog/old-post" src/
# Expect: (empty)
Then in Search Console → URL Inspection on the new URL → “Request indexing”.
Prevention
- URL changes are a four-step migration, never a one-step tag edit: (1) deploy new URL, (2) add 301 from old, (3) update internal links sitewide, (4) regenerate sitemap. Skip any step and the canonical change is wasted.
- Generate all URLs from one
urlFor(slug)helper so a rename only touches the slug map. - Avoid renaming high-traffic URLs for cosmetic reasons. The transition costs 4–12 weeks of degraded rankings.
- Track canonical/sitemap/internal-link consistency in CI: prebuild check fails if a sitemap URL has no matching internal link, or if a page’s canonical doesn’t match its sitemap entry.
FAQ
Q: Why not just delete the old URL with a 410? A: 410 (Gone) tells Google to drop the URL from the index, which loses the backlink value the old URL had accumulated. 301 transfers most of that value to the new URL. Use 301 unless the page is genuinely gone with no replacement.
Q: How long should I wait before assuming the canonical change failed? A: 4 weeks is the minimum for measurable change. 8 weeks is typical for a full transition. If after 12 weeks Google still shows the old URL with all signals (301, internal links, sitemap, content) pointing at the new one, something is wrong — usually a broken 301 chain or a CDN cache serving the old page intermittently.
Q: Can I speed up re-crawl? A: Use URL Inspection → “Request indexing” on both old and new URLs. That gets Google to fetch within hours. But re-evaluation of the canonical decision still takes weeks; you cannot force that timeline.
Q: I changed the canonical, didn’t add a 301. Will Google ever switch? A: Eventually, maybe — but rarely. Without a 301, both pages are live and Google has no strong reason to consolidate. If the new page accumulates more internal links over time, Google may flip. But the canonical tag alone is too weak. Add the 301.
Q: My new URL shows “Indexed, though Google selected a different canonical than user.” Is the page still indexed? A: Yes, the page is in Google’s index — but ranking signals (PageRank, backlinks, etc.) are being credited to the canonical Google chose, not the one you declared. Users searching usually land on the URL Google picked, not yours. See Duplicate, Google chose different canonical for the full diagnostic flow.
Related articles
- Canonical misconfigured: 3 failure modes
- Duplicate, Google chose different canonical than user
- Canonical still points to old domain after migration
- Alternate page with proper canonical tag
- Pagination canonical confusion
Tags: #SEO #Troubleshooting #Debug #Structured data #Canonical