Ruby on Rails Open Graph Tags: Add OG Meta with content_for and Helpers

Add og:title, og:image, og:description, and Twitter card tags to Ruby on Rails apps using content_for, yield, and reusable view helpers.

Rails and OG tags

Ruby on Rails renders HTML on the server, so social crawlers receive your OG tags immediately — no JavaScript execution required. The standard Rails approach uses content_for in views and yield in the application layout to inject page-specific metadata.

Application layout with yield

In app/views/layouts/application.html.erb, add OG tag yield blocks with sensible defaults:

<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
<head>
  <title><%= yield(:title) || "My Rails App" %></title>
  <meta name="description"
    content="<%= yield(:description) || "Default description." %>">

  <!-- Open Graph -->
  <meta property="og:title"
    content="<%= yield(:og_title) || "My Rails App" %>">
  <meta property="og:description"
    content="<%= yield(:og_description) || "Default description." %>">
  <meta property="og:image"
    content="<%= yield(:og_image) || asset_url("og-default.jpg") %>">
  <meta property="og:url"
    content="<%= yield(:og_url) || request.original_url %>">
  <meta property="og:type"
    content="<%= yield(:og_type) || "website" %>">

  <!-- Twitter Card -->
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:title"
    content="<%= yield(:og_title) || "My Rails App" %>">
  <meta name="twitter:description"
    content="<%= yield(:og_description) || "Default description." %>">
  <meta name="twitter:image"
    content="<%= yield(:og_image) || asset_url("og-default.jpg") %>">
</head>
<body>
  <%= yield %>
</body>
</html>

Setting OG tags in views with content_for

<!-- app/views/posts/show.html.erb -->
<% content_for :title, @post.title %>
<% content_for :og_title, @post.title %>
<% content_for :og_description, @post.excerpt %>
<% content_for :og_image, asset_url(@post.cover_image) %>
<% content_for :og_url, post_url(@post) %>
<% content_for :og_type, "article" %>

<article>
  <h1><%= @post.title %></h1>
  <%= @post.body %>
</article>

Reusable helper method

For cleaner code, create a helper in app/helpers/application_helper.rb:

# app/helpers/application_helper.rb
module ApplicationHelper
  def set_og_tags(title:, description:, image: nil, url: nil, type: "website")
    content_for(:og_title, title)
    content_for(:og_description, description)
    content_for(:og_image, image || asset_url("og-default.jpg"))
    content_for(:og_url, url || request.original_url)
    content_for(:og_type, type)
  end
end

<!-- In view: -->
<% set_og_tags(
  title: @post.title,
  description: @post.excerpt,
  image: asset_url(@post.cover_image),
  url: post_url(@post),
  type: "article"
) %>

Using the meta-tags gem

The meta-tags gem provides a DSL for managing all meta tags in Rails:

# Gemfile
gem 'meta-tags'

# In controller:
def show
  @post = Post.find_by!(slug: params[:slug])
  set_meta_tags(
    title: @post.title,
    description: @post.excerpt,
    og: {
      title: @post.title,
      description: @post.excerpt,
      image: asset_url(@post.cover_image),
      url: post_url(@post),
      type: 'article'
    },
    twitter: {
      card: 'summary_large_image'
    }
  )
end

# In layout:
<%= display_meta_tags %>

Common Rails OG mistakes

  • Using image_url in non-asset-pipeline images: for user-uploaded images (e.g., via ActiveStorage), use rails_blob_url(@post.cover_image) to generate absolute URLs.
  • Missing host in asset_url: in production, set config.asset_host in config/environments/production.rb so asset_url generates absolute URLs.
  • HTML entities in content: use h() or ERB auto-escaping to prevent characters like & from breaking meta attributes.

Preview your OG tags free at OGFixer.com → Paste your Rails app URL to verify how your link card looks on Twitter, LinkedIn, Discord, and Slack.

← All guides