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 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 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:
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.
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…
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 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: wordpress, typepad, mod_rewrite

