Support » Fixing WordPress » Best practices for migration from Joomla to WordPress?

  • Hi folks,

    The Preamble

    I’ve got a site that’s been using Joomla since J first came on the scene. It’s currently running Joomla 1.5.23

    I find that Joomla takes way too much of my time to maintain and it becomes a security risk because keeping the core and all the plug-ins, etc. up to date is tedious, to say the least. I’ve got numerous other sites on WP and just love it more and more with every new release. Needless to say, I want to drop Joomla and be solely on WP.

    What I’ve done (and determined) so far
    I’ve read the info at and the part specific to Joomla (it provides three links to variou import tools).

    I’ve also read plenty on info on the forums here, and on other web sites.

    I’ve determined that using one of the migration scripts it should be fairly easy to get the basic page content into WordPress, although there may be issues with formatting (requiring me to manually reformat posts) and their will definitely be issues with images and any content that relies (in Joomla) on plugins or modules, etc.

    Here’s what I’d appreciate advice on

    1) I’d like to make sure the images issue is as automated as possible, but not sure how to go about it.

    2) Plug-in / module specific issues I don’t mind resolving manually. Shouldn’t be too many (he says with fingers crossed)

    3) Here’s the big and important part that so far I’m not 100% sure how to go about doing:
    – How do I ensure my site doesn’t end up generating loads of 404 errors?

    – What is the best practice for migrating a site to a new system, taking into account the SEO permalinks from the old system which Google (etc.) have stored and ranked?

    Currently my site is in

    This is because it was originally on some other system and back then I found that setting up Joomla in a new directory and then putting a message on the old site pages notifying users of the move, etc., was the easiest way to go about it.

    I am thinking the new wordpress install will also need to end up in /site otherwise Google results will all generate 404s. Correct?

    Anyway, the bottom line is that I’d appreciate hearing about how to go about handling what needs to happen AFTER the migration.

    4) I’ve read these articles:

    Can anyone suggest whether the methods outlined in these articles are the best way to go about it?

    5) What happens to article comments? I am assuming they get lost in the process, unless I manually copy them all over? Is that correct?

    What I’d like to create, after doing this successfully, is a guide that comprehensively spells out the steps needed to achieve a full and proper migration from Joomla 1.5.x to WordPress (including handling the potential issues with 404s, SEO migration, permalinks, etc.)

    Any tips or suggestions on any points in the above would be greatly appreciated.

    Thank you,


