Now powering over 17% of the Web, WordPress is increasingly becoming the content management system (CMS) of choice for the average user. But what about websites built with an outdated CMS or without a CMS at all? Does moving to WordPress mean starting over and losing all the time, energy and money put into the current website? Nope!

Migrating a website (including the design) over to WordPress is actually easier than you might think. In this guide, we’ll outline the migration process and work through the steps with a sample project. We’ll also cover some of the challenges you might encounter and review the solutions.

About This Guide

Before we get to work, let’s establish some context. First, this guide was written primarily with beginners in mind and will be most helpful for basic websites. Some of you will likely encounter advanced aspects of WordPress migration, but they are beyond the scope of this guide. If you’re tackling an advanced migration and get stuck, feel free to share your difficulty in the comments below.

OBJECTIVES

The objective of this guide is to help you with the following:

ASSUMPTIONS

I assume you have basic familiarity with WordPress. Previous development experience with WordPress would be helpful, but not necessary. I also assume you have an existing website and design that you want to migrate to WordPress.

Starting With A Plan

BASIC STEPS

Here are the basic steps that I recommend you follow for a typical WordPress migration:

  1. Evaluate website.
    Work carefully through the pages on your existing website, identifying all of the types of content (standard pages, photo galleries, resource pages, etc.) and noting any areas that need special attention.
  2. Set up environment.
    Set up WordPress and get ready to import.
  3. Import content.
    Bring over and organize your content, whether via an importing tool, manual entry (for a small amount, when no tool is available) or a custom importing process.
  4. Migrate design.
    Incorporate your existing design into a custom WordPress theme.
  5. Review website, go live.
    Carefully review the import, making adjustments where needed, set up any URL redirects, and then go live.

With this outline in mind, let’s work through each step in detail.

Start With A Plan

The key to a successful migration is to carefully evaluate your current website. You need to figure out how to import and structure the content in WordPress before carrying over the design.

While the principles are the same across migration projects, the details often vary. So, below are two lists of questions to ask as you work out a plan.

IMPORTED CONTENT

EXISTING FUNCTIONALITY

A WORKING EXAMPLE

My brother, Joshua Wold, has volunteered a website to serve as an example; it’s for a side project of his in which he sells posters and postcards of a Vegan Food Pyramid. He built the website in plain HTML, with some basic PHP includes for the header and footer. Below is a screencast of me evaluating the website to give you a sense of how the process will work. Enjoy!

Set Up WordPress

Before importing the content, we need to get WordPress ready to go. If you’re just experimenting or if you prefer offline development, start with a local installation of WordPress. Otherwise, the next step is to install WordPress with your current hosting provider; or you could use the migration process as a great opportunity to move to a new host.

Once WordPress is up and running, you’re ready for action!

Setting Up WordPress

For our example, we’ve installed WordPress with the same host, setting it up in a/wp directory for the duration of the migration process.

SETTINGS AND PLUGINS

With WordPress installed, we’ll make a few minor adjustments:

Depending on the needs of the project, we might have to preinstall plugins. Here are the major categories of plugins:

Import Content

With WordPress up and running, it’s time to bring over all of your content.

If your old website has a CMS, an importing tool might be available. Start by viewing the list of content-importing scripts in the Codex. If there’s a match, great! Follow the instructions and get to work. If all goes well, you’ll have migrated the content over without any trouble.

If your old CMS is not in the list or you don’t have a CMS at all and you’ve got fewer than 100 pages, then manual migration is probably the way to go. Copy and paste the contents, noting the old URLs as you go (tracking the migration in a spreadsheet is a good idea).

4

If you’ve got a custom CMS or a database of records without an importing tool and a high volume of content, then you might want to bring in a specialist to move the content over before continuing. The higher the volume of content, the higher the chance of human error and the more important automating it becomes.

For our project, I’ve migrated the content manually and replaced the existing navigation with a WordPress menu. You can watch the process in this next screencast:

Bring Over The Design

With our content in WordPress, it’s time to bring over the design. Incidentally, if you’re considering a new design, then now is a great time to look at the many excellent WordPress themes out there, both in the official repository and in third-party marketplaces such as ThemeForest and Creative Market. For our purpose, I’ll assume that you’re happy with your design.

