# Add meta tags to a Rails applications

Even though SEO seems like a black box for many developers, it's not that complicated.

Well, at least it's not that complicated to start out doing it considering the best time to start with SEO was right after `rails new` and the second-best time is right now.

In this article, we will learn what meta tags are, why they matter, how to add them to a Rails application, and some best practices you should consider.

Let's go:

## What are meta tags and why you should care
Meta tags are invisible HTML tags that help search engines better understand the content for a given URL. Besides the content, they are probably the most important thing for search engine optimization.

The most common meta tag is the `<title>` tag which is defined by default for any Rails application, and it usually looks like this:

```erb
<title>How to add meta tags to a Rails application - Avo</title>
``` 

You might know about “invisible” tags like `<script/>` or `<link />`, meta tags are tags just like those, but they have the following structure:

```html
<meta name="tag-name" content="This is the tag content" />
```

If you get rid of the markup, they are actually an HTML equivalent to a `{key: value}` pair.

They're usually added to the `<head>` of a document because they're, by definition, not meant to be part of the structure or semantic meaning of an HTML document.

However, **they're meant to communicate things about our content to users, search engines**, machines, and external services like social media applications or even web scrapers.

{{info}}
You might be familiar with the `csrf-param` and `csrf-token` meta tags set automatically by Rails to prevent an exploit called **Cross-Site Request Forgery**.
{{/info}}

The main use for meta tags is that we can deliberately choose how we appear on search engines:

