# How do you keep SEO through a CMS migration to Sanity?

Reviewed by Martin Dejnicki · facts verified 25 October 2026 · canonical: https://deploi.ca/sanity/migration/cms-to-sanity/seo-preservation

## Short answer

A CMS (content management system) migration to Sanity keeps its search engine optimization (SEO) value when every old URL stays identical or gets one server-side permanent redirect, and titles, canonicals and real modified dates move with each page. Google says permanent redirects lose no PageRank and advises one change at a time ([Google Search Central](https://developers.google.com/search/docs/crawling-indexing/site-move-with-url-changes), October 2026).

- **Vercel configuration redirects:** 2,048 per deployment, as of October 2026. Evaluated at build time, so a redirect stored in Sanity goes live on the next deploy; past 2,048, Vercel points to bulk redirects or middleware ([Vercel, Configuration Redirects](https://vercel.com/docs/redirects/configuration-redirects); [Vercel Knowledge Base, How can I increase the limit of redirects](https://vercel.com/kb/guide/how-can-i-increase-the-limit-of-redirects-or-use-dynamic-redirects-on-vercel))
- **How long redirects stay:** Generally at least 1 year. Google's guidance; 301 and 308 both count as permanent, and permanent redirects lose no PageRank ([Google Search Central, Site Moves and Migrations](https://developers.google.com/search/docs/crawling-indexing/site-move-with-url-changes); [Google Search Central, Redirects and Google Search](https://developers.google.com/search/docs/crawling-indexing/301-redirects))
- **Dates after a Sanity import:** _updatedAt becomes the import time. On every document that holds a reference, because the import strengthens references in new transactions; documents without references keep their date ([Sanity Docs, Import data](https://www.sanity.io/docs/content-lake/importing-data))
- **One sitemap holds:** 50,000 URLs or 50MB uncompressed. Google ignores priority and changefreq, and uses lastmod only when it's consistently and verifiably accurate ([Google Search Central, Build and Submit a Sitemap](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap))

## Deploi's call

Keep every URL identical when you move to Sanity, and change URLs in a later release if you must. A CMS change already replaces templates, metadata and dates, so fixed URLs remove the largest source of loss and let you tell what moved your traffic.

**PHASE: Keep every path identical at launch on Sanity, and change paths in a later release, when**

- A redesign or a domain change ships in the same project, because Google advises one change at a time so you can tell which change moved traffic.
- The site is large or carries many inbound links, so each changed URL is a redirect you maintain for at least a year.
- Nobody owns search engine optimization (SEO) monitoring in Search Console for the weeks after launch.

**MIGRATE: Change URLs in the same move to Sanity when**

- Current URLs carry content management system (CMS) artifacts you lose anyway, such as numeric IDs, query strings or file extensions, so a redirect is coming either way.
- You can map every crawled URL one to one and serve each redirect server-side in one hop.
- Your redirect count fits your host's configuration limit, 2,048 on Vercel as of October 2026, or a middleware lookup is built and tested.

## Do you have to change URLs when you move to Sanity?

No: a move to Sanity can keep every URL exactly as it was, because Sanity stores the path in a slug field and your front end builds the URL from it. Sanity's redirect guide describes that split: in a headless setup the front end and the CMS (content management system) "become decoupled" ([Sanity Docs, Managing redirects](https://www.sanity.io/docs/developer-guides/managing-redirects-with-sanity), October 2026).

Keeping URLs fixed is the lower-risk move. Google says to plan site changes "one after the other, not everything at the same time", and names a domain, a CMS and a layout as separate changes ([Google Search Central](https://developers.google.com/search/docs/crawling-indexing/site-move-with-url-changes), October 2026). The same page prefers setting up the new site on the same CMS as the old one. A move to Sanity can't meet that, so hold the other variable still: the CMS changes, the addresses don't, and any traffic movement traces to one cause.

Change URLs in the same release only when they carry artifacts you'd lose anyway, such as query strings, numeric IDs or `.php` endings. Each changed URL is then a redirect you keep for at least a year. [The full CMS to Sanity migration plan](https://deploi.ca/sanity/migration/cms-to-sanity) starts with an inventory and a crawl of every live URL, which sizes the redirect work, and whether to redesign and replatform together covers the layout half.

## How do you build the URL map for a move to Sanity?

Build the URL map from a crawl of the live site plus an export of the old CMS (content management system), then give every old URL exactly one destination. Sanity's re-platforming course says to extract content and also crawl "your existing website to record all pages that currently exist" ([Sanity Learn](https://www.sanity.io/learn/course/re-platforming-to-sanity/re-modelling-your-existing-content), October 2026). An export misses pages that templates and plugins generate; a crawl misses orphan pages (Deploi's judgment). Google adds four sources of old URLs ([Google Search Central](https://developers.google.com/search/docs/crawling-indexing/site-move-with-url-changes), October 2026):

- Sitemaps already submitted in Search Console.
- Server logs or analytics, for the URLs with the most traffic.
- Search Console's Links report, for pages other sites link to.
- The old CMS's own list of every URL that hosts content.

Put images, PDFs and other embedded files in the map too, because Google says they move like any other URL. Retired content returns 404 or 410. Never send many old URLs to one irrelevant page such as the home page: Google says it might be treated as a soft 404, and Sanity's redirect guide says crawlers penalize redirects to unrelated content ([Sanity Docs](https://www.sanity.io/docs/developer-guides/managing-redirects-with-sanity), October 2026). Keep one rule per old path, so no URL has two competing destinations.

## Where do redirects live in a Sanity stack, and what limits apply?

Redirects run in your front end or at your host, not in Sanity: Sanity stores redirect documents, and the framework or host serves them. Redirect count and edit speed decide where.

**Past 2,048 redirects on Vercel, move to middleware or bulk redirects**

| Where the redirect runs | When an edit goes live | Limit or catch as of October 2026 |
| --- | --- | --- |
| Next.js config reading Sanity at build | Next deploy | 2,048 per deployment on Vercel |
| Middleware, called Proxy in current Next.js, per request | At once, no redeploy | A lookup on every request, slow and costly at scale |
| Vercel bulk redirects | On deploy, or at runtime once published | Pro and Enterprise plans; Pro includes 1,000, then charges; 307 unless set permanent |

The 1,024 limit in Sanity's redirects lesson and Next.js's redirecting guide is out of date ([Vercel](https://vercel.com/docs/redirects/configuration-redirects), October 2026). Sources: [Vercel, Configuration Redirects](https://vercel.com/docs/redirects/configuration-redirects); [Vercel Knowledge Base, How can I increase the limit of redirects](https://vercel.com/kb/guide/how-can-i-increase-the-limit-of-redirects-or-use-dynamic-redirects-on-vercel); [Next.js Docs, How to handle redirects in Next.js](https://nextjs.org/docs/app/guides/redirecting); [Vercel, Bulk Redirects](https://vercel.com/docs/routing/redirects/bulk-redirects); [Vercel, Pricing](https://vercel.com/pricing). As of 24 October 2026.

Next.js sends 308 for a permanent redirect, which Google treats as permanent like 301 ([Next.js Docs](https://nextjs.org/docs/app/api-reference/config/next-config-js/redirects); [Google Search Central](https://developers.google.com/search/docs/crawling-indexing/301-redirects), October 2026). Vercel bulk redirects default to 307 ([Vercel](https://vercel.com/docs/routing/redirects/bulk-redirects), October 2026), and `Response.redirect()`, which Sanity's Remix example uses, defaults to 302 ([Mozilla](https://developer.mozilla.org/en-US/docs/Web/API/Response/redirect_static), October 2026). Google keeps a temporary redirect's source page in search ([Google Search Central](https://developers.google.com/search/docs/crawling-indexing/301-redirects)). Validate redirect documents, because an invalid one can stop a deploy ([Sanity Learn](https://www.sanity.io/learn/course/seo-optimization/implementing-redirects), October 2026). See redirects at scale and [the Next.js wiring](https://deploi.ca/sanity/integrations/nextjs).

## Which SEO metadata has to move with each page?

Every page's search engine optimization (SEO) metadata moves as fields: title, meta description, canonical, hreflang, robots rules, structured data and Open Graph tags. A headless front end doesn't carry these over the way a plugin did, as [the SEO risks of going headless](https://deploi.ca/sanity/faq/what-breaks-for-seo-when-going-headless) explains, so plugin data is read out of each source. [The WordPress playbook](https://deploi.ca/sanity/migration/wordpress-to-sanity) and [the Contentful playbook](https://deploi.ca/sanity/migration/contentful-to-sanity) map their own fields.

Four rules keep the transfer honest:

- **Canonicals name the new URL.** Google says each new URL carries a self-referencing canonical and hreflang moves to the new URLs ([Google Search Central](https://developers.google.com/search/docs/crawling-indexing/site-move-with-url-changes), October 2026).
- **The sitemap agrees.** Google says not to name one URL in a sitemap and another in rel="canonical" ([Google Search Central, canonicals](https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls), October 2026).
- **Overrides stay overrides.** Sanity's SEO course treats SEO fields as optional overrides of existing content ([Sanity Learn](https://www.sanity.io/learn/course/seo-optimization/seo-schema-types-and-metadata), October 2026). Import an old SEO title only where it differs from the page title, so later title edits still reach search (Deploi's judgment).
- **Imported documents get validated.** Application programming interface (API) writes skip Studio validation ([Sanity Docs, Import data](https://www.sanity.io/docs/content-lake/importing-data), October 2026), so run `sanity documents validate` on the import file ([Sanity Docs](https://www.sanity.io/docs/content-lake/schema-and-content-migrations), October 2026).

On three deploi.ca Sanity sections, Deploi builds JSON-LD (JavaScript Object Notation for Linked Data) from the same fields as the visible answer, so the two can't drift: JSON-LD from fields.

## Why do sitemap dates go wrong after a Sanity import, and how do you fix them?

Sitemap dates go wrong because the Sanity CLI (command-line interface) import resets `_updatedAt` on every document that holds a reference, and sitemap code often reads `_updatedAt` as lastmod. The import loads references weak, then strengthens them in patches that "run in new transactions, which sets _updatedAt to the time the patch executes successfully"; documents without references keep their date ([Sanity Docs, Import data](https://www.sanity.io/docs/content-lake/importing-data), October 2026). Sanity's sitemap lesson builds lastmod from `_updatedAt` ([Sanity Learn](https://www.sanity.io/learn/course/seo-optimization/building-a-dynamic-sitemap), October 2026). So every migrated page with an author or a category reads as changed on import day. Sanity's answer engine optimization (AEO) guide calls `_updatedAt` an honest dateModified ([Sanity](https://www.sanity.io/aeo-geo-developer-guide), October 2026); for a migrated document that holds a reference, it isn't.

Google uses lastmod only if it's "consistently and verifiably" accurate ([Google Search Central](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap), October 2026). Three fixes:

1. Add editorial `created` and `modified` datetime fields and fill them from the old CMS (content management system) during the import, as Sanity's refactoring course advises ([Sanity Learn](https://www.sanity.io/learn/course/refactoring-content/setting-created-and-modified-dates), October 2026).
1. Build lastmod and JSON-LD (JavaScript Object Notation for Linked Data) dateModified from `modified`, and move it only on significant updates, the standard Google sets.
1. Drop priority and changefreq, which Google ignores, and split sitemaps above 50,000 URLs.

## What is the SEO plan for a move to Sanity, from crawl to monitoring?

The search engine optimization (SEO) plan for a move to Sanity runs in seven steps, and the last two are monitoring. Google says a medium-sized site can take "a few weeks or more" to show its new URLs and is crawled more heavily at first ([Google Search Central](https://developers.google.com/search/docs/crawling-indexing/site-move-with-url-changes), October 2026).

**Keeping SEO through a move to Sanity**

1. **Crawl and export.** Collect every live URL. Owner: search lead.
1. **Map.** One destination, or a 404 or 410, per old URL. Owner: search lead.
1. **Move metadata and dates.** Import seo fields and source modified dates. Owner: developer.
1. **Test redirects.** Crawl the old list on staging for one-hop permanent redirects. Owner: search lead.
1. **Launch.** Lift development noindex and robots.txt blocks, submit old and new sitemaps, and file Change of Address only for a new domain or subdomain ([cutover day](https://deploi.ca/sanity/migration/cms-to-sanity/cutover-and-rollback)). Owner: search lead.
1. **Watch.** Check Search Console's sitemap and crawl error reports regularly as indexing moves to the new sitemap. Owner: search lead.
1. **Hold.** Keep redirects, generally at least a year, and update internal links. Owner: developer.

> **The redirect gap you find after launch**
>
> Sanity's Webflow course warns that "Some URL patterns that seemed covered will surface gaps in your redirect map" ([Sanity Learn](https://www.sanity.io/learn/course/migrating-content-from-webflow-to-sanity/launch-checklist-dns), October 2026), and its refactoring course calls for automated external link checking ([Sanity Learn](https://www.sanity.io/learn/course/refactoring-content/reducing-seo-impact), October 2026).

## Deploi's point of view

**Where we disagree.** Two pieces of standard advice fail in a migration. The first is that a sitemap's priority value tells search engines which pages matter most; Google ignores priority and changefreq. The second is that the automatic _updatedAt timestamp is an honest dateModified. That holds for edits made after launch. For a migrated document that holds a reference, _updatedAt is the import time, so a sitemap or JSON-LD that reads it tells Google every page changed on launch day.

**What we've seen.** deploi.ca's Shopify sections build most of their search plumbing from Sanity content. The FAQ sitemap is built from Sanity and listed 316 URLs on 24 October 2026, and JSON-LD on the Build vs. Buy, FAQ and data pages is built from the same fields as the visible answer, so the two can't drift. Two other sections serve sitemap files written by a script, which go stale until someone reruns it; a sitemap generated on request avoids that drift.

**What this adds.** The root plans the whole migration and gives SEO one step. This page holds what that step needs: where redirects can run in a Sanity stack and the limit of each, why a Sanity CLI import resets _updatedAt and with it every lastmod, which metadata rules keep canonicals and overrides honest, and the order of Search Console checks after launch.

**What we'd tell you to do first.** Crawl the live site before you write the content model. The count of URLs that will change decides where redirects run: a few hundred fit in redirect documents read at build time (Deploi's judgment), while anything near Vercel's 2,048 limit, as of October 2026, needs a middleware lookup or bulk redirects planned from the start, not discovered in the last week.

## When this answer changes

- Google updates its site move guidance or its sitemap lastmod rules
- Vercel changes its 2,048 configuration redirect limit, or the plans and default status code of bulk redirects
- Sanity changes how the CLI import strengthens references or sets _updatedAt
- Sanity corrects the 1,024 figure in its Implementing redirects lesson or changes its sitemap lesson's date source
- Next.js changes the status codes behind permanent and temporary redirects

## Planning the switch itself?

See how to cut over from the old CMS to Sanity with a parallel run, a rollback plan and redirects live on day one. [Plan the cutover](https://deploi.ca/sanity/migration/cms-to-sanity/cutover-and-rollback)

## Sources

1. [Google Search Central, Site Moves and Migrations](https://developers.google.com/search/docs/crawling-indexing/site-move-with-url-changes), checked 24 October 2026
2. [Google Search Central, Redirects and Google Search](https://developers.google.com/search/docs/crawling-indexing/301-redirects), checked 24 October 2026
3. [Google Search Central, Build and Submit a Sitemap](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap), checked 24 October 2026
4. [Google Search Central, How to Specify a Canonical](https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls), checked 24 October 2026
5. [Sanity Learn, Re-modelling your existing content](https://www.sanity.io/learn/course/re-platforming-to-sanity/re-modelling-your-existing-content), checked 24 October 2026
6. [Sanity Docs, Managing redirects with Sanity](https://www.sanity.io/docs/developer-guides/managing-redirects-with-sanity), checked 24 October 2026
7. [Sanity Learn, Implementing redirects](https://www.sanity.io/learn/course/seo-optimization/implementing-redirects), checked 24 October 2026
8. [Sanity Learn, Build a dynamic sitemap](https://www.sanity.io/learn/course/seo-optimization/building-a-dynamic-sitemap), checked 24 October 2026
9. [Sanity Learn, Setting created and modified dates](https://www.sanity.io/learn/course/refactoring-content/setting-created-and-modified-dates), checked 24 October 2026
10. [Sanity Docs, Import data](https://www.sanity.io/docs/content-lake/importing-data), checked 24 October 2026
11. [Sanity Learn, Launch checklist and DNS transfer](https://www.sanity.io/learn/course/migrating-content-from-webflow-to-sanity/launch-checklist-dns), checked 24 October 2026
12. [Sanity, AEO and GEO for developers](https://www.sanity.io/aeo-geo-developer-guide), checked 24 October 2026
13. [Vercel, Configuration Redirects](https://vercel.com/docs/redirects/configuration-redirects), checked 24 October 2026
14. [Vercel Knowledge Base, How can I increase the limit of redirects](https://vercel.com/kb/guide/how-can-i-increase-the-limit-of-redirects-or-use-dynamic-redirects-on-vercel), checked 24 October 2026
15. [Next.js Docs, redirects](https://nextjs.org/docs/app/api-reference/config/next-config-js/redirects), checked 24 October 2026
16. [Next.js Docs, How to handle redirects in Next.js](https://nextjs.org/docs/app/guides/redirecting), checked 24 October 2026
17. [Sanity Learn, Reducing SEO impact](https://www.sanity.io/learn/course/refactoring-content/reducing-seo-impact), checked 24 October 2026
18. [Mozilla, Response: redirect() static method](https://developer.mozilla.org/en-US/docs/Web/API/Response/redirect_static), checked 24 October 2026
19. [Vercel, Bulk Redirects](https://vercel.com/docs/routing/redirects/bulk-redirects), checked 24 October 2026
20. [Vercel, Pricing](https://vercel.com/pricing), checked 24 October 2026
21. [Sanity Learn, SEO schema types and metadata](https://www.sanity.io/learn/course/seo-optimization/seo-schema-types-and-metadata), checked 24 October 2026
22. [Sanity Docs, Migrating your schema and content](https://www.sanity.io/docs/content-lake/schema-and-content-migrations), checked 24 October 2026
