How Core dna caches pages, what makes a render fast, how code reaches a site and what stays behind, the go-live checklist, and running a site once it is live. For developers, leads and site operators who already build pages in a theme repository.
L2–L3
Unit 05 · Go-live
Redirect mapping
Go-livePage 25 of 34Updated
Every URL the old site served needs somewhere to go. Building the map, how the platform matches a redirect, importing the map in bulk through the REST API, and testing every entry with a script rather than a sample by hand.
Who this is for. The developer moving an existing site to Core dna. Afterwards you can build a complete redirect map, load it as published redirects in one run, and prove that every line works on launch day.
When a site moves, every link to the old site, in search results, other sites, old emails and bookmarks, keeps pointing at the old URLs. A redirect map sends each to its new address with a permanent redirect, which keeps the visitors and most of the ranking the old URL had earned. It is one of the two go-live items most often done badly, because it is tedious and its failures are invisible until traffic drops.
Building the map
Collect every URL the old site serves: its sitemap, a full crawl, the landing pages in its analytics for the last year, the pages search engines have indexed, and the pages other sites link to most. The union of these, without duplicates, is the list.
Map each one to the most specific new URL. An old product goes to the same product, an old article to the same article. Where nothing corresponds, send it to the nearest section, never to the home page: search engines treat a mass redirect to the home page as a page that no longer exists.
Keep only the path. Sources are paths such as /about-us.html, without a trailing slash. Targets on the same domain are paths; a target on another domain is a full URL.
Set aside URLs that differ only by query string, such as /product.php?id=12. A redirect cannot tell them apart (below); they are handled in a template.
Keep the map in a file in the repository, one line per redirect, so it is reviewed, versioned and testable:
A redirect is a record of the site, shared by all of its environments. Each has a source, a target, a matchType of exact or regex, an action of redirect or rewrite, and a redirectCode, 301 unless you set another. Only a published redirect is applied. On each request the platform:
Looks for an exact redirect whose source equals the request's path with any trailing slash removed. On this site /developer-docs/api-documentation, the same path with a trailing slash, and /Developer-Docs/API-Documentation all answer the same 301: exact sources match regardless of a trailing slash and of letter case.
Otherwise tries each pattern redirect in position order, and the first match wins. The source is a regular expression applied to the path as written, without flags, so a pattern is case-sensitive; $1, $2 in the target take the captured groups: ^/news/(\d{4})/(.+)$ to /blog/$2. Every request without an exact match is tested against every pattern, so prefer hundreds of exact redirects to a handful of clever patterns, and anchor each pattern with ^ and $.
Adds the request's query string to the target./developer-docs/api-documentation?utm_source=x is sent to /developer-docs/api-reference?utm_source=x; a parameter written into the target wins over one of the same name in the request.
So the query string is never part of the match: /product.php?id=12 and /product.php?id=13 meet the same redirect. Read the parameter in the template of the path they share instead, as Bulk-import redirects from an old site shows.
The action rewrite serves the target's content at the source URL without redirecting; it is for keeping a URL, not for a migration. Source and target are each at most 190 characters.
A stored page is served before redirects are checked
Redirects run before the site's own pages, so a redirect from a path the new site also uses hides the new page. A page already in the page cache is answered before redirects are looked at, so clear the cache after adding a redirect for a path that was already cached (what invalidation never sees). With CDN caching on, the redirect response itself is cached at the CDN; editing or deleting the redirect clears that copy.
Importing in bulk
Redirects can be created one by one in the admin, or in bulk with POST /cdna-api/rewrites/add-rewrite (API reference), authenticated as an integration: an OAuth access token, or an API key, the older option. Send "published": true in the same call: only a published redirect is applied. A short script reads the file and creates each line:
JavaScriptimport-redirects.mjs
// node import-redirects.mjs redirects.csv
import { readFileSync } from 'node:fs';
const base = process.env.SITE_URL; // https://www.example.com
const token = process.env.CDNA_TOKEN; // never commit it
const rows = readFileSync(process.argv[2], 'utf8').split(/\r?\n/)
.filter(line => line && !line.startsWith('#') && !line.includes('?'))
.map(line => line.split(','));
let failed = 0;
for (const [source, target] of rows) {
const res = await fetch(`${base}/cdna-api/rewrites/add-rewrite`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ source, target, matchType: 'exact', action: 'redirect',
redirectCode: 301, published: true })
});
if (!res.ok) { failed++; console.error(res.status, source, await res.text()); }
}
console.log(`${rows.length - failed} created, ${failed} failed`);
Run it against staging first and test there; redirects are records of the site, so what staging gets, production has too, and running the import again on production would create every redirect twice. If the build was done on a separate copy, run it once on the production site on launch day. Afterwards, count what is there and compare with the file:
The published exact redirects, with the total in totalCount
GET /cdna-api/rewrites/rewrites?matchType=exact&action=redirect&limit=2&properties={id,source,target,redirectCode,published} HTTP/1.1
Host: hub.coredna.com
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
Keep the file as the source of truth. A later correction is a change to the file, applied with PUT /cdna-api/rewrites/rewrites/{id} for the redirect it replaces rather than a second create.
Testing every entry
A sample proves the importer works; it does not prove the map is right. Test every line: each source must answer a 301 whose location is the target, and following it must end on a 200 after exactly one redirect.
Shelltest-redirects.sh
#!/bin/sh
# test-redirects.sh https://www.example.com redirects.csv
base="$1"
tr -d '\r' < "$2" | grep -v '^#' | grep -v '?' | while IFS=, read -r source target; do
[ -z "$source" ] && continue
hop=$(curl -s -o /dev/null -w '%{http_code} %{redirect_url}' "$base$source")
final=$(curl -s -o /dev/null -L -w '%{http_code} %{num_redirects}' "$base$source")
case "$target" in http*) want="$target" ;; *) want="$base$target" ;; esac
if [ "$hop" != "301 $want" ] || [ "$final" != "200 1" ]; then
echo "FAIL $source: first '$hop', final '$final'"
fi
done
Every line it prints is a redirect that is missing, points somewhere else, chains through a second redirect, or ends on an error. A source that answers 200 is usually a page still in the cache. Run it on staging before launch, on production straight after the cache is cleared on launch day, and again a week later. After launch, read the not-found pages reported by analytics and the search console every day for the first weeks, and add what the map missed.