# Keep Your Search Rankings Through a Migration

> Source: https://agilitycms.com/docs/developers/keep-search-rankings-through-a-migration

Search engines and other sites know your content by its URLs. When a URL changes or disappears without a redirect, visitors and crawlers that follow it get a 404. This guide shows how to keep every old URL working, carry your SEO metadata into Agility, and catch problems after launch. It is part of [Migrating to Agility](/docs/developers/migrating-to-agility).

## 1. Inventory every URL

Build one list of every URL the old site serves or used to serve. Pull it from several sources, because each one misses something:

- The old site's `sitemap.xml`.
- The old CMS: for example, WordPress returns each post's and term's URL in its `link` field.
- A crawl of the live site.
- Your analytics: the landing pages that get search traffic.
- Your search engines' webmaster tools: indexed pages and pages with external links.
- Files that other sites link to, such as PDFs and images.

Mark the URLs that matter most: top landing pages, pages with external links and pages that convert. Those are the ones you check by hand after launch.

## 2. Keep URLs where you can

The safest redirect is the one you don't need. Agility gives you control over paths:

- **Pages** in the sitemap get their path from the page's place in the sitemap and its page path setting. You can rebuild the old structure.
- **Dynamic pages** generate one page per item in a list, with a path formula built from a field such as `Slug`. Import the old slugs and the URLs stay the same. See [Generating Dynamic Pages From Content](/docs/editors/generating-dynamic-pages-from-content).

Change URLs only where there's a reason to, and redirect every one you change.

## 3. Build the URL map

For every URL in the inventory, record where it goes on the new site:

| Old URL | New URL | Code | Notes |
| --- | --- | --- | --- |
| `/2024/05/spring-launch/` | `/blog/spring-launch` | 301 | Date-based post URL |
| `/category/news/` | `/blog/news` | 301 | Category archive |
| `/about-us/` | `/about-us/` | none | Unchanged, no redirect |
| `/wp-content/uploads/2024/05/guide.pdf` | The file's new `cdn.aglty.io` URL | 301 | A file other sites link to. Use the URL the media library gave you when you uploaded it. |
| `/old-promo/` | none | none | Retired; let it return 404 or 410 |

Rules that keep the map clean:

- **Redirect to the final URL.** Don't chain one redirect into another, and check that no destination is also an origin elsewhere in the list, which would create a loop.
- **Redirect to the closest equivalent,** not to the home page.
- **Use 301 for permanent moves.** Agility redirects are 301 (permanent) or 302 (temporary). Browsers cache 301s heavily.
- **Retired content with no equivalent** should return 404 or 410. Agility's redirect list only does 301 and 302, so handle those status codes in your front end.
- **Normalize the origin URLs.** Pick one form for case and trailing slashes, and match requests in that form. See [Implementing URL Redirects with Next.js](/docs/nextjs/implementing-url-redirects-with-next-js).
- **Remember that a redirect beats a page.** If a path is both a page and a redirect origin, the page can't be reached.

## 4. Load the redirects into Agility

| Method | Use it for |
| --- | --- |
| Import a file in **URL Redirections** | Most migrations. The file has three columns: `OriginURL`, `DestinationURL` and `HTTPCode` (301 or 302). It must not repeat redirections that already exist. |
| Management API: `POST /api/v1/instance/{guid}/url-redirections` | Creating or updating up to 250 redirects per call from a script. Redirects that fail validation or collide with an existing origin URL are skipped and listed in the response. |
| Management API: `POST /api/v1/instance/{guid}/url-redirections/import` | Importing an Excel file of up to 5000 rows. Optional columns limit a redirect to particular locales. |
| Export | Reviewing the full list, or editing it and importing it back as a bulk update. |

Each origin URL can appear only once in an instance. A redirect can apply to all locales or only to the locales you list, which helps when each language has its own URL prefix.

Agility stores the redirects, and your front end applies them. Your site reads the list from the Content Fetch API (`getUrlRedirections` in the JavaScript SDK), which accepts a `lastAccessDate` so a frequent check stays cheap. Test the redirects with the Test action in URL Redirections, which needs a production deployment configured for your sitemap. See [URL Redirections](/docs/editors/url-redirections) and [Testing URL Redirections](/docs/editors/how-to-test-url-redirections).

## 5. Carry over titles, descriptions and canonicals

