Google indexed your pages on the wrong host, like test.example.com/slug instead of example.com/slug. This guide shows how to move them over with 301 redirects, verify the setup, and monitor the move until Google is done.
Don't want to touch DNS and server configs? We can do the move for you →
Decide where the pages should live: example.com or www.example.com. Check which one actually serves your site:
curl -sI https://example.com/ | head -1
curl -sI https://www.example.com/ | head -1200. Check the body too: curl -s https://www.example.com/ | wc -c. A 0 means a blank page Google could index.Always redirect straight to the final host. A chain like test → www → example.com works, but a single hop is cleaner.
Google Search Console has no single export of every indexed URL, so combine these sources:
test.example.com and export. This lists URLs that received impressions.site:test.example.com as a sanity check.Tip: a Domain property (example.com) in Search Console covers every subdomain, so you can inspect both the old and the new URLs in one place.
If you removed the subdomain from DNS, Google only gets DNS errors. It will drop the URLs eventually, but nothing is passed to your main domain and nothing can redirect. Recreate the DNS record and point it at something that does one job: send 301s. No app, no content.
A/AAAA record for test pointing to your web server or reverse proxy.The host needs a valid TLS certificate. The indexed URLs are usually https://, and a certificate error stops Google before it sees the redirect.
Map every path 1:1: test.example.com/slug → example.com/slug. Pick your stack:
AAAA record named test with content 100:: and proxy status Proxied.test.example.com.concat("https://example.com", http.request.uri.path)Cloudflare issues the certificate automatically.
server {
listen 80;
listen 443 ssl;
server_name test.example.com;
ssl_certificate /etc/letsencrypt/live/test.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/test.example.com/privkey.pem;
return 301 https://example.com$request_uri;
}$request_uri keeps the path and query string. Get the certificate with certbot before enabling the 443 listener.
test.example.com {
redir https://example.com{uri} permanent
}Caddy gets the certificate automatically. Behind an edge proxy that terminates TLS, use http://test.example.com as the site address in the inner Caddyfile. The redirect target stays https://.
Add test.example.com to your project's domains and set it to redirect to example.com, or use a host-based redirect in vercel.json:
{
"redirects": [
{
"source": "/:path*",
"has": [{ "type": "host", "value": "test.example.com" }],
"destination": "https://example.com/:path*",
"permanent": true
}
]
}"permanent": true sends a 308, which Google treats the same as a 301.
No live equivalent? Redirect a URL to the closest matching page, or let it return 410. Don't send everything to the homepage. Google treats mass homepage redirects as soft 404s.
Disallow stops Google from crawling the old URLs, so it never sees the redirects.Check a single URL:
curl -sI https://test.example.com/slug1You want exactly one response with status 301 (or 308) and location: https://example.com/slug1. To check every URL from Step 2, put them in old-urls.txt, one per line:
while read -r url; do
curl -s -o /dev/null -w "%{http_code} %{redirect_url} $url\n" "$url"
done < old-urls.txtEvery line should start with 301 and show the matching new URL.
Google recrawls old URLs on its own schedule, which can be slow for a host it rarely visits. Speed it up with a temporary sitemap that lists the old URLs:
sitemap-old-urls.xml with the old test.example.com URLs.Make sure the new URLs are in your regular sitemap too.
In Search Console, "Page with redirect" is usually listed as a reason a page is not indexed. During a move, it is the status you want for the old URLs. The move is done when:
site:test.example.com returns no results.Expect a few weeks for small sites and up to a few months for hosts Google rarely crawls. Checking hundreds of URLs by hand is tedious. MyURLMonitor inspects them on a schedule and shows how many have moved.
Yes, once Google recrawls them. It follows the redirect, indexes the new URL and drops the old one.
Yes. Pick one canonical host, 301 the other permanently, and make sure your canonical tags and internal links use the canonical host.
Usually a robots.txt block that hid the noindex, or links pointing to the staging host. Read why staging sites get indexed despite noindex →
At least a year, and longer if old links to the subdomain still exist on other sites.
Our SEO migration service finds every misplaced URL, sets up and verifies the redirects on your stack, and monitors the move until Google has finished. Or do it yourself and track the progress with MyURLMonitor.