Elegant Titles and SEO Meta Tags in Rails

One of the best things about Rails is its powerful templating system which logically split the view into layouts, views, and partials, and makes creating great sites a snap. But this template approach makes it difficult to create dynamic <title> </title> tags, as you can't easily alter your layout file from within a view.

In this tutorial, we are looking for a solution which fulfills the following criteria:

  1. We need to be able to create dynamic titles on a view-by-view basis.
  2. Specifying the title should be optional. If no title is specified in a view, the title tag should fall back to a pre-defined default.
  3. The solution must be elegant: the default title should be stored in an appropriate settings file, and all logic powering our title tags should be contained within our views and helpers, where they belong - and not in any controllers or models.
  4. There should be minimal markup in our views.

After we look at creating our title tags, we will implement a similar solution for those all-important SEO meta tags.

Creating Defaults

Let's begin by creating a file where we will keep all default settings for our app. We will define our default page title here.

The logical place for such a file would be in the config directory. Let's create a new file there called config.yml, and define our default title within it. We are using a .yml file as YAML is an ideal format for a settings file like this.

default_title: Drunk On Rails by David Lesches

Side note: This file is an ideal spot for saving all values you need to access across an app, such as payment gateway API keys.

Now that we have created our settings file, we need to tell Rails to pick it up. In your config/environment.rb file, add APP_CONFIG = YAML.load_file("#{Rails.root}/config/config.yml").

Each of your settings defined in your config.yml file will now be accessible by calling APP_CONFIG['item'] anywhere in your code. You will need to restart your Rails app for this to take effect.

The Title Method

The title method is a views related method, so let's put in it helpers/application_helper.rb

  def title(title = nil)
    if title.present?
      content_for :title, title
    else
      content_for?(:title) ? APP_CONFIG['default_title'] + ' | ' + content_for(:title) : APP_CONFIG['default_title']
    end
  end

Let's go through this line by line.

The title method can be called either with a title parameter or without. When our title method is called with a parameter, as in title "Our Blog", it assigns "Our Blog" to content_for :title. content_for stores a block of markup in an identifier for later use. We can assign values to a content_for identifier within a view, and retrieve that value later on within the layout. We can do this because Rails interprets the view file before the layout file when rendering a page.

When our title method is called without a parameter, it simply returns the value for our title. It checks to see if we have defined a title using content_for :title. If we have, it will return the app's default title (specified in our config.yml settings file) along with the dynamic title we defined: Drunk On Rails by David Lesches. If no dynamic title was defined, it simply returns the default title alone.

Using The Title Method in Views

Now that we have the title method defined, let's finish up our views. Open your layouts/application.html.erb file and add within the <head> section <title><%= title %></title>, or, if you are using HAML %title= title.

If you visit your app in your browser, you will now see your default title rendered.

So how do we dynamically change our title on a per-view basis? Easy! Open any view file and simply add

For ERB: <% title "My Blog" %>

For HAML: - title "My Blog"

And your title on that page will be rendered as: Drunk On Rails by David Lesches | My Blog

Simple, easy, and very elegant.

Now Repeat for SEO Meta Tags

Now that we've seen how easy it is to create dynamic titles, let's duplicate this functionality to allow us to easily create SEO meta tags.

Back in our config/config.yml, let's define site-wide defaults:

meta_keywords: "ruby on rails, ruby, tutorials, advanced, api, confident code, best practices"
meta_description: "Advanced Ruby on Rails articles from David Lesches on best-practices, confident code design, APIs, tips and tricks, and all kinds of awesome."

Back in our application helper, we will add methods for our tags:

  def meta_keywords(tags = nil)
    if tags.present?
      content_for :meta_keywords, tags
    else
      content_for?(:meta_keywords) ? [content_for(:meta_keywords), APP_CONFIG['meta_keywords']].join(', ') : APP_CONFIG['meta_keywords']
    end
  end

  def meta_description(desc = nil)
    if desc.present?
      content_for :meta_description, desc
    else
      content_for?(:meta_description) ? content_for(:meta_description) : APP_CONFIG['meta_description']
    end
  end

The meta_keywords method now allows us to add keywords to our defaults on a per-view basis. The meta_description method allows us to override the default description on a per-view basis.

In your layouts/application.html.erb file -

<meta name="keywords" content="<%= meta_keywords %>" /> 
<meta name="description" content="<%= meta_description %>" />

Or in HAML -

%meta{ name: 'keywords', content: meta_keywords } 
%meta{ name: 'description', content: meta_description }

And we can now override the defaults on a per-view basis by adding in any view -

ERB: <% meta_description "The Drunk on Rails blog contains elegant solutions to common Rails problems." %>
HAML: - meta_description "The Drunk on Rails blog contains elegant solutions to common Rails problems."

Have comments or thoughts on this article? Let us know in the comments!