MIGRATION
The redirect map: why migrations lose rankings
Almost nobody loses a migration on the content. They lose it on three thousand addresses and a bulk rule that sent nine hundred of them to the homepage.
Content imports. Media imports. Users import. That part is scripted, boring, and it almost never goes wrong.
What goes wrong is URLs. A site has three thousand addresses that ranked, got linked to, and sit in somebody’s bookmarks. A migration replaces them with three thousand different ones. What you do in that gap decides whether you keep your traffic.
Losing nothing across a platform move is not a matter of talent. It is what a spreadsheet and three rehearsals buy you, and this guide is the whole method.
A recognisable kind of job is the recovery, arriving months after somebody applied a bulk redirect rule. The pattern is always the same: organic traffic gone for weeks before anyone diagnosed it, because the site was up, the pages loaded, and nothing in the analytics said “redirect”.
Why bulk rules fail
A bulk rule looks reasonable. “Everything under /product/ goes to /shop/.”
One line, covers a thousand URLs, and wrong in a way that stays invisible until
traffic drops.
Four things happen.
Pages with no equivalent land somewhere generic. A discontinued product redirects to its category. Google treats a redirect to a page that is not equivalent as a soft 404 and drops it, along with whatever authority the old URL had. The redirect returns 301, the browser follows it, and nothing anywhere reports a problem.
Redirect chains form. The old rule redirects to a URL another rule redirects again. Each hop costs a little, and past a few hops crawlers stop following. Chains accumulate quietly across successive migrations, and most sites we inherit already have two generations of them.
Query strings and edge cases get swallowed. Paginated URLs, filtered listings, tracking parameters, uppercase variants, trailing-slash variants, URL-encoded characters. A pattern rule usually handles one form and 404s the rest, and the rest is often the majority once you count real traffic.
Nobody can audit a rule. A spreadsheet of three thousand rows can be checked by a person, sorted by traffic, and reviewed line by line for the twenty that matter. A regular expression cannot. When something goes wrong at 2am you can read a row. You cannot read intent out of a pattern.
The alternative is not glamorous. It is a spreadsheet.
Week one is a crawl and a spreadsheet
Every migration we do starts with the same document, and it is the deliverable the rest of the project gets measured against.
Crawl the live site. Screaming Frog, Sitebulb, whichever crawler you like. Not the sitemap, because the sitemap is what the CMS thinks exists. The crawl is what actually resolves, and the gap between those two lists is frequently thousands of URLs.
Add the URLs the crawl misses. Three sources people forget:
- Search Console, last 12 months, every page that received an impression. This catches pages nothing links to any more but which still rank, which is a surprisingly large category on any site over five years old.
- Server logs, if you can get them. This catches what real crawlers and real people request, including URLs from years ago that no longer appear anywhere. Worth asking your host for, even when it is inconvenient.
- Backlink data, from whatever tool you have. A URL with external links carries authority worth preserving even when it gets no traffic at all.
Add traffic and revenue to every row, from analytics, last twelve months. That is what turns a flat list into a priority order. Twenty URLs usually carry most of the value, and those get verified by hand, twice.
Decide a destination for every row. Not a pattern. A destination.
The columns that earn their place
The sheet is not complicated, and every column has a job:
| Column | Why it is there |
|---|---|
| Old URL | The key. Exactly as it resolves, including trailing slash |
| Status now | Some of them are already 301s or 404s, and you should know |
| Sessions, 12mo | Priority order |
| Revenue, 12mo | Priority order for commerce |
| Referring domains | Authority worth preserving even at zero traffic |
| New URL | The destination, or blank if 410 |
| Action | 301, 410, or keep |
| Verified | Ticked after the rehearsal crawl confirms it |
| Note | Why, for anything not obvious |
The Note column is the one people skip and the one that pays. In eight months
when somebody asks why a page 410s, the answer is in the row.
What to do when there is no equivalent
This is the decision people avoid, and avoiding it is what produces the bulk rule in the first place.
For each old URL with no direct replacement, choose deliberately:
Redirect to the closest genuinely equivalent page. A discontinued blue widget redirects to the red widget if a customer looking for one would accept the other. The test is whether a visitor arriving there would feel they had found what they wanted, not whether the pages are in the same category.
Redirect to the parent category, but only where the page belonged to that category in a way a visitor would recognise, and only where the category page actually shows them something useful. Never as a default, which is exactly what the bulk rule does.
Return 410 Gone. For content that is genuinely finished: an expired campaign, a filled job listing, a discontinued line with no successor. A 410 tells Google to drop it cleanly and stops it consuming crawl budget. That is a legitimate answer, and it is better than pointing at something irrelevant. Most teams are afraid of it and should not be.
Keep the URL. Sometimes the right migration does not change the URL at all. If the structure works, carry it across. The best redirect map is a short one, and “we kept 60% of the URLs” is a better outcome than a beautifully constructed map of three thousand rows.
The order to apply those: keep, then equivalent, then category, then 410. Work down the list and take the first that honestly applies. If you find yourself reaching for “category” more than a fifth of the time, the new information architecture probably needs another look before anyone writes redirects.
301, 302 or 410
Briefly, because it causes more confusion than it should.
301 permanent for anything that has genuinely moved and is not coming back. This is nearly everything in a migration, and it is what passes authority.
302 temporary almost never, in a migration context. Use it for a genuinely temporary state: a page down for maintenance, an A/B test, a seasonal redirection you will reverse. A 302 left in place by accident is a common reason a migrated page never regains its rankings.
410 Gone for content that is finished, as above. A 404 works too, and 410 is a clearer signal that says “this is intentional” rather than “something might be broken”.
One rule that catches people: redirects must be served at the server or CDN, not by a plugin that boots the whole application to issue a header. On a large site that difference is measurable, and a redirect plugin holding three thousand rules is also a database query on every 404.
Rehearse the cutover on a clone
The second thing that goes wrong is doing the cutover for the first time in production.
We perform the whole thing on a copy, timed, before anything touches DNS:
- Restore production data to a clone.
- Run the import scripts end to end. Time each phase.
- Apply the redirect map.
- Re-crawl the old URL list against the new site, asserting every row returns the status it should: 301 to the mapped destination, or 410.
- Fix what failed. Repeat.
Step four is the one that turns the spreadsheet into a test suite. In crawler terms it is list mode against the old URLs pointed at the staging host. In shell terms it is not much more than this:
while IFS=, read -r old new; do
code=$(curl -s -o /dev/null -w '%{http_code}' -I "https://staging.example.com${old}")
dest=$(curl -s -o /dev/null -w '%{redirect_url}' -I "https://staging.example.com${old}")
[ "$code" = "301" ] && [ "$dest" = "$new" ] || echo "FAIL ${old} -> ${code} ${dest}"
done < redirect-map.csv
Anything printed is a row to fix. Run it until it prints nothing, then run it once more after the next import to be sure the import did not undo it.
By the time DNS moves it is the second or third run, not the first. On the last migration the third run took nineteen minutes and nobody noticed it happen.
What the rehearsal finds, every time: an import taking four hours rather than forty minutes, a media library with a permissions problem, a redirect rule that works on the sample and not on the long tail, or a webhook still pointing at an old URL.
The rollback
Not “we take a backup”. A written procedure, rehearsed, with a decision point and a name against it.
Ours says: if these specific checks fail within the first hour, this named person reverts DNS and we restore from the pre-cutover snapshot. The checks are written down in advance and they are concrete, because “the site seems fine” is not a decision criterion at 3am.
The four we use on most migrations:
- Homepage and the top five pages return 200 with the expected content.
- A sample of fifty redirect rows behaves correctly against production.
- Checkout or the primary conversion path completes end to end with a real transaction.
- Error rate in the log is within normal range for the hour.
We have used the rollback once in four years and it took eleven minutes. Most migrations never need it. The ones that do need it inside twenty minutes, not after an hour of somebody reading documentation and looking for a password.
One preparation that makes this cheap: lower your DNS TTL to 300 seconds at least 48 hours before the cutover, and put it back a week after. Otherwise your rollback is real and your propagation is not.
The week after
Cutover is not the end. For the first week:
Watch 404s daily, in your server log or an error tracker. Every 404 with a referrer or any traffic is a row you missed. Fix it that day, not at the end of the sprint. Day one usually produces a handful, and they are almost always URL forms nobody thought to crawl.
Submit the new sitemap and watch coverage. In Search Console the page indexing report shows pages moving between states. Some churn is normal. Pages moving to “Crawled, currently not indexed” in volume is not, and neither is a rising count of “Page with redirect” for URLs that should be canonical.
Check the top twenty by hand, every day for a week. Those are the pages carrying the value, and a hand check catches things a status code does not: a page that returns 200 with the wrong content, a canonical pointing at staging, a noindex tag that came across from the development environment.
Watch for the staging leak. The single most common post-migration disaster
is a noindex header or a robots.txt disallow that came from the staging
environment. Check both on day one, and check them again on day three, because
a deploy can restore them.
Do not panic at a dip. A small ranking wobble in the first fortnight is normal while Google recrawls. Six weeks of decline is not, and by then you want to have been watching rather than starting to look.
A reasonable expectation: most rankings stable within two weeks, and full recovery of any wobble by week four to six. If week six looks worse than week two, something is wrong and it is nearly always a redirect issue rather than a content one.
Things worth doing while you are in there
- Fix the redirect chains you inherited. Most old sites carry redirects from two migrations ago. Point them at the final destination directly. This is usually a morning’s work and it is the cheapest performance and crawl-budget win available.
- Sort out trailing slashes and case. Pick one form, redirect the other, once, at the server. Doing it now costs nothing; doing it later is another migration.
- Consolidate the near-duplicates. Migrations surface pages nobody knew existed, several of which compete with each other. Merging two thin pages into one good one is worth more than either was.
- Keep the map. It is a project asset. The next migration starts from it, and it is the document proving what was decided and by whom.
What a migration actually costs
The redirect work is a distinct line and worth pricing separately, because it scales with URL count rather than with design complexity.
| Site size | Redirect mapping effort |
|---|---|
| Under 200 URLs | 1 to 2 days |
| 200 to 2,000 URLs | 3 to 5 days |
| 2,000 to 10,000 URLs | 1 to 2 weeks |
| Above 10,000 URLs | 2 weeks plus, and partly scripted with hand review of the top 500 |
Add two to three days for the rehearsals regardless of size, since the number of runs matters more than the number of URLs. On our published WordPress rates that puts the mapping and verification portion of a mid-size migration in the region of $2,000 to $5,000, which is a small fraction of a rebuild and the part that protects the traffic the rest of the project depends on.
What we need before we can price one
Five things. Anyone quoting a platform move without them is guessing.
- A crawl of the current site. We run it for you in the audit, which is a fixed $800 over two days.
- Read access to the current platform. Exports lie, and fields that look tidy in an interface are frequently inconsistent underneath.
- Your top pages by traffic and revenue, last twelve months.
- Every integration touching the site: payment gateways, ERPs, email platforms, anything with a webhook pointing at a URL about to change. Most commonly forgotten, most disruptive when missed.
- Any date you cannot move.
Common questions
How long should redirects stay in place?
Permanently, in practice. Google consolidates most signals within a few months, but links on other people’s sites and in other people’s emails do not expire. Removing a redirect map after a year is a way of losing traffic slowly. Keep them, and clean up chains rather than deleting rows.
Will we lose rankings no matter what?
No. A small, short wobble is common while pages are recrawled. Sustained loss is a symptom, not an inevitability, and in the recovery jobs we have taken on the cause has been a redirect problem every time.
Can we redirect everything to the homepage temporarily?
No. That is the specific failure this guide exists to prevent. Google treats a mass redirect to an unrelated page as a soft 404 and drops the URLs, and the recovery takes far longer than doing it properly would have.
What about changing domain at the same time as replatforming?
It is possible and we would rather you did not do both at once. If the date allows, move the platform on the existing domain first, confirm stability for four weeks, then change domain. Two variables mean two possible causes when something goes wrong.
Who should own the redirect map, us or you?
You should own it and we should build it. It is your asset, it outlives the project, and the twenty rows that carry most of your value need somebody from your side to confirm the destinations are right. That review takes an hour and it is the highest-value hour in the whole project.