SHORT ANSWER
A redirect map template is a spreadsheet with one row per url of the old site. Three columns are required — old url, new url and status (301, 410, or keep) — and four more make it reviewable: match type, a traffic column such as clicks, notes, and a verified flag. Fill it from a complete list of old urls, settle exact matches and whole folders first, decide the rest by hand starting with the urls that carry traffic, and check that no target is itself a redirect before converting the sheet into your platform’s import file.
The columns that matter
| column | what goes in | why it is there |
|---|---|---|
old_url | the full old url, exactly as it was served | the key of the sheet; one row per old url, never two |
new_url | the full target url, or empty for a 410 | one target per row; it must answer 200 on the new site |
status | 301, 410, or keep (path unchanged) | keep rows document that a url was checked and needs no rule |
match_type | exact, directory, fuzzy, manual, unmatched | tells a reviewer how the target was found — and which rows to read first |
clicks | clicks from the Search Console page export | sort order for the review: the urls that earn traffic get read by a human |
notes | the reason behind a non-obvious decision | six months later, nobody remembers why a page went to the category |
verified | true once a person has checked the row | the line between a suggestion and a decision |
Optional columns earn their place on bigger projects: referring_domains from a backlink tool (a url with links and no traffic is still worth a careful target), owner when several people review sections, and tested_status for the result of the check after launch. Leave out anything nobody will fill in — an empty column is worse than none, because it looks like a decision was recorded.
A worked example
Seven rows from a fictional relaunch of example.com, one of each kind you will meet. Copy the block into a file called redirect-map.csv and open it in Excel or Google Sheets to start from the same columns.
old_url,new_url,status,match_type,clicks,notes,verified https://www.example.com/,https://www.example.com/,keep,exact,4210,homepage,true https://www.example.com/about-us/,https://www.example.com/about,301,fuzzy,310,,true https://www.example.com/services/web-design,https://www.example.com/services/webdesign,301,fuzzy,1180,,true https://www.example.com/blog/2021/pricing-guide,https://www.example.com/magazine/pricing-guide,301,directory,95,rule /blog/ -> /magazine/,true https://www.example.com/team/anna,https://www.example.com/about,301,manual,4,person left; about page lists the team,true https://www.example.com/products/cutter-2018,https://www.example.com/products/cutters,301,manual,22,discontinued; category instead,false https://www.example.com/summer-sale-2019,,410,unmatched,0,expired campaign; no links,true
the homepage — keep — the same url on both sites. It stays in the sheet so the inventory is complete, but it produces no redirect rule.
/about-us/ → /about — the same page under a shorter path, without the trailing slash. A fuzzy match: slug and title agree closely.
/blog/2021/pricing-guide — one of many rows produced by a single directory decision; the note names the rule. In the import file the whole folder can become one wildcard row.
/team/anna — no equivalent exists on the new site; the closest page that answers the same question is the about page. Manual, with the reason written down.
/products/cutter-2018 — a discontinued product sent to its category. Still unverified — the category name might change before launch.
/summer-sale-2019 — an expired campaign with no links and no traffic. Status 410, no target: it is gone on purpose, and the sheet says so.
How to fill it
The order matters more than the speed. Each step shrinks the pile the next one has to look at, so the rows left for manual work are the ones that need it.
- list every old url. A crawl, the sitemap, the Search Console page export, server logs and the previous relaunch’s redirect file — Google’s site move guide names sitemaps, logs and analytics as the places to look. Details in finding the urls nothing links to.
- deduplicate.
/About-Us,/about-us/and/about-us?utm_source=xare one page. Decide on one spelling per row, but keep a note of variants with their own backlinks — they may need their own rule. - mark the exact matches. Same path on the new site: status keep. On a redesign that keeps its structure, that is most of the sheet.
- apply directory decisions.
/blog/becomes/magazine/with sub-paths kept — one decision fills dozens of rows. - pair the rest one to one, on slug, title and h1. Where no equivalent exists, the nearest category page; never the homepage in bulk.
- decide the 410s. What is gone on purpose and holds no links. See 301 vs 302 vs 410.
- sort by clicks and verify. Read every row above a traffic threshold yourself, and set verified only on rows you actually read.
- run the two checks below, then write the import file.
Two formulas that catch the expensive mistakes
With old_url in column A and new_url in column B, add two helper columns. Both formulas work the same in Excel and Google Sheets.
=COUNTIF(A:A, A2)>1 — a duplicate source. The same old url with two targets means one of them is never used — and you do not decide which, the importer does.
=COUNTIF(A:A, B2)>0 — a chain. The target of this row is itself an old url with its own redirect, so a visitor takes two hops. Replace the target with the final destination. Chains come mostly from merging the previous relaunch’s rules with the new map — redirect chains and loops covers how to flatten them.
Both formulas compare text, so they only work if every cell uses the same spelling: the same protocol, host, case and trailing-slash convention. Normalising before the check is part of the deduplication step, not an extra.
EXAMPLE
a 900-row sheet flags 41 chains. 38 of them are rows from the 2019 relaunch’s redirect file whose old targets are now themselves being moved; pointing them at the new targets takes ten minutes and saves a hop on every one of those urls for years.
What goes wrong in a redirect sheet
- a sheet built from the crawl alone. Every orphan page, pdf and campaign url is missing, and nothing in the sheet shows it. The rows you never listed are the ones that turn into 404s.
- targets typed by hand. One typo is a redirect to a 404. Pick targets from a list of the new site’s urls rather than writing them, and check each target answers 200 before export.
- a whole section mapped to the homepage because nobody had time for the rows. Google’s site move guide warns that this “might be treated as a soft 404 error”. The nearest category is almost always available.
- verified set in bulk. A column that is true everywhere carries no information. Mark only rows someone actually read.
- the sheet frozen too early. Pages renamed on the new site after mapping leave targets that no longer exist. Re-check the targets the week before launch.
From the template to the import file
The sheet is for deciding; the import file is for the platform. Only rows with status 301 go into it — keep rows would be redirects to themselves, and a 410 is set on the server or the platform, not in a redirect list. Most importers want two columns, but each spells them differently:
| platform | columns | guide |
|---|---|---|
| Webflow | fromUrl,toUrl | importing into Webflow |
| Shopify | Redirect from,Redirect to | importing into Shopify |
| WordPress plugins | one format per plugin | importing into WordPress |
| Apache, nginx | rules, not a csv | csv to .htaccess or nginx |
The csv Silentfrog exports
If the sheet is the goal, Silentfrog fills most of it: it crawls the old and the new site, pairs identical paths, scores the rest on slug, title and h1, and lets you review, re-map and verify rows in a table before anything is downloaded. The generic csv has these columns:
source_url,target_url,status_code,match_type,confidence,verified
source_urlandtarget_urlare absolute urls; unmatched rows are included with an empty target, so the file is a complete inventory.status_codeis 301 for every row with a target and empty otherwise.match_typeisexact,fuzzy,manualorunmatched;confidenceis the match score from 0 to 1.verifiedistruefor rows you confirmed in the table.clicksandimpressionsare appended once a Search Console export has been imported (traffic data).
It has no notes column and no 410 status — add those in the spreadsheet if you keep one. The second download, the redirects file, skips the sheet entirely: it writes only the rows that should become redirects (no identity rows, no unmatched rows, no unverified review rows) in the spelling of the importer you choose, with directory rules as wildcard rows where the importer supports them (the two downloads).
site settings → publishing → 301 redirects, or the data api
the two export buttons — webflow csv and generic csv — next to the option that includes needs-review matches.
Whether a spreadsheet alone is enough for your site is its own question — spreadsheet vs automated mapping weighs it up.
In short
- One row per old url; old url, new url and status are required, match type, clicks, notes and verified make it reviewable.
- Full urls in the sheet, paths in the import file if the importer wants them.
- Fill it in order: inventory, deduplicate, exact, directories, one to one, 410s, then review by clicks.
- =COUNTIF(A:A, A2)>1 finds duplicate sources; =COUNTIF(A:A, B2)>0 finds chains.
- Only 301 rows go into the import file; keep rows and 410s stay in the sheet.
To start from a filled sheet rather than an empty one, crawl both sites in Silentfrog — the first 50 pages of the old site are free.