Migrating from Expression Engine to WordPress

Recently, at King, we moved our blog over from an old Expression Engine build (v2) over to a new WordPress install. I figured it would be helpful to share my experiences since a lot of the other articles I read were pretty outdated.

First, I’d like to thank Domenico Bettinelli for his article and Travis Smith for his article giving me the initial information for my workflow.

The Workflow

Broken down as simply as possible: we’re going to create a template inside Expression Engine that will convert all of our blog posts into data that WordPress can interpret, save that as an .xml file, and import that file into WordPress.

Step 1

Inside Expression Engine, create a blank template called export and make sure it’s in the default template group. Add this code to the template:

<!--?xml version="1.0" encoding="UTF-8"?-->

    {current_time format="{DATE_RSS}"}
    {exp:channel:categories style="linear" channel="DEFAULT_SITE"}
    {exp:channel:entries channel="DEFAULT_SITE" orderby="date" sort="desc" limit="200" offset="0" rdf="off"}
      {entry_date format="{DATE_RSS}"}
      {entry_date format="%Y-%m-%d %H:%i:%s"}
      {gmt_entry_date format="%Y-%m-%d %H:%i:%s"}
      {embed="comments.xml" the_entry_id="{entry_id}"}

Under Template Preferences, change type to “XML” and “Yes” for Allow PHP.

Enabling PHP in a template will enable anyone with editing rights for that template to become a de-facto Super Admin since they can execute any PHP they want in that template, including PHP that can reveal information about your system, PHP that can delete data from your database, etc. Exercise extreme caution before enabling this option if you permit others to edit your templates.

If you are also exporting comments, create another template called comments, with the same preferences, and with this code:

<!--?php global $IN; $IN--->QSTR = '{embed:the_entry_id}'; ?>
<!--?php global $IN; $IN->QSTR = '{embed:the_entry_id}'; ?-->
{exp:comment:entries weblog="default_site" sort="asc"}
    {comment_date format="%Y-%m-%d %h:%i:%s"}
    {gmt_comment_date format="%Y-%m-%d %h:%i:%s"}

Step 2

Now we have to go through the code and replace the placeholders and general Expression Engine tags with your custom tags.

  • Where it says SITE_DESCRIPTION_HERE put the tagline for your site
  • Where you see YOUR_BLOG_URL_WITH_TRAILING_SLASH/, put the URL to where your WordPress install will go. For example, it might http://www.site.com/blog/
  • Where it says channel=”DEFAULT_SITE”, replace DEFAULT_SITE with the actual channel for your blog.
  • Take a look at the EE tags and change any to match your custom tags. In my instance, I only needed to change the actual post body and excerpt which are:

Step 3

Now that we have our template to generate the data, let’s make it work. Go to the url of that new template file (http://www.site.com/export) and view the page’s source. Save that .xml file as full_export.xml. Open up that .xml file in a text editor such as Coda or Sublime. You should be able to see all the posts and data now. If you don’t have a lot of posts skip to Step 5 but if you do, like I did, we want to just test out the import on one post. Since each tag is an individual entry, delete all but one and save it as single.xml.

When you import your posts you have to assign them to an associated author. Create these authors as “Users” inside WordPress and/or a general user to be used. If this isn’t done all the posts will be authored to your admin account.

Step 4

Inside your WordPress dashboard, go to Tools, Import, WordPress. If you’ve never imported anything, you’re most likely going to have to install the WordPress Importer plugin. Depending on if you’re just testing out a one post import or your full one from Step 4, choose the associated .xml file. Head over to your Posts tab and double check if all of the information made it over. If you were just doing a one post test and everything looks good, delete that post (also from the trash) and import the full one.

Step 5

Once everything is good to go, go back into Expression Engine and delete the template(s) you created.


Hopefully everything went smoothly for you and you have all your old posts on a brand spankin’ new WordPress site. If you know of a better way or feel like I need to elaborate more, let me know below. Good luck exporting!

Join in the Discussion

  • You’re welcome. Glad it worked out for you, Brandon.

  • nlavine

    I think I missed something since nothing exported for me. I also don’t see “Where it says channel=“YOUR_CHANNEL””

    • jasonisaacs

      same for me

    • Sonya Senkowsky

      Did you ever manage to make this work?

      • Brandon Barish

        Hi Sonya, this was the workflow I used that worked. I recently updated the post for EE v2. Take another look and see if the updated documentation works for you.

  • Sonya Senkowsky

    What “old” build of ee were you using?

    • Brandon Barish

      I was using v1. I recently updated the post to show v2 since I assume that’s what most people viewing this post would be using.

    • I was using v1. I recently updated the post to show v2 since I assume that’s what most people viewing this post would be using.

  • TTM Web Design

    The code in the example is from EE v1.x. You need to replace any “weblog” reference to “channel” instead, for it to work on v2.x.

    • Brandon Barish

      Thanks for commenting TTM. The build I was using was v1 so I had used weblog. I updated the documentation for v2, hopefully that will be more helpful to everyone.

    • Thanks, I updated the post.

  • This generated a 404 error for me. Any suggestions?

    • Nm. I solved this problem by using the “view” link within the ExpressionEngine template manager. This helped me discover the correct URL.

  • Katy Forte

    When you say “Where it says channel=”DEFAULT_SITE”, replace DEFAULT_SITE with the actual channel for your blog”, what do you mean by channel?

    • The Expression Engine Channel that your posts are associated with.