A simple pattern for generating Open Graph Images in Rails
  • Open graph images are the images that google/twitter/linkedin show when a page is shared on their newsfeeds. Custom images can make a big impact

  • Requirements

    • Easy to set up

    • Easy to understand and extend

    • Easy to customise

    • Not brittle or prone to break

  • Approach

  • The simplest way to have control over what the image looks like, is to code it as HTML and have it converted into an image using a free third party url-to-image conversion API.

  • Setup

  • Create a new route and controller action - in this case I'm using the application controller but you can use whatever.

  • # config/routes.rb
    get "/og-image/:page_slug" => "application#og_image", :as => "og_image"
  • Add the controller. We can use whatever code we like to get the relevant resource - in this case it's a Page. To prevent complications, avoiding rendering inside a layout file.

  • def og_image 
      @page = Page.find(params[:page_id])
      @title = @page.title
      @url = "tonyennis.com"
      render layout: false 
    end
  • Create the view file. Add the necessary CSS/Fonts directly in here. The default dimensions needed by the sites generally are 1200px x 630px.

  • <link rel="stylesheet" href="https://cdn.toniclabs.ltd/dumb-tailwind.css" />
    
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;600;900&display=swap" rel="stylesheet">
    
    <div id="og-image" style="font-family: 'Outfit';width:1200px;height:630px" class="relative bg-gray-100 flex items-center justify-center border-t-8 border-gray-800">
      <div class="absolute top-0 right-0">
        <img src="/images/me.jpeg" style="width:170px" class="mt-10 mr-10 rounded-full" />
      </div>
      <div class="flex flex-col gap-y-2 p-12">
        <div class="uppercase tracking-wide text-sm text-gray-500" style="letter-spacing: .1em;font-size: 30px">
          <%= @url %>
        </div>
        <div class="font-bold" style="font-size: 100px;line-height:120px;display: -webkit-box;-webkit-line-clamp: 2; /* number of lines to show */-webkit-box-orient: vertical;overflow: hidden;text-overflow: ellipsis;">
          <%= @title %>
        </div>
      </div>
    </div>
  • Visit a url directly in your browser to make sure everything looks as you would expect it to

  • Now use the thum service to convert the content of this url into an image file. This is as simple as prepending the url with https://image.thum.io/get/width/1200/crop/630/. For example this is the image url for a recent blog post.

  • Add a method on the model to get the full og image url

  • # app/models/page.rb
    
    def og_image_url 
      html_url = Rails.application.routes.url_helpers.og_image_url(self.url_slug, host: "tonyennis.com")
      thum_url = "https://image.thum.io/get/width/1200/crop/630/#{html_url}"
      return thum_url
    end
  • Add the og tags to your head

  • # app/helpers/application_helper.rb
    
    def og_image_url
      if @page
        @page.og_image_url
      end
    end
    
  • # app/views/shared/_head.html.erb
    
    <meta property="og:image" content="<%= og_image_url %>" />
  • Test everything in the Facebook linter to make sure it all works ok.


  • Website Page