WordPress to Craft CMS Migration: Preserving Your Content, Design, and SEO

WordPress to Craft CMS Migration: Preserving Your Content, Design, and SEO

Alex Rollin
Alex Rollin
October 28, 2025
Last updated : February 15, 2026
October 28, 2025

Moving from WordPress to Craft CMS can feel like a major undertaking, but with the right approach, you can make the switch without losing your hard-earned content, design work, or search rankings. This guide walks you through the entire migration process, from initial planning to post-launch monitoring, with practical code examples and specific steps you can follow.

Why Teams Choose to Migrate from WordPress to Craft CMS

WordPress powers millions of websites, but as sites grow and requirements become more complex, its limitations start showing. Plugin conflicts, security concerns, and performance issues push many teams to look for alternatives.

Craft CMS offers a different approach. Instead of relying on dozens of plugins, Craft provides built-in flexibility for custom content structures. You get cleaner code, better performance, and more control over how your site works. The trade-off? Migration requires careful planning and execution.

Prerequisites Before Starting Your WordPress to Craft Migration

Before you begin moving content, you'll need several things in place:

Technical Requirements:

  • Access to your WordPress admin panel and database
  • A staging server with PHP 8.2 and MySQL 5.7.8 or PostgreSQL 13 
  • Composer installed for managing Craft dependencies
  • Basic familiarity with command-line operations

WordPress Site Preparation:

  • Complete backup of your WordPress files and database
  • List of all active plugins and their functions
  • Documentation of your current URL structure
  • Export of your current redirects (if any)
  • Screenshot or documentation of custom post types and taxonomies

Craft CMS Setup:

  • Fresh Craft CMS 5 installation on your staging server
  • Admin account created and configured
  • Basic project configuration completed

Step-by-Step WordPress to Craft CMS Migration Process

Step 1: Audit and Map Your Content Structure

Start by creating a detailed inventory of your WordPress content. Open a spreadsheet and document:

  • All post types (standard posts, pages, custom post types)
  • Taxonomies (categories, tags, custom taxonomies)
  • Custom fields (especially if using ACF or similar plugins)
  • Media files and their organization
  • User roles and permissions

Next, map each WordPress element to its Craft equivalent:

| WordPress Component | Craft CMS Equivalent | Notes |
|-------------------|---------------------|-------|
| Posts | Channel entries | Create a "Blog" channel |
| Pages | Singles or Structure entries | Depends on hierarchy needs |
| Custom Post Types | Channel entries | One channel per post type |
| Categories | Category groups | Direct mapping possible |
| Tags | Tag groups | Direct mapping possible |
| Media Library | Assets | Requires volume setup |
| Custom Fields | Field types | May need field type conversion |

Step 2: Export Your WordPress Content

WordPress offers several export methods. For most migrations, you'll want to combine approaches:

Using WordPress's Built-in Export:

# From WordPress admin:
# Tools > Export > All content > Download Export File
# This creates an XML file with your content

For custom fields and complex data, use WP All Export or create a custom export script:

 'any',
        'posts_per_page' => -1,
        'post_status' => 'any'
    ]);
    
    $export_data = [];
    
    foreach($posts as $post) {
        $export_data[] = [
            'title' => $post->post_title,
            'slug' => $post->post_name,
            'content' => $post->post_content,
            'excerpt' => $post->post_excerpt,
            'date' => $post->post_date,
            'author' => get_the_author_meta('user_login', $post->post_author),
            'categories' => wp_get_post_categories($post->ID, ['fields' => 'names']),
            'tags' => wp_get_post_tags($post->ID, ['fields' => 'names']),
            'meta' => get_post_meta($post->ID),
            'featured_image' => get_the_post_thumbnail_url($post->ID, 'full')
        ];
    }
    
    // Save as JSON for easier import
    file_put_contents('wordpress-export.json', json_encode($export_data));
}

Step 3: Import Content into Craft CMS

We've found that the wp-import CLI tool handles most standard WordPress migrations well, but complex sites often need additional work. Here's how to use it:

# Install wp-import via Composer
composer require craftcms/wp-import

# Run the import
php craft wp-import /path/to/wordpress-export.xml

# The tool will:
# - Analyze your WordPress structure
# - Create matching sections and fields in Craft
# - Import all content with relationships intact

For more control over the import process, use Feed Me plugin with custom mapping:

# feed-me-config.yaml
elementType: craft\elements\Entry
siteId: 1
section: blog
entryType: post

fieldMapping:
  title:
    field: title
    node: wp:title
  slug:
    field: slug
    node: wp:post_name
  postDate:
    field: postDate
    node: wp:post_date
  body:
    field: body
    node: content:encoded
  categories:
    field: blogCategories
    node: category
    options:
      create: true

Step 4: Rebuild Your Templates in Craft

Craft uses Twig templating instead of PHP. You'll need to convert your WordPress theme files:

WordPress header.php example:

>

    <?php wp_title('|', true, 'right'); ?>
    

Becomes this in Craft (_layout.twig):

    {{ siteName }} | {{ title ?? entry.title ?? '' }}
    {{ head() }}

WordPress loop:

    

    


Becomes this in Craft:

{% for entry in craft.entries.section('blog').all() %}
    

{{ entry.title }}

