How can you create a Google sitemap for your Rails application? I searched on the web, and found no real solution–only different people offering their own solutions. What follows is my own solution; I’ve tested it, validated it against the sitemap specification, and it works; so here goes.
First, you need to create an action in one of your controllers. In this action, grab all the pages you want to add an entry for in your sitemap. Here’s how it looks for Launchpad:
def sitemap
@posts = Post.find(:all, :order => "created_on DESC")
@pages = Page.find(:all, :order => "created_on DESC")
end
This code snippet just fetches all posts (chronological entries) and pages (non-chronological entries). We assume our posts and pages each have a slug attribute (that is, a URL–eg. if the title is “Migrations in Rails 2.0″, the slug is migrations-in-rails-20), and a created_on attribute.
If you use a layout for your application (or your controller), you’ll need to disable it for the sitemap action by adding it to the array of :exceptions (or by excluding it from the apply-layout-to-these array)–like so:
layout "something", :except => [:rss, :sitemap]
(Our example has an RSS action, too.) If you don’t do this, your application will render your layout (which is HTML), and embed your XML sitemap in it–not what you want.
The last step is the view template. This template works with posts and pages, follows the official sitemap specification. Behold:
xml.instruct! :xml, :version=>"1.0"
xml.urlset(:xmlns => "http://www.sitemaps.org/schemas/sitemap/0.9") {
xml.url {
xml.loc("http://yoursite.com/")
xml.lastmod(Time.now.localtime.strftime("%Y-%m-%d"))
xml.changefreq("daily")
xml.priority("0.25")
}
for post in @posts
xml.url do
xml.loc("http://www.railsrocket.com/articles/#{post.slug}")
xml.lastmod(post.created_on.strftime("%Y-%m-%d"))
xml.changefreq("daily")
xml.priority("0.99")
end
end
for page in @pages
xml.url do
xml.loc("http://www.railsrocket.com/#{page.slug}")
xml.lastmod(page.created_on.strftime("%Y-%m-%d"))
xml.changefreq("monthly")
xml.priority("0.5")
end
end
}
This generates an entry for our home-page (which is not so important), our pages (which are mostly static, and a little more important then our homepage) and our posts (which are the most important). Pages are updated rarely, posts more often (due to comments).
Everything meets the sitemap XML standard–including the format of the date, and the priority (which, for some reason, cannot be 1–that’s invalid, according to the sitemap specification).
If you want to add any more entries–hard-coded or otherwise–just add another xml.url block.
Once you’ve created your own sitemap, make sure you can view it–you should see the XML document in your browser. Then, validate it–you can find a validator here (requires your sitemap to be online).
As a final step, you can map your sitemap to http://www.yoursite.com/sitemap by adding this to your routes.rb file:
map.connect 'sitemap', :controller => "Something", :action => "sitemap"
And that’s really all there is! Log in to your Google account, specify your sitemap URL, and you’re ready to go!