EVALUATING A DESIGN

Evaluate the source code of a prospective design as best you can before tackling the migration. If the code is table-based or more complex than you’re comfortable with, then migrating the design might not be worth the effort. While anything is possible (I’ve migrated some complex table-based designs in my time), not everything is practical.

WORKING WITH SOURCE CODE

In my experience, the easiest way to migrate is to work directly with the source code in the browser. While having access to the original hosting environment can be helpful (especially when working with a lot of images and downloadable files), the ways that websites are built vary so widely that you’ll often have to reverse-engineer the original architecture in order to derive anything useful.

5

Going directly to the source code in your browser of choice will save a lot of time and, barring any important “behind the scenes” functionality, give you everything you need. Google Chrome is currently my browser of choice, and I’ve pulled our source-code samples directly from the browser. (In Chrome, go to Menu → Tools → View Source, or just right-click to bring up the contextual menu.)

Create A Custom Theme

If you’re new to them, learn about using themes in the Codex. For the migration process, you can either build a new WordPress theme from the ground up or modify an existing theme to meet your needs. I recommend the latter.

Most of my migration projects have started with the latest version of WordPress’ default theme (currently Twenty Twelve). Recently, I stripped down the default theme to create my own migration starter theme, which I’ll use in our example and which you’re welcome to use yourself. (Feel free to suggest improvements!) Let’s get to work.

Download a copy (ZIP) of the migration starter theme or follow along in your own theme of choice as we work through the relevant theme files.

1. Style Sheet

Our first step is to bring over the styles from the old website. In most cases, this is as simple as searching the source code for references to .css and then copying and pasting the contents from those style sheet(s) into our own style.css. Let’s get to it.

  1. Open up style.css.
  2. Replace the details of the theme (“Name,” “URI,” “Description,” etc.) with your own.
  3. Paste in the styles from the old website.

A NOTE ABOUT IMAGES

As you migrate the style sheet(s), search for and update any references to images. In general, I like to keep all images in an /images/ folder within the theme’s directory. More often than not, changing the locations of images referenced in the original CSS is necessary, and I make sure to update all references in the style sheet and templates accordingly.

2. Header

The next step is to create the header for our new theme. Our objective here is to merge the structure of the current code base with WordPress’ templates. Here’s what we’re going to do:

Let’s get into the code!

ORIGINAL HTML




Vegan Food Pyramid posters, postcards and wallpapers









Vegan Food Pyramid

MERGED HEADER (HEADER.PHP)




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








>

Vegan Food Pyramid

'primary', 'container' => false, 'menu_class' => 'menu' ) ); ?>

EXPLANATION

One of the challenges of migration is deciding whether to improve code as you go along. Our project has a few areas that could be improved, but Joshua and I agreed to leave them as is. Most of you will be tackling the migration of a design that hasn’t been coded to current best practices (although, in fairness to the original coder, they may have been best practices at the time).

Website Review

If time and opportunity allow, I encourage you to improve on the code.Otherwise, take comfort in the fact that, with the website now on WordPress, improvements will be a whole lot easier down the road.

Let’s work through the changes we’ve made!

And that’s a wrap! Let’s move on to the next piece.

3. Footer

The footer is usually the most uneventful template in the migration process. As with the header, our objective is to merge the relevant parts of the original source code. Let’s get to it!

ORIGINAL HTML


<div id="footer"><p>© 2013 VeganFoodPyramid.com</p></div>

<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-6992755-1");
pageTracker._trackPageview();
} catch(err) {}</script>

</body>
</html>

MERGED FOOTER (FOOTER.PHP)


<div id="footer"><p>© <?php echo date('Y'); ?> VeganFoodPyramid.com</p></div>

<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-6992755-1");
pageTracker._trackPageview();
} catch(err) {}</script>

<?php wp_footer(); ?>

</body>
</html>

EXPLANATION

Some footers are hard to migrate (such as ones with complex menus and widgets), but most are simple. In this case, we’ve merged the HTML with our footer template, making sure to preserve our reference to the wp_footer hook. We’ve also changed the date reference to use PHP, ensuring that it updates with each year.

4. Home Page

One of the challenges of a migration is that there are so many different ways to get the job done. The home page is a good illustration of this because it tends to be the most different from the rest of the website. Adopting the simplest method is usually best. I’ve opted to put all of the home page’s content directly in the template. Changes will be rare and can easily be made by editing the template.

Let’s look at the code, excluding the header and footer, which we’ve already covered.

ORIGINAL HTML


<div id="content">

<div id="poster">
<a href="http://veganfoodpyramid.com/images/Vegan-Food-Pyramid-New.jpg"><img class="product-img" src="http://veganfoodpyramid.com/images/Vegan-Food-Pyramid-New.jpg" /></a>
<div class="description">
<h2>Poster</h2>
<p>A 30×20-inch poster illustrating over 125 vegan food items as an alternative to the traditional food pyramid. This poster will catch people’s attention and serve as a suggestion for food ideas.</p>
<h3>$30 each</h3>
<p>Includes free shipping worldwide</p>
<a class="button" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2FKQT879CXYYG">Buy</a>
</div>
</div>

<div id="postcard">
<a href="http://veganfoodpyramid.com/images/Vegan-Food-Pyramid-New.jpg"><img class="product-img" src="http://veganfoodpyramid.com/images/postcard-splash.jpg" alt="Postcard Splash" /></a>
<div class="description">
<h2>Postcards</h2>
<p>Beautiful 4×6 postcards that can be mailed and shared with friends and family. Hand them out at events. Post them on walls. Share the vegan love!</p>
<h3>$50 for 50</h3>
<p>Includes free shipping worldwide</p>
<a class="button" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EN387WHNSSFMW">Buy</a>
</div>
</div>

</div> <!-- end content -->

MERGED HOME PAGE (/PAGE-TEMPLATES/FRONT-PAGE.PHP)


<?php
/**
 * Template Name: Front Page Template
 */

get_header(); ?>

<div id="content">

   <div id="poster">
      <a href="<?php echo get_stylesheet_directory_uri(); ?>/images/Vegan-Food-Pyramid-New.jpg"><img src="<?php echo get_stylesheet_directory_uri(); ?>/images/Vegan-Food-Pyramid-New.jpg" /></a>
      <div class="description">
         <h2>Poster</h2>
         <p>A 30×20-inch poster illustrating over 125 vegan food items as an alternative to the traditional food pyramid. This poster will catch people’s attention and serve as a suggestion for food ideas.</p>
         <h3>$30 each</h3>
         <p>Includes free shipping worldwide</p>
         <a class="button" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2FKQT879CXYYG">Buy</a>
      </div>
   </div>

   <div id="postcard">
      <a href="<?php echo get_stylesheet_directory_uri(); ?>/images/Vegan-Food-Pyramid-New.jpg"><img src="<?php echo get_stylesheet_directory_uri(); ?>/images/postcard-splash.jpg" alt="Postcard Splash" /></a>
      <div class="description">
         <h2>Postcards</h2>
         <p>Beautiful 4×6 postcards that can be mailed and shared with friends and family. Hand them out at events. Post them on walls. Share the vegan love!</p>
         <h3>$50 for 50</h3>
         <p>Includes free shipping worldwide</p>
         <a class="button" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EN387WHNSSFMW">Buy</a>
      </div>
   </div>

</div> <!-- end #content -->

<?php get_footer(); ?>

EXPLANATION

The front-page.php template begins and ends with a reference to the header and footer that we’ve just prepared. In between, we’ll merge the rest of the HTML, and we’ll use the get_stylesheet_directory_uri function, which will dynamically generate references to the images folder in our new theme.

5. Standard Page Template

With the header and footer done, the standard templates are usually quite easy. For brevity’s sake, we’ll go directly to the merged templates.

MERGED TEMPLATE (PAGE.PHP)


<?php
/**
 * The template for displaying all pages.
 */

get_header(); ?>

<div id="content">

   <?php while ( have_posts() ) : the_post(); ?>

      <?php get_template_part( 'content', 'page' ); ?>

   <?php endwhile; ?>

</div>

<?php get_footer(); ?>

CONTENT TEMPLATE (CONTENT-PAGE.PHP)


<?php
/**
 * The template used for displaying page content in page.php
 */
?>

   <article <?php post_class(); ?>>
      <?php the_content(); ?>
   </article>

EXPLANATION