![Search results page showing Avo's website](/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MzQwLCJwdXIiOiJibG9iX2lkIn19--1bb777205aca6f87e37f1f675ff4ea103940c40f/search-results-page.webp)

Here, the `<title>Ruby on Rails Admin Panel Framework - Avo</title>` tag is shown just as it was defined.

But the `meta description` tag's content was not picked up by Google. Instead, it decided to pick a bit of content from the document that they deemed appropriate for this search result.

In the grand scheme of things, **adding meta tags to a site is often a low-effort task that can help us rank better** because they help search engines better understand our intent behind the content and because we are forced to think a bit more about the titles, descriptions, etc. we choose.

Now that we know what they are and why they're useful, let's jump into **adding meta tags for a Rails application:**

{{further_reading slug="structured-data-rails" /}}

## Adding meta tags to a Rails application
As they are just HTML, we could implement meta tags for our application using partials or even our custom [Rails SEO](https://avohq.io/rails-seo) helpers.

However, we can save a lot of time and have the feature be future-proof by using the **“meta-tags”** gem because it comes with basically everything we need built-in.

We will be working with a simple blog as an example, so assume we have an `Article` model with a `title` an `excerpt` and a `content` database columns. It will also have a `cover` attachment using ActiveStorage.

Let's start by adding the gem to our project:

```shell
# Make sure to use 'meta-tags' with the hyphen, the 'meta_tags' gem is deprecated.
bundle add meta-tags
bundle install
```

Then, we install the gem

```shell
bin/rails generate meta_tags:install
```

This generates an initializer located at `config/initializers/meta_tags.rb` which allows us to customize the way the gem works. The default settings are pretty reasonable, so we don't need to change them, at least for now.

Now, there are two important methods that we will be using, which are `display_meta_tags` and `set_meta_tags`. The former is used inside the `<head>` tag of our layouts. The latter is used in every page we want to show custom meta tags for.

So we add the following to our **application.html.erb** layout file:

```erb
<head>
  <%= display_meta_tags site: "OurSite" %>
</head>
```

This will set the `<title>` tag to display “OurSite” which is nice, but we need to fully customize the tags, and there are two main ways to do it:

### Setting meta tags in controllers
We can set `title` `description` and `keywords` meta tags in our controllers by setting the following instance variables in them:

```ruby
# app/controllers/articles_controller.b
def show
  @page_title = @article.title
  @page_description = @article.excerpt
  @page_keywords = @article.tag_list # We would need to implement this method
end
```

Or we could also use the `set_meta_tags` method to:

```ruby
# app/controllers/articles_controller.rb
def show
  set_meta_tags(
    title: @article.title,
    description: @article.excerpt,
    keywords: @article.tag_list,
  )
end
```

Using the `set_meta_tags` method can provide us with access to add more tags like canonical, noindex, and Open Graph, which we will cover further in this article.

### Setting meta tags in views
Apart from the controller, we can set meta tags in views using separate methods or passing a hash to the `set_meta_tags` method.

Using separate methods looks like this:

```erb
<% title @article.title %>
<% description @article.excerpt %>
<% keywords @article.tag_list %>
```

 While using the `set_meta_tags_method` looks like this:
 
```erb
<% set_meta_tags {title: @article.title, description: @article.excerpt, keywords: @article.tag_list} %> 
```

We can also add meta tags by implementing a method that returns a hash with the desired attributes:

```ruby
# app/models/article.rb
def to_meta_tags
  {
    title: title,
    description: excerpt
  }
end
``` 

And then, in the `show.html.erb`

```erb
<% set_meta_tags @article.to_meta_tags %>
```

Finally, either way ends up with the same results, and it's up to you which fits your application better.

I prefer to add them directly in the views, using the `set_meta_tags` method to access route helpers or stuff I would rather not include in the model.

## Open Graph tags
Open graph tags are a special kind of meta tags that implement the [Open Graph protocol,](https://ogp.me) which is a specification created by Facebook to embed web pages to display them as rich objects.

You may have seen OG tags in use when you paste a URL into some website, and it displays a preview with an image, the title, and a description:

![Enriched Open Graph preview in WhatsApp](/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MzQxLCJwdXIiOiJibG9iX2lkIn19--40650c728e8a31be4aacf16ac5ae85b86f425631/whatsapp-open-graph-rich-object.webp)

They matter because with them, we can control how these enriched previews look and thus improve our chances of users clicking on them.  

To add Open Graph tags to your Rails app with the meta tags gem, we need to add some attributes to the hash we pass to the `set_meta_tags` method:

```erb
# app/views/articles/show.html.erb
<% set_meta_tags
  {
    title: @article.title,
    description: @article.excerpt,
    og: {
      title: @article.title,
      description: @article.excerpt,
      site_name: "OurSite",
      url: article_url(@article),
      image: {
        _: url_for(@article.cover.variant(:medium)),
        width: 1200,
        height: 630
      },
      video: "https://example.com/video.mp4",
      type: "article",
      locale: "en"
    }
  }
%>
```

Some recommendations to set your Open Graph tags are:

- **Title and description:** they can be the same you use for your title and meta description. However, if you feel that changing them can improve your chances of users clicking to see your content, you could personalize them.
- **Site Name:** you can include your site's name here. It 
- **URL:** this is the canonical URL for your page. We will explore what this means later in this article, but consider it the de facto URL for your article. Say, for example, that we're adding a banner using query params; unless that's crucial for the content, we should remove the params from the URL.
- **Image:** you can use the cover URL here. However, consider that the OG image size is usually **1200×630** so take that into consideration. If your cover images have text, it might get truncated.
- **Video:** if your page contains a relevant video, you can include it here.
- **Type:** you can choose 'website' or 'article'. In your case, the latter is more relevant.
- **Locale:** if your page is localized, consider adding that to the OG tags.

## Twitter card tags
Even though Twitter is currently named "X", they have their set of meta tags under the “Twitter” name.

They behave mostly like Open Graph tags, and they help us customize the way our content is shown on Twitter/X when shared.

We can add these tags to our site in the following manner:

```erb
<% set_meta_tags {
  twitter: {
    title: @article.title,
    description: @article.excerpt,
    card: "summary || large_image || app || player",
    image: {
      _: url_for(@article.cover.variant(:medium)),
      alt: "Your image's alt text",
    }
    creator: "@author_twitter_username",
    site: "@our_sites_twitter_username",
  }
}
%>
```

- **Creator:** represents the author's username within Twitter/X.
- **Site:** represents the site or company's username within Twitter/X.
- **Card:** the type of content our Twitter card represents. You would mostly use 'summary' but there are times that the other card types could be relevant.
- **Image:** we pass the image URL with the `_` key and the image alt text in case we want it to be added when embedding our URL on X (formerly known as Twitter).

## Other important meta tags
There is a set of meta tags beyond the basics that we need to know about to optimize our site for search engines.

Some of them might be relevant for your use case, and some of them might not, but knowing about them matters because they might become relevant at some point.

Let's explore them:

- **Canonical:** it can be added using the `canonical` attribute. It represents the URL you want to be indexed and considered the single source of truth for the URL. For example, if your site redirects `www.example.com` to `example.com` your canonical URL should be `example.com`. The same applies if you use query params like `color=red` to customize content, but red is your default color. Correctly setting canonical URLs using the `<link rel="canonical">` tag is essential to avoid indexation errors.
- **No follow:** it can be added using `nofollow: true` to the tags hash. It communicates to search engines that the links within a page shouldn't pass authority to the target URLs. Adding this tag can be useful for pages you know can get manipulated by malicious actors trying to get links from your page merely for the fact of having authority passed to their sites. It adds a `<meta name="robots" content="nofollow" />` tag to the head.
- **Follow:** it tells search engines that links should pass authority. It's the default value for any page. If you set your site's links to be 'nofollow' by default, you can add this tag to specific pages that you think should pass authority when linking out.
- **No Index:** this tag tells search engines to avoid indexing the URL. The default value is set to `false` so, unless you tell them not to, search engines will index your resources whenever they can.
- **No archive:** this tag tells search engines not to cache a specific URL. You can add it using `noarchive: true` to the tags hash. It will produce a `<meta name="robots" content="noarchive"/>` tag.
- **Prev and Next:** these tags are meant to better guide search engines through your site's pagination. When you add them, you generate `<link/>` tags with the `prev` and `next` attributes that tell search engines the URLs for the previous and next pagination links. If you're on the first page of pagination, only the `next` tag should be used. If you're on the last page of pagination only the `prev` tag should be used. Otherwise, both tags should be defined. Google says they've been ignoring these tags since 2020, but you should probably add them because Bing still uses them, and official Google statements should always be taken with skepticism.

Next is an example of how we can add these tags using the **meta-tags** gem:

```ruby
{
  canonical: article_url(@article), # the de-factor URL for our resource
  nofollow: true, # links within our page won't pass authority
  noarchive: true, #our content won't be cached by search engines
  prev: article_url(@article, page: 1),
  next: article_url(@article, page: 3)
}
```
## Meta tags best practices
Adding meta tags to our application is just the first step when it comes to search engine optimization.

Actual traffic from search engines comes when create traffic-worthy content, and we follow meta tags best practices:

- **Have a keyword-centric approach to URLs:** whenever you publish a URL, try to think about the keyword the URL would be ranking for. For example, if you're writing about the “Rails asset pipeline”, you should probably include those keywords in the **title** and **description** attributes. Think something like **“A guide to the Rails Asset Pipeline”** instead of something like **“Everything I learned about the Asset Pipeline in My Journey with Ruby on Rails.”**
- **Don't obsess over the keywords tag:** this tag has been largely ignored by search engines since around 2010. Keyword stuffing this tag is not going to get you ranked. However, some sites might use this tag to classify your content, so you should provide relevant keywords for them to do so.
- **Customize your title and description tags for clicks:** many people populate their `title` and `description` using content that's shown to final users in their application. However, customizing those to improve the CTR our site gets in the search engine results page.
- **Add Open Graph and Twitter tags whenever you can:** adding tags to customize the way our content is shown when shared on social is crucial. If you can customize content for those tags, even better.
- **Think about nofollowing or noindexing content:** some parts of your site might be worthy of adding the `nofollow` or `noindex` tags. However, you should decide upon this carefully because it might take search engines some time to revert your initial decision.

## Conclusions
Adding meta tags to a Rails application is a good first step towards better search engine optimization. 

Meta tags are mostly just plain HTML, so we could add them using helpers or partials. However, using a gem can actually save us a lot of time.

In this article, we learned how to add meta tags to a Rails app using the `meta-tags` gem and what each one of those tags means, plus some best practices that can help you improve your results with search engines.

I hope it was all useful to improve your SEO game. If you have any doubts, don't hesitate to contact us!
