Painless Switch from TypePad to WordPress

Earlier this week I switched my blogging platform from TypePad to WordPress. TypePad is a hosted service and its been REALLY slow lately, its feature-set has stagnated, and it reports barely any statistics. Switching to WordPress would give me tons of power and flexibility.

But switching isn’t easy. It was critical to me not to have any down time and and not to break incoming links. Links from other people or from search engines needed to “just work”.

If I had been using the default TypePad URL stiles.typepad.com I would have been up-a-creek, but I used their domain mapping function and my blog has always served pages at http://www.adamstiles.com. Because I control that domain and its DNS I could manage the switch more easily.

The first thing I did was setup the new WordPress site on one of my servers. The new site was “located” at adamstiles.com but http://www.adamstiles.com was still working at TypePad. Having two live sites with similar URLs made it easy to test links. Just grab a link from the old blog, remove the “www”, test it, etc. When I was finally ready to switchover, I would just change the “www” CNAME DNS record to point at adamstiles.com instead of at stiles.typepad.com. Easy.

TypePad shares an export format with its cousin MovableType. My old TypePad urls took the format adam/{year}/{month}/{name}.html. I setup WordPress to do something similar. In WordPress Admin, Options, Permalinks, set Structure to this value:

/%year%/%monthnum%/%postname%/

OK – lets import the posts from my old blog. The WordPress/Movable Type importer worked great, but my new post URLs didn’t map very well to the old ones.

OLD: /adam/2005/10/refactoring_wit.html
NEW: /2005/10/refactoring-with-pickaxe/

Arghh. The TypePad exporter didn’t include the post “name” (called a “slug” in WordPress lingo) so WordPress created its own. That’s not gonna work. I could workaround the missing “adam” in the URL or the extra “.html” at the end (more on that later), but I needed my post names to come through. TypePad custom templates to the rescue.

All TypePad pages are created using templates. These templates have variables and you can use these variables to do a “mail-merge” to create new documents. If I could create a template that could mail-merge my posts into the standard TypePad export format, but add the post name, then tweak the WordPress importer to recognize and save the post name, I’d be good to go.

Here’s the custom export template I created, and here’s the new importer. I had to make three changes to the old importer: I added a section that would import the correct post name; I removed the old post name section; and I worked around some extra line breaks in the PING parsing section. If anyone wants to see a diff, just ask. I exported my data (I actually did it a bunch of times, made tweaks, reset the database, and started over), imported it into WordPress, and now my new URLs are much closer to what I need.

The custom-export custom-import tweaks go me this far…

OLD: /adam/2005/10/refactoring_wit.html
NEW: /2005/10/refactoring-with-pickaxe/

…but now I needed to make sure that WordPress would respond correctly to the old URLs. That’s where Apache’s mod_rewrite module comes in. mod_rewrite lets you take in incoming URL, slice-and-dice it, and rewrite it in another format.

The first custom mod_rewrite rule I added maintains my permalinks. Any URL coming in that starts with “adam” followed by a 4-digit-year and a 2-digit-month, and ending in “.html” would be handled exactly like the sample WordPress URL above… we would pass WordPress the year, month and name variables and everything would work as expected.

#
# Rewrite old permalinks to new location
# FROM: /adam/2005/12/article_name.html
# TO: index.php?year=2005&monthnum=12&name=article_name
# Same as 2005/12/article_name/ in new system
#
RewriteRule ^adam/([0-9]{4})/([0-9]{1,2})/(.*).html$ /index.php?year=$1&monthnum=$2&name=$3 [QSA,L]

The next custom rule allowed me to maintain the old calendar archive links. These links are similar to the permalinks above but don’t have a name.

#
# Redirect montly archives to new location
# FROM: adam/2005/12/index.html
# TO: index.php?year=2005&monthnum=12
#
RewriteRule ^adam/([0-9]{4})/([0-9]{1,2})/index.html$ /index.php?year=$1&monthnum=$2 [QSA,L]

The next rule makes sure the old category links are maintained too.

#
# Rewrite old category links to new location
# FROM: adam/blogging/index.html
# TO: index.php?category_name=blogging
#
RewriteRule ^adam/(.*)/index.html$ /index.php?category_name=$1 [QSA,L]

One gotcha when importing categories – TypePad uses underscores (_) to separate multiple word category names, and WordPress uses dashes (-). Version 2 of my importer should take this into account, but for now, I just changed my two multi-word categories using the WordPress admin functions.

The last custom rule was important to make sure that old feed/rss subscriptions still worked.

#
# Rewrite old RSS links to new location
# FROM: adam/atom.xml
# TO: index.php?&feed=atom
#
# FROM: adam/index.rdf
# TO: index.php?&feed=rss
#
RewriteRule ^adam/atom.xml$ /index.php?&feed=atom [QSA,L]
RewriteRule ^adam/index.rdf$ /index.php?&feed=rss [QSA,L]

These rules should all come before the default WordPress rules.

Now that all the old links are working (remember the remove-the-www and test trick I mentioned above?) I was set to make the old site live. I changed the DNS so that http://www.adamstiles.com points to the new site at adamstilesoft.com and then started watching my error logs. Those would be the first indicator of broken links. I added a favicon and a robots.txt file, but that was it – everything else (except for some Google-cache issues) worked.

The only minor irritation was that feed-readers “lost track” of which posts my subscribers has already read. That’s because the last-modified date and e-tag data from the old server was lost in the transfer. Not a big deal, and its a small one-time cost. After a few days on WordPress I have no regrets from making the switch.

Tags: , ,

Advertisements

