Create Twitter Cards and LinkedIn Previews with Rails
You want a nice preview when your content is shared on Twitter, LinkedIn, and other sites? That’s a good idea, because, well, it just looks better. Let’s build a simple solution.
Most sites are looking for special meta tags to render their previews. These meta tags are defined by the Open Graph protocol. Additionally, Twitter introduced its own set for their Twitter Card previews.
But Twitter uses Open Graph tags as a fallback. Hence we use them and just add Twitter’s tags for specific information like the username. These are the tags we need:
Used by all sites
Additionally used by Twitter
twitter:creator(Twitter @username of the author of an article)
twitter:site(Twitter @username of the site, product, …)
First, you probably don’t need these previews for each page. It only makes sense for pages that will get shared – e.g. your home page and articles.
We want a simple and flexible solution. So we define a placeholder with
yield in our layout file, and let the view template populate it with
content_for. Here is the layout file:
# app/views/application.html.haml %html %head # ... = yield :og_header = tag(:meta, property: "twitter:site", content: "@exceptiontrap")
The site username is the same for all pages. That’s why we put it directly in the layout file.
In our views, we define the meta tags within a
content_for block. The home page view could look like this:
# app/views/home/index.html.haml - content_for :og_header = tag(:meta, property: "og:title", content: "The Title") = tag(:meta, property: "og:description", content: "The Description") = tag(:meta, property: "og:image", content: asset_url("summary-large-card-tweet.png")) = tag(:meta, property: "twitter:card", content: "summary_large_image")
We use the
asset_url helper to specify the image, because we need the absolute URL, and want to use the asset pipeline. The image would be stored in
Here is an example of what the article page view could look like:
# app/views/blog/articles/show.html.haml - content_for :og_header do = tag("meta", property: "og:title", content: @article.title) = tag("meta", property: "og:description", content: strip_tags(@article.excerpt)) = tag("meta", property: "og:image", content: asset_url("logos/logo-square-250x250.png")) = tag("meta", property: "twitter:card", content: "summary") = tag("meta", property: "twitter:creator", content: "@tbuehl")
Do you find yourself inserting the same code in a lot of views, or do you want a default for all pages? A “default setting” in your layout could be one way to solve this. For example:
# app/views/layouts/application.html.haml %html %head # ... if content_for?(:og_header) = yield :og_header - else = render "layouts/default_og_header"
# app/views/layouts/_default_og_header.html.haml = tag(:meta, property: "og:title", content: "The Title") = tag(:meta, property: "og:description", content: "The Description") # ...
Note: The first time you use Twitter Cards, you need to activate them with the Card Validator. Which doesn’t make much sense to me, but that’s how it works.
Let me know
Any feedback? Just ping me at @tbuehl