{{ entry.body }} {% endfor %}

Step 5: Set Up URL Routing and Redirects

Maintaining your URL structure is critical for SEO. Configure Craft's routes to match your WordPress permalinks:

// config/routes.php
return [
    // Match WordPress blog structure
    'blog///' => ['template' => 'blog/_entry'],
    
    // Category archives
    'category/' => ['template' => 'blog/_category'],
    
    // Tag archives  
    'tag/' => ['template' => 'blog/_tag'],
];

For URLs that must change, set up 301 redirects using the Retour plugin:

// Setting up redirects programmatically
use nystudio107\retour\Retour;

Retour::$plugin->redirects->saveRedirect([
    'sourceUrl' => '/old-url-pattern/.*',
    'destinationUrl' => '/new-url-pattern/$1',
    'matchType' => 'regex',
    'redirectHttpCode' => 301
]);

Step 6: Migrate SEO Metadata

Working with teams has taught us that SEO preservation often determines migration success. Install and configure SEOmatic for Craft:

{# In your templates, pull in existing SEO data #}
{% do seomatic.meta.seoTitle(entry.seoTitle ?? entry.title) %}
{% do seomatic.meta.seoDescription(entry.seoDescription ?? entry.excerpt) %}
{% do seomatic.meta.seoImage(entry.featuredImage.one() ?? null) %}

{# Set up structured data #}
{% do seomatic.jsonLd.create({
    'type': 'Article',
    'headline': entry.title,
    'datePublished': entry.postDate|atom,
    'dateModified': entry.dateUpdated|atom,
    'author': {
        'type': 'Person',
        'name': entry.author.fullName
    }
}) %}

Common Mistakes to Avoid During WordPress to Craft Migration

1. Forgetting Media File Permissions

When migrating media, ensure your Craft assets volume has proper write permissions:

chmod -R 775 web/uploads
chown -R www-data:www-data web/uploads

2. Missing Internal Link Updates

WordPress internal links often use absolute URLs. Update them during migration:

// Migration script to update internal links
$content = $entry->body;
$content = str_replace('https://old-domain.com', '@web', $content);
$content = str_replace('/wp-content/uploads/', '/uploads/', $content);
$entry->body = $content;

3. Ignoring Custom Field Complexity

ACF repeater fields and flexible content require special handling:

// Converting ACF repeater to Craft Matrix
foreach($acf_repeater as $row) {
    $matrixBlock = new MatrixBlock();
    $matrixBlock->type = 'blockType';
    $matrixBlock->setFieldValues([
        'fieldHandle' => $row['field_value']
    ]);
    $blocks[] = $matrixBlock;
}

4. Not Planning for Plugin Replacements

Document which Craft plugins replace WordPress functionality:

  • Contact Form 7 → Formie or Contact Form
  • Yoast SEO → SEOmatic
  • WP Super Cache → Craft's built-in caching
  • Custom Post Type UI → Native Craft sections

Testing and Verification Steps

Content Verification Checklist

Run these checks on your staging site:

# Check for broken images
wget --spider -r -nd -nv -l 2 https://staging-site.com 2>&1 | grep -B1 "404"

# Verify all entries imported
php craft shell
>>> \craft\elements\Entry::find()->count()
>>> // Compare with WordPress post count

# Check for missing categories/tags
>>> \craft\elements\Category::find()->count()
>>> \craft\elements\Tag::find()->count()

SEO Audit Process

1. Pre-migration baseline: Export all URLs, titles, and meta descriptions from WordPress

2. Post-migration check: Use Screaming Frog to crawl the staging site

3. Compare results: Look for missing pages, changed URLs, or dropped metadata

4. Verify redirects: Test a sample of old URLs to confirm 301 redirects work

Performance Testing

# Test page load times
lighthouse https://staging-site.com --output json --output-path ./lighthouse-report.json

# Check Time to First Byte (TTFB)
curl -w "@curl-format.txt" -o /dev/null -s https://staging-site.com

User Acceptance Testing

Create test scenarios for content editors:

1. Can they create new entries easily?
2. Do image uploads work correctly?
3. Are preview functions working?
4. Can they find and edit existing content?

Post-Launch Monitoring

After going live, monitor these metrics closely:

  • 404 errors: Check server logs and Google Search Console daily
  • Search rankings: Track key pages in your ranking tool
  • Page speed: Monitor Core Web Vitals in Google Search Console
  • User feedback: Set up a feedback form for editors and visitors

Conclusion

Migrating from WordPress to Craft CMS requires careful planning and attention to detail, but the payoff comes in the form of a more flexible, performant, and maintainable website. By following this guide's steps, from initial content audit through post-launch monitoring, you can preserve your valuable content, maintain your design, and protect your search rankings throughout the transition.

Our experience shows that successful migrations happen when teams take time to properly map content structures, test thoroughly on staging environments, and have solid rollback plans. The tools available today, particularly wp-import and Feed Me, make the technical aspects of migration more manageable than ever.

If you're planning a WordPress to Craft CMS migration and need help evaluating your specific requirements, whether it's handling complex custom fields, preserving specialized plugin functionality, or ensuring zero downtime during the switch, we can review your current setup and create a detailed migration plan tailored to your site's unique needs.

Share this article