Nithin Bekal

Posts About Notes Slides

Set page titles and meta tags in Rails views

22 Jul 2015

When building websites that need to be SEO friendly, we often need to customize the page title and meta tags for individual views.

My preferred way to do this is to add helper methods that you can use in the views to override the defaults. For example, we might want to be able to set the page title and meta tags for a posts#show view like this:

<% # Meta information for the <head> section %>
<% title @post.title %>
<% meta_tag :description, @post.description %>
<% meta_tag :keywords, @post.keywords.join(',') %>

<% # Actual view content %>
<h2><%= @post.title %></h2>
<div class='content'><%= @post.body %></div>

Now let’s write the helpers and modify layouts/application.html.erb to be able to use such helpers.

Page titles

First, we’ll write the page title helper. Add this method to ApplicationController:

module ApplicationHelper
  def title(text)
    content_for :title, text
  end
end

Now change the title tag in app/views/layouts/application.html.erb to look something like this:

<% # inside the head tag... %>
<title>
  <%= if content_for?(:title) then yield(:title) + ' | ' end %>
  My Awesome Site
</title>

Now if you set the title in posts#show, you will see the title as “My Post Title | My Awesome Site”, and otherwise it will be “My Awesome Site”.

Meta tags

Next we will set up the helpers for the meta tags. We might need to setup helpers for description and tags. We can use a single helper that can be used like meta_tag, :description, 'Some description goes here'. We’ll add two helper methods to accomplish this.

module ApplicationHelper
  def meta_tag(tag, text)
    content_for :"meta_#{tag}", text
  end

  def yield_meta_tag(tag, default_text='')
    content_for?(:"meta_#{tag}") ? content_for(:"meta_#{tag}") : default_text
  end
end

In the head section of layouts/application.html.erb:

<meta name='description'
      content='<%= yield_meta_tag(:description, 'Default description') %>' />
<meta name='keywords'
      content='<%= yield_meta_tag(:keywords, 'defaults,ruby,rails') %>' />

In posts#show:

<% meta_tag :description, @post.description %>
<% meta_tag :keywords, @post.keywords.join(',') %>

This solution is actually overkill if we only need to override description and keywords tags. Having two helper methods, #meta_description and #meta_keywords, similar to the title helper, would be a much simpler option in that case. But if you need the ability to override many different tags, the above approach make it simpler.

Hi, I’m Nithin Bekal, a software craftsman with over 7 years of experience in shipping web applications. I mostly use Ruby, but lately have also been exploring Elixir. Co-founder of CrowdStudio.in, and helping organize Rubyconf India. Tweet to me at @nithinbekal.