Glenn Jones

Hello đź‘‹ Welcome to my corner of the internet. I write here about the different challenges I encounter, and the projects I work on. Find out more about me.

A straightforward og-tags and meta data pattern in Rails 4

For a current rails project, we have a set of public resources that need to be extra shareable. Shareability is mainly aimed at facebook and twitter. We do this by defining meta OG (opengraph) and twitter tags.

Looking over the internet, I couldn’t find a widely used pattern to set those tags at the top of views. Commonly, the data becomes available at that level though. This is what I thought of.

Wanted behavior for the meta tags

  1. Should be settable at the lowest view layer
  2. Should revert to default values if values are not explicitly set
  3. Should never give 404’s

Make a meta partial

// app/views/partials/_meta_og.html.slim
// tags to provide: og_title, og_description, og_image, og_url, og_article

// use asset_host to change relative urls into absolute urls for og:image. asset uploader (carrierwave) based constraint
- asset_host = Rails.application.config.action_mailer.asset_host
// set a default image
- default_image_url = "http://2.bp.blogspot.com/-j9rFDwz9CME/TrpKEA1NM3I/AAAAAAAADMA/LgeLoblmQAQ/s1600/baby-duck.jpg"

| <!-- twitter -->
meta name="twitter:card" content="summary_large_image"
meta name="twitter:site" content="@_my_twitter_handle_"
meta name="twitter:creator" content="@_my_twitter_handle_"
meta name="twitter:title" content=(content_for?(:og_title) ? yield(:og_title) : “the default title of my twitter links“)
// make sure to kee
meta name="twitter:description" content=(content_for?(:og_description) ? truncate(yield(:og_description), length: 100) : "the default title of my twitter description”)
meta name="twitter:image" content=(content_for?(:og_image) ? asset_host + yield(:og_image) : default_image_url )

| <!-- Facebook and others http://ogp.me/ -->

// gain insights about how your website is being shared in facebook admin by enabling this
// meta property="fb:app_id" content="xxxxxxxx"

meta property="og:locale" content="en_EN"
meta property="og:url" content=(content_for?(:og_url) ? yield(:og_url) : "https://my_website_url.com”)
meta property="og:title" content=(content_for?(:og_title) ? yield(:og_title) : "the default title for OG based links")
meta property="og:description" content=(content_for?(:og_description) ? truncate(yield(:og_description).strip_tags, length: 100) : "the default description for OG based links")
meta property="og:image" content=(content_for?(:og_image) ? asset_host + yield(:og_image) : default_image_url )

// set og:type to article if og_article is provided
- if content_for?(:og_article)
  meta property="og:type" content="article"
- else
  meta property="og:type" content="website"

As you can see this calls yield(:og_symbol) a number of times. yield(:symbol) allows you to set the data to be rendered in that spot at a later moment in the request chain by using content_for(:symbol). Comes in really handy when you need to place data that becomes available in the lowest view, into partials that are called by layouts (thus, higher in the request chain).

Typically, you call this meta in your layout, since you want your meta data to be in the HEAD of your page.

// app/views/layouts/application.html.slim
doctype html
html lang="en-us"
  head
    = render partial: "partials/og_meta"
    = stylesheet_link_tag 'application', media: 'all'
    = csrf_meta_tags

  body
    = render partial: "partials/flash_messages"
    = render partial: "partials/navbar"
    = yield  
    = javascript_include_tag 'application', 'data-turbolinks-track' => true

Creating the content_for‘s

For this, we make a helper.

# app/helpers/share_helper.rb
module ShareHelper
  def set_tags(tag_args)
    tag_args.keys.each do |tag|
      content_for(tag, tag_args[tag])
    end
  end
end

Set the tags on each page

Next you are able to set the tags as appropriate on a per-page basis. If any of the tags are not provided, the partial will use the default value.

- set_tags(meta_title: @resource.name.capitalize, meta_author: @resource.teacher.full_name.capitalize_all, og_title: @resource.name.capitalize, og_description: @resource.description.strip_tags, og_image: @resource.coverimage.xxl.url, og_url: public_course_url(@resource.slug))

h1 hello world

// rest of template goes here

This will put the right OG-tags and other twitter meta data in the HEAD of your page. Simple but effective. Hope it helps you.

Links

Previous: Adding persistent storage to dokku
Next: Import your production data from dokku-postgres