Moving a content-heavy site off WordPress sounds simple in a Trello card and brutal at 2 a.m. when you discover that 4,000 posts have inline base64 images and a custom shortcode no one documented. If you’re planning to migrate WordPress to a headless CMS like Strapi, Sanity, Hygraph, or Cosmic, this guide focuses on the decisions and traps that the average tutorial skips.
We’ve shipped several of these migrations at adproductstogo.com, and below is the workflow we actually use, including the parts that hurt.
Why teams move from WordPress to a headless CMS
Before touching a single export file, be honest about why you’re migrating. The reason changes the architecture.
- Performance: ship a static or ISR front-end on Next.js, Nuxt, or Astro.
- Multi-channel publishing: feed a website, a mobile app, and a kiosk from the same content API.
- Developer experience: typed schemas, Git-based workflows, modern preview pipelines.
- Security and maintenance: less plugin sprawl, fewer 3 a.m. CVE patches.
If your only goal is “WordPress feels slow”, a good cache layer might be cheaper than a full migration. If you need structured content reused across channels, headless is the right call.

Step 1: Audit before you export
Most failed migrations skip this step. Run a real content audit before exporting anything.
- List every post type: posts, pages, custom post types (CPTs), ACF groups, taxonomies.
- Crawl the live site with Screaming Frog or Sitebulb. Save the URL list, status codes, canonicals, and meta tags.
- Export your top 200 URLs from Google Search Console. These are the ones whose ranking you absolutely cannot lose.
- Identify shortcodes, Gutenberg blocks, and embedded HTML that won’t survive a clean export.
- Check media: total size, hotlinks, missing alt text, WebP/AVIF coverage.
Decide your target schema now
Headless CMSs reward structured content. Don’t replicate the WordPress “one big HTML field” model in Strapi or Sanity. Break a Post into clean fields: title, slug, excerpt, hero image, body (portable text or blocks), author reference, categories, SEO object.
Step 2: Pick the right destination
There is no universal winner. Match the CMS to the team.
| CMS | Best for | Watch out for |
|---|---|---|
| Strapi | Self-hosted, full control, custom roles | You own infra, upgrades, backups |
| Sanity | Rich content, Portable Text, real-time collab | GROQ learning curve, usage-based pricing |
| Hygraph | GraphQL-first, federated content | Less plugin ecosystem |
| Cosmic / Contentful | Marketing-friendly UIs, fast onboarding | Cost scales with editors and API calls |
Step 3: Export WordPress content cleanly
You have three realistic options:
- WP REST API (recommended): paginated, predictable JSON, can include ACF fields with the right plugin.
- WPGraphQL: cleaner queries, great for selective field extraction.
- WXR XML export: works for tiny sites, breaks fast on anything custom.
Sample REST extraction loop
GET https://yoursite.com/wp-json/wp/v2/posts?per_page=100&page=1&_embed
The _embed flag pulls featured media, author, and taxonomy in one call, which saves thousands of round-trips on a large site.
The shortcode and Gutenberg trap
The REST API returns rendered HTML, but shortcodes that depend on PHP runtime (forms, sliders, related posts) will return broken markup. Decide per shortcode:
- Replace with a structured field (e.g., a Gallery component).
- Replace with a front-end component in your Next.js or Nuxt app.
- Strip and rewrite manually for high-value pages.