22 thoughts on “Painless Switch from TypePad to WordPress

  1. Terrific explanation, Adam. Very comprehensive. It interests me becuase I’m about to make the move from TypePad to WordPress. I’ve also got domain mapping set up so the switch should be reasonably smooth.

    Unlike you, though, I don’t plan on migrating all the content over to my new WordPress home. Instead, I plan to leave the old blog in place. Of course, that will break every link once I revert the TypePad blog back to the underlying TypePad address. From what I’ve read about export/import, it seemed to me quite a daunting job. However, reading your post gives me a bit of hope that perhaps I ought to make that attempt after all.

    Thanks for a great post. Very helpful.

  2. Good luck to you Neville. Drop me an email if you run into problems – aj nospace stiles at gmail dot com.

  3. If you don’t mind me asking, why would you choose to move to WordPress instead of Movable Type. Since you’re familiar with TypePad it seems that the switch to Movable Type would have be far easier both in terms of import, configuration and use of the program.

  4. Jay – I don’t mind at all. I’ve used MT quite a bit, actually, but liked that WP was pure PHP and that it more hackable. I didn’t find MT to have feature advantages over WP, and the price was right too.

    Adam

  5. hi.

    i just switched from MT to WP. i am trying to get my hands across this redirect business:

    MT url: /archives/category_name/post_title.html
    WP url: /archives/category-name/post-title

    how do i capture this scenario in my htaccess file? any help will be appreciated!

  6. Sepoy – first you have to get mod_rewrite working so that you can create rewriting rules in .htaccess.

    To keep things simple, your new category names should match your old ones… change all dashes (-) to underscores (_) using the WP control panel. Your post names need to match too… I’ll assume they do.

    You need a new rewrite rule in .htaccess, something like this…

    RewriteRule ^archives/(.*)/(.*).html$ /index.php?category_name=$1&name=$2 [QSA,L]

  7. Thanks a bunch, adam.
    I do have mod_write working – because I can get these nice permalinks.

    but any attempt to put a htaccess file fails the whole thing. I will contact my host for that. For the rewrite rules, many cheers!

  8. Pingback: NevOn 2.0 » Final preparations for the move

  9. Pingback: NevOn 2.0 » The dilemma of matching URLs

  10. I’m a mod_rewrite ignoramus who tried to migrate fr. TP to WP with lots of headaches. I even had some really good help fr. Carthik Sharma who did my installation. Carthik wrote mod_rewrite rules for me but somehow my host (or perhaps I) overwrote the rules & they’ve never worked since. So I’m losing 5-10% of my traffic who come to my site using old, broken permalinks.

    I know that these migrations are totally unique & personal so its hard to create a single set of standards for them. But I’d sure like to get more people like you & Neville to write up yr experience both for the WP support forum and for the Codex in order to help others through it.

    Part of my difficult migration experience is detailed in the post linked to this comment.

  11. Hi Adam, I’ve followed the link from Bruce’s blog list – yours is the first one that’s worked !

    Impressive page rank you’ve got. I’ve been blogging about 3 weeks, so bear with me … 🙂

  12. Pingback: Slacker Manager » Blog Archive » links for 2005-12-18

  13. Great writeup! I’m undertaking my own migration and have just a couple of questions. First, are your before/after examples of URLs identical? I’d kinda figured they’d be different, but they look the same…

    Second, I’d love a little help with the Typepad export stuff. I’m comfortable making custom templates, so no worries there. I’m just not sure how you export them without making the template be the default template. What’d you do exactly?

  14. Bren – The before/after examples are without doing any custom templating… just showing what my URLs were like before and after a standard import/export. Those just show that you have to do some custom work to achieve the goal.

    On your second question – its been a while since I did the whole template thing, and I don’t have a TP account anymore, but I think you can create a new template that’s a part of your default template set. IIRC, you can have lots of individual templates that are a part of the main template set. Just create a new one that exports to a file with a new name that doesn’t conflict with other files. Sorry… its been a while.

    Adam

  15. Pingback: Slacker Manager » Blog Archive » links for 2005-12-18

  16. Adam,

    Thanks for the tutorial — it was a lifesaver! However, I found an error in your new importer script: On line 59, you call the old importer script to handle steps 1 and 2, so the Typepad names don’t get imported properly. All that needs to be done is to change “import-mt.php” to “import-mt-with-name.php” and it works like a charm. It might also be helpful to point out to folks that they need to change the path name on line 237 to one that matches their own Typepad paths.

    As for the question about the custom export script, what I did was create a new index template under Design/Edit Current. I called the new template “Export” and gave it the file name export.html. Then I republished the index files and went to /blogname/export.html, which brought up my posts all ready to export. I think perhaps only Pro-level users can do this, so anyone who wants to do this and isn’t already a Pro user will have to upgrade their subscription just prior to cancelling. A couple of issues I ran into along the way:

    1. The first line of your custom export template reads . I can’t explain why, but the lastn specification produced an empty export.html file for me. The only way around it seemed to be to delete the lastn parameter so the first line read simply .

    2. After doing part 1 above, my export.html file displayed as it should, However, it only displayed the last 10 entries of my blog. In order to get around this, I had to go to Configure/Preferences and change the number of posts to display on the front page to 100 (really it just needs to be a number equal to or larger than the number of posts in your blog — I had 95 posts to export). Republish the indexes and all should work properly.

    Thanks again for the great tutorial!

    Alan

  17. Pingback: links for 2005-12-01 at The International House of Nathos

  18. Pingback: Adam Stiles » Running WordPress Feeds Through FeedBurner

  19. Pingback: Mo Jebus

  20. Pingback: HowTo: Make the move to Wordpress from a hosted service at My Africa

  21. Pingback: Converting From Typepad to Wordpress | Working Blogger

Comments are closed.