Map the old site's SEO fields into Agility during the import, not after launch:

| Old site | Agility |
| --- | --- |
| Page title (the `<title>` tag) | The page's **Page Title**, limited to 128 characters, or a meta title field on your content model |
| Meta description | The page's **Meta Description**, or a field on your model |
| Extra head tags (verification tags, hreflang, structured data) | **Additional Header Markup**, or generated by your front end |
| Open Graph and social card tags | Generated by your front end from structured fields such as title, summary and image |
| "Exclude from sitemap" or noindex flags | **Visible on Sitemap**, and your front end's robots handling |

Pages in the sitemap have these SEO fields built in. For items shown through dynamic pages, keep **Include SEO fields on all items** turned on for the list. See [Managing SEO for Editors](/docs/editors/manage-seo) and [Managing SEO for Developers](/docs/developers/manging-seo-for-developers).

**Canonical links:** have your front end output a `<link rel="canonical">` with the absolute production URL of each page. Check that canonicals don't point at the old domain, a staging host or a URL that now redirects.

**Internal links:** rewrite links inside imported body content to the new URLs during the import. Redirects keep old links working, but links on your own site should go straight to the final URL.

## 6. Ship an accurate sitemap and robots.txt

- Generate `sitemap.xml` from your Agility sitemap so it lists the new URLs only. Leave out folders, redirects and hidden pages.
- Give each URL a `lastmod` only when you know the real date its content changed. A migration import can make every item look modified on the same day, so consider keeping the source system's modified date in a field and using it until the item is edited in Agility.
- Submit the new sitemap to your search engines' webmaster tools after launch.
- Use IndexNow to notify the search engines that support it when you publish. Google doesn't use IndexNow, so the sitemap stays your main route there.
- Make sure the production robots.txt allows crawling, and staging and preview hosts don't.

[Faster Indexing with XML Sitemaps and IndexNow](/docs/developers/faster-indexing-with-xml-sitemaps-and-indexnow) shows both in detail.

## 7. Monitor after launch

- **Day 1:** request your top URLs and a sample of old URLs with `curl -I` and confirm each returns 200 or a single 301 to the right place. Re-run the Agility redirect tests.
- **Week 1:** watch your 404 logs and add redirects for old URLs you missed. Check that the new sitemap was read without errors.
- **Weeks 2 to 8:** compare traffic and rankings for your most important pages against the weeks before launch, and look at indexing and redirect reports in your webmaster tools. Fix any page whose title or description was lost.
- **Keep the redirects** in place for the long term. Old links on other sites don't go away.

## Checklist

- [ ] One URL inventory built from the sitemap, CMS, crawl, analytics and webmaster tools.
- [ ] Every old URL is unchanged, redirected (301) to its closest equivalent, or deliberately retired.
- [ ] No redirect chains or loops.
- [ ] Redirects loaded into Agility, applied by the front end and tested.
- [ ] Titles and meta descriptions carried over for every page.
- [ ] Canonicals use absolute production URLs.
- [ ] Internal links point at final URLs.
- [ ] New sitemap.xml submitted; robots.txt correct on production and staging.
- [ ] Monitoring scheduled for the first eight weeks.

## Related

- [Migrating to Agility](/docs/developers/migrating-to-agility)
- [Migration Cutover Runbook](/docs/developers/migration-cutover-runbook)
- [URL Redirections](/docs/editors/url-redirections)
- [Implementing URL Redirects with Next.js](/docs/nextjs/implementing-url-redirects-with-next-js)
- [Faster Indexing with XML Sitemaps and IndexNow](/docs/developers/faster-indexing-with-xml-sitemaps-and-indexnow)

---

## Related pages

- [Migrating to Agility](https://agilitycms.com/docs/developers/migrating-to-agility.md)
- [Migrate from WordPress to Agility](https://agilitycms.com/docs/developers/migrate-from-wordpress.md)
- [Migrate from Contentful to Agility](https://agilitycms.com/docs/developers/migrate-from-contentful.md)
- [Migrate from Sitecore to Agility](https://agilitycms.com/docs/developers/migrate-from-sitecore.md)
- [Migration Cutover Runbook](https://agilitycms.com/docs/developers/migration-cutover-runbook.md)

Index of every docs page: https://agilitycms.com/docs/llms.txt