Step 4: Transform and import
Write a Node.js script. Don’t try to do this in a no-code tool unless your site has fewer than 50 posts.
- Fetch posts in batches from the WP API.
- Map fields to your new schema (title, slug, body, seo, etc.).
- Convert HTML to Portable Text (Sanity) or keep it as rich-text blocks (Strapi).
- Upload media to the new CMS or to a CDN like Cloudinary or Bunny, and rewrite image URLs in the body.
- Recreate references: authors, categories, tags. Create them before importing posts so foreign keys resolve.
- Push to the CMS via its CLI or API. Sanity has
sanity dataset import, Strapi has its REST/import plugin.
Handle media properly
Media is where migrations bleed time. Recommendations:
- Download every
/wp-content/uploads/asset locally first. Don’t trust the live server to be available during cutover. - Preserve filenames so old
uploads/URLs can be 301-redirected to the new CDN paths. - Generate WebP/AVIF variants in the new pipeline rather than importing legacy JPEG soup.
- Re-attach alt text. WordPress stores it on the attachment, not in the post HTML, so your transformer needs to fetch it explicitly.
Step 5: Preserve SEO (the part that decides if the project is a success)
Losing rankings is the number one regret in headless migrations. Lock these down:
URL structure
Match your existing slugs exactly. If WordPress used /category/post-slug/, replicate it in your front-end router. If you must change patterns, build a 301 map.
Redirect map
| Old URL | New URL | Type |
|---|---|---|
| /2022/03/old-slug/ | /blog/old-slug | 301 |
| /?p=1234 | /blog/resolved-slug | 301 |
| /wp-content/uploads/img.jpg | https://cdn.site.com/img.jpg | 301 |
Meta and structured data
- Export Yoast or Rank Math meta into a dedicated seo object on each entry.
- Rebuild JSON-LD (Article, BreadcrumbList, Organization) on the front-end.
- Regenerate
sitemap.xmlandrobots.txtfrom the new CMS data, not from the framework defaults. - Keep canonical tags self-referential unless you intentionally consolidate.
Step 6: Stage, QA, and cut over
- Deploy the headless front-end to a staging domain blocked by
robots.txtand basic auth. - Run a Screaming Frog crawl on staging. Compare title tags, H1s, meta descriptions, status codes against the old crawl.
- Validate Core Web Vitals on representative pages.
- Smoke-test forms, search, comments (Disqus, Giscus, or custom), and analytics.
- Schedule the cutover during low-traffic hours. Switch DNS, deploy redirects, submit the new sitemap in Google Search Console.
- Monitor 404s daily for two weeks. Patch the redirect map as needed.

Pitfalls we keep seeing in 2026
- Forgetting feed URLs:
/feed/still gets traffic from aggregators. Generate a new RSS endpoint. - Author archives: WordPress generates them automatically, headless does not. Either rebuild or 301 to the homepage.
- Search: WP’s built-in search disappears. Plug in Algolia, Meilisearch, or Pagefind.
- Comments: decide early whether to migrate, archive read-only, or drop them.
- Editorial shock: editors used to the WP block editor will resist. Budget time for training and good preview URLs.
- Preview environments: configure draft preview before launch, not after editors complain.
Should you keep WordPress as the back-end?
One pragmatic middle path: run headless WordPress with WPGraphQL feeding a Next.js front-end. You keep the editor your team knows, gain a modern front-end, and avoid a full content migration. It’s a valid stop on the road to a fully decoupled CMS, and sometimes it’s the final destination.
FAQ
How long does it take to migrate WordPress to a headless CMS?
For a 100-page marketing site, two to four weeks including QA. For a 5,000-post publication with custom fields and complex media, plan for two to four months.
Will my Google rankings drop?
Not if URLs match, redirects are in place, meta data is preserved, and Core Web Vitals improve. Most well-executed migrations see rankings hold or rise within 30 to 60 days.
Strapi or Sanity for a WordPress migration?
Choose Strapi if you want self-hosting, predictable costs, and a familiar admin UI. Choose Sanity if your content is rich, collaborative, and benefits from Portable Text and GROQ queries.
Can I migrate without downtime?
Yes. Build the new site on a staging subdomain, run both in parallel, then swap DNS. Use a short TTL (300 seconds) the day before the swap.
What about WooCommerce?
WooCommerce is a different beast. Migrating product content to a headless CMS while keeping WooCommerce as the commerce engine, or moving to Shopify/Medusa, is a separate project. Don’t bundle it with a content migration unless you have to.
Final thought
A headless migration is 20% code and 80% content decisions. Audit hard, model your schema before exporting, treat redirects as a first-class deliverable, and don’t ship until a full crawl matches. Do that, and the move from WordPress to a headless CMS becomes a performance win instead of an SEO regret.