There are several items to point out here:

5. Full-Width Template (full-width.php)

Although not illustrated in the screencast, the design includes a full-width template for use on the “Wallpaper” page, while the standard page template is changed to a narrow width.

Let’s have a look.

MERGED TEMPLATE (TEMPLATES/FULL-WIDTH.PHP)


<?php
/**
 * Template Name: Full-Width Template
 */

get_header(); ?>

<div id="content" class="full-width">

   <?php while ( have_posts() ) : the_post(); ?>

      <?php get_template_part( 'content', 'page' ); ?>

   <?php endwhile; ?>

</div>

<?php get_footer(); ?>

EXPLANATION

With the template created, all that remains is to assign it to a page. From the “Edit Page” interface, find the “Page Attributes” box (usually right below the “Publish” box) and select “Full-Width Template” from the “Templates” dropdown menu.

6. Extras

Now let’s tackle some of the “extras” that sometimes come up as challenges during a WordPress migration.

Review Website

Now that we’ve wrapped up work on the theme, it’s time for a review. Work carefully through the pages on the migrated website. For a large website, focus on the different templates. As you review, here are some things to watch out for:

  1. Broken links
    Make sure all links work as they should. If you have only a few pages, you can check manually. For an automated check, use Integrity (free, for Mac) or Xenu’s Link Sleuth (free, for Windows).
  2. Broken styles
    Occasionally, for one reason or another, a design element of your website might have broken during the migration. Carefully compare the old HTML to the new to make sure you haven’t missed any important code and that the corresponding style sheet rules have been carried over. If all else fails, a quick rebuild of the design element on the new website might be in order.
  3. Broken functionality
    Test any functionality that you’ve migrated over, such as “Buy now” buttons, contact forms, newsletter opt-ins, “members-only” content, embedded maps, media players, etc.
  4. Temporary links
    Depending on how you’ve carried out the migration, temporary links to a subfolder or testing domain might appear in your content or theme. You’ll want to update these before going live. Use the Search and Replace plugin (free) to check for and update links in your content.

SETTING UP REDIRECTS

If your link structure has changed (and it usually will, even if only slightly), make sure that visitors are redirected from the old pages to the new. For small amounts of content, one of the easiest ways to set up redirects is by adding them to the.htaccess file.

Open the .htaccess file in the WordPress directory. If you don’t see it, set your FTP client to show hidden files. Now, create redirect rules for each of the old pages. Be sure to put these rules after WordPress’ block of rules.

Here are the rewrite rules for our links:

Redirect 301 /wallpaper.php http://veganfoodpyramid.com/wallpaper/
Redirect 301 /about.php http://veganfoodpyramid.com/about/
Redirect 301 /contact.php http://veganfoodpyramid.com/contact/
Redirect 301 /contactthanks.php http://veganfoodpyramid.com/contact/thanks/

If editing your .htaccess file is not an option or if you’re dealing with a lot of redirects, then have a look at Redirection (free).

Advanced tip: If the volume of redirects is very high (which is likely with a large-scale migration and a custom importing process), then consider building a function that hooks into template_redirect, compares a generated list of cases, and then uses the wp_redirect function to redirect any matches.

Going Live

Going live with a website usually involves one of two tasks:

  1. Relocate WordPress from the development folder to the root directory.
  2. Point the domain name from the old server to the new WordPress server.

Going Live!

RELOCATING WORDPRESS

If you set up WordPress in a subfolder (as we did), then going live involves a few simple steps. Follow the guide to using a pre-existing subdirectory installation.

Once you’ve made the change, check immediately for any broken links that you may have missed in the final review.

POINTING TO A NEW SERVER

If you set up WordPress on a new server, then you probably used a temporary domain. Accordingly, remove references to the temporary domain before pointing the domain to the new server.

Also, if you’re planning to update the name servers for your domain, then first resolve any dependencies in the current DNS records (such as hosted email and third-party services). I usually go live with a domain by updating the A records, leaving the name servers in place.

Conclusion

And there you have it! A successful WordPress migration is all about the details, and while this guide is by no means comprehensive, you now have a good outline of the process and a sense of some of the challenges you’ll encounter, along with ideas for solving them. If you run into challenges along the way, share them in the comments below. Now get migrating!