Saturday, June 14, 2008

Using rails routing for easy search engine friendly URL changes


In this entry I am going to show how to, in a very search engine friendly way, update a URL for a particular page in a rails website. The rails routing system provides named routes, which are a very nice way to change the URL for a particular page and have all of your links update without having to change code in a bunch of different places. That is a great start on moving a page, but it doesn't take care of any links from outside of your site that might be pointing at the old URL. The best way to handle that is to make it so that the old URL redirects to the new URL, your end users won't notice a difference but the search engines bots will take note and update their indexes.


First off if you are not familiar with routing and named routes in rails you might want to read up on it. The rails API docs have some pretty good material on routes located at http://api.rubyonrails.org/classes/ActionController/Routing.htm


Lets pretend we are moving "http://example.com/users/signup" to "http://example.com/signup". Our original named route might look something like this:


map.signup '/users/signup', :controller => 'users', :action => 'signup'


And the code for a link that pointed to it would look something like this:


<%= link_to 'Signup', signup_url %>

To change our URL we would simply change the named route to look like this:

map.signup '/signup', :controller => 'users', :action => 'signup'

All of the links that used the named route would automatically change to link to the new URL but the old URL would stop working. To change that we could add the following to the routes file

map.signup_old '/users/signup', :controller => 'users', :action => 'signup', :old_url => true

This would allow the old URL to work, but it would be best if we made it so that it redirected to the new URL so that search engines would switch over to the new URL faster. Notice that there is an additional parameter that is defined on the end of the second route, this makes it so that we can easily differentiate what URL a visitor arrived on the page with.

Now all we have to do is make a method we can use in a before filter that redirects the user to the same action, the redirect will automatically use the first route we defined (as long as we leave them in that order in the routes file). In the users controller we would add the following code:

before_filter :redirect_to_new_url

def redirect_to_new_url
if params[:old_url] == true
headers["Status"] = "301 Moved Permanently"
redirect_to({:action => action_name})
end
end
The lines in the route file would look like this:

map.signup '/signup', :controller => 'users', :action => 'signup'
map.signup_old '/users/signup', :controller => 'users', :action => 'signup', :old_url => true

Once you have this in place you only have to add a new route to move a URL in a search engine friendly way, and when you decide that all the external links and search engines are updated all you have to do is get rid of the route that points to the old URL.

83 comments: