SEO for Ruby on Rails

Dave Peiris

August 14, 2019

Ruby on Rails is an incredible framework, and one that I love for how intuitive and understandable it is. When it comes to SEO, there are a huge number of things that Rails does right – but there are a few other things that, like any framework, require some tweaks to make sure it works for search engines as well as users. Whenever I’m working on a Rails app, there’s a few things that I always look at to help give the site a stronger start in search.

1. Redirect www to non-www URLs

I prefer my sites to render at the root domain, so https://yoursite.com, rather than at a www subdomain like https://www.yoursite.com. If you’re using something like Heroku and set both as custom domains, then you’ll find that traffic to both URLs will render the page – without one redirecting to the other. This, ultimately, results in duplicate content.

Duplicate content occurs when the exact same page or content is easily accessed by search engines at more than one URL. While you can’t really receive a penalty for it, it can still cause you some issues when it comes to getting your site ranking well in search.

Duplicate content can result in search engines spending more time and resources crawling pages they don’t need to, and this time can be better spent crawling more valuable pages on your site. And importantly, if you have links pointing to duplicate pages, then that link value can end up being split between your content rather than consolidated into one, well-linked to page – which can hinder your chances of ranking as well as you otherwise should.

With Rails 5, it’s incredibly easy to 301 redirect all requests to the www subdomain to the root domain.

In your routes file, add the following line:

match '(*any)', to: redirect(subdomain: ''), via: :all, constraints: {subdomain: 'www'}

This ensures that any request to any URL on the www subdomain will 301 redirect to it’s equivalent non-www URL (e.g. https://www.yoursite.com/123 would 301 redirect to https://yoursite.com/123).

Thanks to Mike Kitson for the above code.

2. Create SEO-friendly URLs

By default, Rails uses the id of a record to help identify it from the URL, which means you end up with a lot of URLs like /user/45 or /profile/14. However, there will be times where you want to create a URL that’s a bit more SEO-friendly, and that includes keywords separated by a hyphen, rather than a number. Blog posts are a good example of this – you don’t want /posts/15 – you want /posts/seo-friendly-urls (or even just /seo-friendly-urls).

Using a blog post as an example, you’d achieve this by giving every post a unique slug that Rails can use to recognise the post instead of relying on the id.

First, create a migration adding a slug field to posts in the database:

def change
  add_column :posts, :slug, :string

Migrate the database with:

rake db:migrate

And then update Post.rb to include:

validates_uniqueness_of :slug
after_validation :set_slug, on: [:create]

def set_slug
  self.slug = self.slug.to_s.parameterize

You’ll want to make sure that you have a <%= form.text_field :slug %> input field in your new and edit views for the post.

If you want your post to appear at the top-level of your site (so yoursite.com/seo-friendly-url), add this to your routes.rb file:

get '/:id', to: 'posts#show', as: 'blog_post'

And then in your posts_controller.rb file, you can find your post by its slug using:

@post = Post.find_by_slug(params[:id])

3. Fix trailing slash issues

Google treats URLs with and without the trailing slash (like yoursite.com/file and yoursite.com/file/) as if they’re separate pages. In truth, it’s right to – because they could be completely separate pages. We tested this a while ago and found that Google will crawl both versions of the URL (if they’re both linked to, or if it knows about them) and can index both of them – which ultimately means that these URLs would be seen as duplicate content if they both rendered. There are ways to fix this using canonical tags, but ideally you’d pick a structure (either trailing slash or no trailing slash), only ever link to that version, and have one version 301 redirect to the other.

When I’m building a Rails app, I prefer to have URLs that don’t end in a trailing slash. To do that, in your gemfile add the rack-rewrite gem:

gem 'rack-rewrite'

And then in your config/application.rb file, add:

config.middleware.insert_before(Rack::Runtime, Rack::Rewrite) do
  r301 %r{^/(.*)/$}, '/$1'

Thanks to Steve Grossi for the code above.

4. Force SSL

Google has been using SSL as a ranking factor for years, so for that reason alone you’ll most likely want to ensure your Rails app makes use of it. If you’ve got an SSL certificate up and running for your site, you’ll also want to ensure that HTTP traffic is 301 redirected to it’s HTTPS equivalent. Rails makes this incredibly easy. In config/environments/production.rb, add the following line:

config.force_ssl = true

And that’ll be enough to ensure all requests to non-SSL URLs end up 301 redirecting to the SSL version.

5. Enable gzip compression on Heroku

This one is a tip for those of us who use Heroku to serve their Ruby on Rails apps. Rails spends time using gzip to compress files, which can help to improve page load times by serving smaller files. By default though, Heroku doesn’t make use of it. It’s really easy to implement gzip on Heroku by adding the heroku-deflater gem. Add this to your gemfile:

gem 'heroku-deflater', :group => :production

If you’d like to talk to us about improving the organic search performance for your Ruby on Rails site, drop us a line – we’d love to hear from you.

Header image by Ales Nesetril

Related Articles