Chapter 2

Tag Helpers

Patterns for managing Open Graph tags in Rails

The Getting Started guide puts meta tags directly in your layout. That works fine for small apps, but as your app grows you’ll want to extract them into partials or helpers. Here are a few ways to do that.

Shared partial

Pull your meta tags into a partial so you can reuse them across layouts:

<%# app/views/shared/_open_graph.html.erb %>
<meta property="og:title" content="<%= og_title || "My Site" %>">
<meta property="og:description" content="<%= og_description || "Welcome to my site" %>">
<meta property="og:url" content="<%= request.original_url %>">
<meta property="og:site_name" content="My Site">
<meta property="og:type" content="<%= og_type || "website" %>">
<meta property="og:image" content="https://$OGPLUS_KEY.ogplus.net<%= request.path %>">
<meta name="twitter:card" content="summary_large_image">

Render it in your layout:

<head>
  <%= render "shared/open_graph",
    og_title: content_for(:og_title),
    og_description: content_for(:og_description),
    og_type: content_for(:og_type) %>
</head>

Helper method

If you want to build the tags in Ruby instead of ERB, create a helper:

# app/helpers/open_graph_helper.rb
module OpenGraphHelper
  def og_meta_tags(title: nil, description: nil, type: "website")
    safe_join([
      tag.meta(property: "og:title", content: title || "My Site"),
      tag.meta(property: "og:description", content: description || "Welcome to my site"),
      tag.meta(property: "og:url", content: request.original_url),
      tag.meta(property: "og:site_name", content: "My Site"),
      tag.meta(property: "og:type", content: type),
      tag.meta(property: "og:image", content: "https://$OGPLUS_KEY.ogplus.net#{request.path}"),
      tag.meta(name: "twitter:card", content: "summary_large_image"),
    ])
  end
end

Then in your layout:

<head>
  <%= og_meta_tags title: content_for(:og_title),
                   description: content_for(:og_description),
                   type: content_for(:og_type) %>
</head>

Setting tags from controllers

You can also set content_for in a before_action instead of in the view. This is useful when the controller already loads the record:

class PostsController < ApplicationController
  before_action :set_post, only: :show

  def show
  end

  private

  def set_post
    @post = Post.find(params[:id])
    content_for(:og_title) { @post.title }
    content_for(:og_description) { @post.excerpt }
    content_for(:og_type) { "article" }
  end
end