An SEO friendly way to remove index.php : Codeigniter 2

Something that has been around as long as Codeigniter, is the ability to modify its URLs and what they show up as in the ‘address bar’. However, sometimes, ‘pretty-urls’ are not the highest thing on your list, or you weren’t aware of them when you first started your website. If you follow the way codeigniter recommends you change and remove your index.php, you may actually cause more harm to your site than you realize. Code after the break.

Update - 4/6/2011

Another nice approach is found in the comments, take a look!

It starts with how search engines manage what URLs your site is using. Search engines need to keep a good idea if you are trying to manipulate your results on the search by including ‘junk’ content. A familiar approach is to have two URLs point to the same content. This way, you are using the same content multiple times and would expect to have a better result on the search engines (because you have so much content on the subject!). Search engines have caught on to this (Google suggestions), and they keep a signature of all the content for your pages with the URLs; if they detect the same or very similar content across different URLs they instinctively rule that content out of the equation (SEO by the sea).
odeigniter is actually suggesting you make two URLs for the same content with their recommended solution by adding the following code into a .htaccess file at the root of your codeigniter installation.

RewriteEngine on
RewriteCond $1 !^(index.php|images|robots.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]

Line by line, this is stating to ‘rewrite’ everything that isn’t beginning with index.php in the URL so that it does not contain index.php on the server-side logic (hidden from the user). However, if the user were to use the URL with index.php still in it, guess what; it will still work. You now have two URLs pointing to the same content!
The SEO friendly way to do this would require a little bit of ‘tom foolery’ with the code. Here is my .htaccess file that I use for my codeigniter sites.

Options +FollowSymLinks
DirectoryIndex index.php

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

RewriteRule ^index.php?(.*)$ $1 [L,R=301]

RewriteCond $1 !^(home.php|css|js|images|robots.txt)
RewriteRule ^(.*)$ /home.php/$1 [L]

<IfModule !mod_rewrite.c>
# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
# Submitted by: ElliotHaughin

ErrorDocument 404 /index.php

First thing you will notice is that I have very similar code involved in my .htaccess that you find in the codeigniter code.

RewriteCond $1 !^(home.php|css|js|images|robots.txt)
RewriteRule ^(.*)$ /home.php/$1 [L]

I have changed out the index.php with home.php (which doesn’t exist yet) and I’m also allowing some CSS and JS folders through the ‘rewrite’. Above this code I’m adding the SEO friendly 301 redirect hook.

RewriteRule ^index.php?(.*)$ $1 [L,R=301]

I am purposely rewriting any URL that begins with index.php to no longer begin with index.php. I also pass [R=301] which tells a browser or search engine that the old URL no longer exists and they need to use the new one from now on.
Back to the home.php, you need to create a new file called home.php and place it in the same place as index.php. The only thing that needs to be inside home.php is the following code.

<?php /*this file is for SEO purposes */

Now, anything going to home.php will be routed to index.php internally so nothing in codeigniter needs to change.


This hasn’t solved the multiple URLs completely, as now anything pointing to home.php will be a second URL to the same content. However, you should’t have anything pointing to this URL and you can make sure that search engines cannot use this URL by adding a clause to your robots.txt. Anybody using the older index.php URL will get a 301 redirect that lets the software they use know not to use it anymore.

There are probably also options to handle not needing another file (home.php) in the .htaccess file but I was unable to get the same results that I am getting with this method. Feel free to correct or update, or tell me why I’m wrong!