Viewing 15 replies - 1 through 15 (of 32 total)
  • Here’s an update (6 hours after my original questions):
    I’ve now done the migration, using the Joomla2WP Migrator plugin. It worked well.

    So of my questions/points above, 1 and 2 are resolved.
    5 is resolved, in that I understand comments are not migrated and I’ll have to do it manually or just let them go.

    3 and 4 are still the big question. Namely, how do I ensure the transition is seemless from Google’s perspective?
    The permalink structure on my wordpress site will be quite different from what I had on Joomla. So there will need to be some way to ensure links from search engines end up in the right place.

    Any suggestions? I don’t wish to risk screwing this part up, as it may have long term consequences.



    As far as #3 and #4 I think you can still refer to posts via identifier, so if you had a post with, say, id=276 in Joomla, giving WordPress something like ?p=276 will reach the proper location. That’s if your migration preserved identifiers, which presumably it did…

    Fiddling with .htaccess should point you in the right direction. For example, if you had Joomla URLs of the form /content/view/2985/33/, the following should work:
    RewriteRule ^content\/view\/([0-9]*)/ /?p=$1 [R=301,L]

    If your Joomla URLs were formatted like /index.php?view=article&id=2985&itemid=33, then you’ll need to rewrite those as:

    RewriteCond %{QUERY_STRING} id\=([0-9]+)
    RewriteRule ^ /?p=%1 [R=301,L]

    All the above does is use WordPress’s internal id reference (?p=id always works, provided the given id is that of a valid post) to serve the post. The URL is automatically rewritten as per WordPress settings afterwards.

    Note you’ll need to add your Joomla legacy URL rules above the WordPress rules in .htaccess. If you had Joomla pages with other formats, you’ll have to set up several rules to cover all cases.

    I think that covers it as far as SEO. Google will reach the right page with a code 301 (Moved Permanently), and will update its database with the new WordPress URL.

    Hope that helps.

    Quick reference:
    mod_rewrite wiki

    Thank you very much Spiff06.
    You’ve provided a very comprehensive and super answer! I found nothing like this in my hunt online.

    So what I am understanding is that I simply use the syntax of my old joomla permalinks to grab the post ID and then rewrite to a syntax WordPress understands. Brilliant.

    However, I’ve discovered a limitation in the migration plugin script I used. It did not keep the ID of each post, but instead each article received a new ID. Darn.

    So I will now see if any of the scripts keep the same ID and go through the whole process again (I spent much of yesterday importing and then sorting out everything on the new site… oh well).

    I may return looking for a little help on exactly how to form the rewrite regex string for my joomla permalink format.



    Well, I’ve found only one plugin/script that works with importing from Joomla 1.5.23 to WordPress 3.2.1 – and it’s the one I used. Unfortunately it does not preserve the unique identifier. I’ve looked through its code and could not figure out how I might modify it to do so (not with my super limited programming skills).

    From what I understand, the only way I can successfully use a set of rewrite rules to redirect all my joomla permalinks to their respective wordpress posts is to first have the same unique ID on each, yes? If that is the case, and since my IDs differ, is there any other way to go about this?

    Much thanks,


    That is unfortunate.

    I just took a look at this page and browsed code for the third one in the list (Joomla to WordPress migration wizard). I believe that’s the one you used, correct?

    If that’s the one, then you can try doing the following.

    In index.php, the INSERT line goes like so:

    $j = 0;
    	while ($j < $i) {
    		/* Create an acceptable WP post_name */
    		$post_name = sanitize_title_with_dashes($import[1][$j]);
    		/* Do the actual query */
    		$query = "INSERT INTO wp_posts (id, post_title, post_content, post_date, post_modified, post_name, post_category) VALUES ('', '{$import[1][$j]}', '{$import[2][$j]}', '{$import[3][$j]}', '{$import[4][$j]}', '$post_name', '$wpsection')";
    		/* For debugging purposes */
    		echo "<br />".$query."<br />";
    		$result = mysql_query($query) or die("<p>Query failed</p>");

    The script doesn’t preserve identifiers (the first VALUE entered is ”, i.e. blank, which tells MySQL to auto-increment the index). If you empty the table (to remove leftovers and the first default post) and force the id, you should be able to preserve them.

    First, empty the wp-posts table in phpMyAdmin or from the command-line (TRUNCATE TABLE wp-posts).

    Now modify the INSERT in index.php to force the ID (change the ” to ‘{$import[0][$j]}’) in all three places (lines 385, 468 and 577) [1], something like:

    $query = "INSERT INTO wp_posts
    	(id, post_title, post_content, post_date, post_modified, post_name, post_category)
    	('{$import[0][$j]}', '{$import[1][$j]}', '{$import[2][$j]}', '{$import[3][$j]}', '{$import[4][$j]}', '$post_name', '$wpsection')";

    I think that should do it as far as preserving IDs.

    Note that preserving comments would follow more or less the same pattern used in index.php. If you match the rows in Joomla to those of WordPress, you should be able to find out how to do the INSERTs (example: Migrating from Drupal).

    [1] The third one is actually for links, so you’ll want to truncate the wp_links table as well if you want to migrate links from Joomla and preserve IDs.

    Hello spiff06,

    Actually the 2nd and 3rd one in that list are for old (really old) versions of WP and Joomla. Neither work any more, as far as I understand it.

    The first one says it works on my version of WP, but it did nothing one I hit the IMPORT button. Just refreshed the page, and nothing imported. So in my case that one does not work either.

    The one I used, which worked beautifully, except for it not preserving the unique identifier is called Joomla/Mambo to WordPress Migrator v1.5.4. You can view it here:

    It sorted out internal links, and pulled in images and tags. It seemed like a dream come true, just that’s it’s missing the ID functionality we’ve discussed.

    I’d be happy to modify it to make it work, but looking through its long script in the joomla2wp-mig.php file, I could not easily figure out its logic… I was trying to find where it created each new POST and PAGE record in the WP database, but could not.

    I greatly appreciate you taking the time to tell me how to modify the other plugin. If you have the time and inclination to look through the joomla2wp-mig.php file on the plugin I’ve used, I’d love to hear your suggestions.

    I’ll look over the COMMENTS info you’ve shared. Thank you.

    [As per version 1.5.4 of Joomla to WordPress migrator]

    The insertion happens on line 408 in joomla2wp-mig.php:

    $id = wp_insert_post( $j2wp_page );

    wp_insert_post accepts the ID as a parameter, so all that’s needed is to put an extra key with the Joomla ID in the array.

    The array is populated on line 376:

    $j2wp_pages[] = array(
            'post_author' => $user_id,
            'post_content' => $post_content,
            'post_date' => $R->created,
            'post_date_gmt' => $R->created,
            'post_modified' => $R->modified,
            'post_modified_gmt' => $R->modified,
            'post_title' => $R->title,
            'post_status' => 'publish',
            'comment_status' => 'open',
            'ping_status' => 'open',
            'post_name' => $R->alias,
            'tags_input' => $R->metakey,
            'post_type' => 'page'

    Just add the id to the list (referring to this, and assuming Joomla does indeed use “id” as index field):

    'ID' => $R->id,

    I believe that making these two changes is all that’s needed to make the script preserve identifiers.

    Thank you, again.
    Your help is again much appreciate (I can’t tell you enough!). When I woke up this morning (after discovering last night I needed the script to preserve the identifier) I was on the verge of paying the folks at $50+ to do the whole process from scratch.

    Since my last message I’ve been looking through that file in more detail, and came to the same conclussion as you did. Nice to know I was able to figure it out.

    I gather I MUST empty the WP posts table completely in order to add posts with a forced ID, correct? I ask, because I tried adding on in with my modified script (one with an ID number much higher than any in there at the moment) and although the script reported it successfully inserted one post, the post did not appear. So I am assuming MYSQL refused it due to it trying to force the ID when there are already IDs in there. Correct?

    I have created a new posts table (same structure, but no data) to test my above question out. Will test that now.

    ACtually, taking a closer look at your last suggestion…

    I have determined the insertion was taking place on line 1099:

    $insert_sql = "INSERT INTO " . $j2wp_wp_tb_prefix . "posts" . " set ";

    and that the array was being built on line either or both 1049:

    $wp_posts[] = array(
            'post_author' => $user_id,
            'post_category' => array($wp_cat_id),
            'post_content' => $post_content,

    and/or 1082:

    $array = array(
            "post_author"       => $user_id,
            "post_parent"       => intval($wp_cat_id),
            "post_content"      => $item['post_content'],
    et cetera

    I was going to add this line to the first line of each of those array building sections:
    'ID' => $R->id,

    What are your thoughts? I’ve I identified the wrong section of code, and should go with the code section you found?

    Ah, that’s a shortcoming of wp_insert_post, which I overlooked:

    IMPORTANT: Setting a value for $post[‘ID’] WILL NOT create a post with that ID number. Setting this value will cause the function to update the post with that ID number with the other values specified in $post. In short, to insert a new post, $post[‘ID’] must be blank or not set at all.

    Above solution won’t work. The first workaround that comes to mind is to create a whole bunch of dummy posts starting with id 1 to the highest id in your Joomla installation. Messy.

    RE: the shortcoming of wp_insert_post

    Darn. So close. Thanks for discovering this.

    Well, it looks like I am going to have to have a bash at the “messy” option! I’ll create a bunch of empty records. I have Navicat, so it is relatively easy for me to mess around with my database tables.

    Another thought…
    How complicated would it be to count the number of records in Joomla, and then use some SQL to create that many blank records?

    Answers crossed.

    You are correct. Actual inserts are occuring circa line 1097.

    So, in the list starting at line 1049, add:

    'ID' => $R->id,

    Then in the list starting on line 1081:

    "ID" => $item['ID']

    Give that a try. Truncate wp_posts first.

    Okay. So I tried with an empty (truncated) table, and it did not work. The script reports that it’s working, but the table is not touched.

    I then tried with a table in which I have a whole lot of emtpy records (just the ID is there). That worked.

    My wish is to make this easily repeatable for other folks on Joomla 1.5.x wishing to move to WP. I know there are quite a few, judging by blogs and comments I’ve read online.

    So, it seems that it is this wp_insert_post function you’ve mentioned. Any idea if there is another way of going about it (inserting the records, that is) ?

    Further thoughts:

    Since the script is using a standard SQL “INSERT INTO” statement, I am not sure why this limitation of not being able to create a new record with a forced ID is still in effect.

    Just running the INSERT INTO… myself from a MYSQL command line works fine. I can give it any ID I like… 300, 240, etc.

    I am an absolutely novice at all this, just figuring it out as I go.

    Any ideas on why it’s still not letting me specify the ID field?

    Also, I see the code is using the syntax:

    I am wondering if that has a limitation to only working with existing rows in the table. From what I am reading it is a MYSQL specific statement that uses the same syntax as the normal UPDATE command in SQL. Perhaps it also somehow limited to not being able to force a value for the KEY in a table?

    I am now looking into rewriting the INSERT statement to use VALUES rather than SET. Not getting very far with it so far.

Viewing 15 replies - 1 through 15 (of 32 total)
  • The topic ‘Best practices for migration from Joomla to WordPress?’ is closed to new replies.