Railsのmeta設定とOGP量産


# meta設定

meta設定はだいたい[Settings](https://github.com/binarylogic/settingslogic)か[Global](https://github.com/railsware/global)を使う

## デフォルトのレイアウトをつくる

https://github.com/kpumuk/meta-tags gem をインストールする

```slim:app/views/layouts/application.html.slim
doctype html
html
  head
    = render partial: 'layouts/meta_tags'
    = stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true
    = javascript_include_tag 'application', 'data-turbolinks-track' => true
    = csrf_meta_tags

  body
    = yield
```

## metaタグのpartialをつくる

meta-tagsのgemでカバーしていないmetaタグをざっと書いていく。
最後に `display_meta_tags(default_meta_tags)` というメソッドでデフォルトのmetaタグを呼び出す。

```slim:app/views/layouts/_meta_tags.html.slim
meta(content='NOYDIR' name='ROBOTS')
meta(content='NOODP' name='ROBOTS')
link(media='handheld' rel='alternate')

meta(name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, shrink-to-fit=no")
meta(property="fb:app_id" content=Settings.site.meta.fb.app_id)

/ IEで「互換モード」で表示されるのを防ぐための指定
meta(http-equiv="X-UA-Compatible" content="IE=Edge")

/ webclip icon
meta(name="apple-mobile-web-app-capable" content='yes')
meta(name="apple-mobile-web-app-status-bar-style" content='default')
link(rel="apple-touch-icon" href=Settings.site.meta.webclipicon)

- if noindex?
  - set_meta_tags noindex: true, nofollow: true

= display_meta_tags(default_meta_tags)
```

## default_meta_tagsメソッド

`@page_title` などの変数の上書きがなければ、
その後に続く値 `@page_title || 'xxx'` をデフォルトでセットする。

```ruby:app/helpers/application_helper.rb
module ApplicationHelper

  def default_meta_tags
    {
      charset: 'utf-8',
      site: Settings.site.name,
      reverse: true,
      title: @page_title || Settings.site.meta.title,
      description: @page_description || Settings.site.meta.description,
      keywords: @page_keywords || Settings.site.meta.keywords,
      canonical: url_for(only_path: false, protocol: 'https'),
      icon: Settings.site.meta.favicon,
      og: default_og,
      twitter: default_twitter
    }
  end

  def default_og
    return if noindex?
    {
      title: @og_title || Settings.site.meta.og.title, # :title
      description: @og_description || Settings.site.meta.og.description, # :description
      type: Settings.site.meta.og.type,
      url: :canonical,
      image: page_og_image,
      site_name: Settings.site.name,
      locale: 'ja_JP'
    }
  end

  def page_og_image
    @page_image || image_url(Settings.site.meta.og.image)
  end

  def default_twitter
    return if noindex?
    {
      card: "summary_large_image",
      title: @twitter_title || Settings.site.meta.twitter.title,
      description: @twitter_description || Settings.site.meta.twitter.description,
      image: page_twitter_image
    }
  end

  def page_twitter_image
    @page_image || image_url(Settings.site.meta.twitter.image)
  end

  def noindex?
  end

end
```

## settingslogic

上記で出てきた `Settings` を使えるようにする
https://github.com/binarylogic/settingslogic gem をインストールする
読み込むymlファイルのパスを設定

```ruby:app/models/settings.rb
class Settings < Settingslogic
  source "#{Rails.root}/config/application.yml"
  namespace Rails.env
end
```

## application.ymlで全体の情報を管理

基本的にこの一箇所にすべてまとめておきたい

```yml:config/application.yml
defaults: &defaults

  # 全体ページ
  site:
    name: site name
    root_url: https://sample.com
    meta:
      title: page title
      description: description
      keywords: sample1, sample2, sample3
      webclipicon: /webclipicon.png
      favicon: /favicon.ico
      fb:
        app_id: 9999999999
      og:
        title: page title
        description: og description
        image: /img/ogp.png
        type: website
      twitter:
        title: page title
        description: twitter description
        image: /img/ogp.png
    sns_account:
      twitter: https://twitter.com/sample
      instagram: https://www.instagram.com/sample

  # 個別ページ
  about:
    meta:
      title: about page
      description: about description
      keywords: about1, about2, about3

  # 複数OGP
  ogp:
    - index: 1
      title: ogp1 title
      description: ogp1 description
      share_description: ogp1 share_description
    - index: 2
      title: ogp2 title
      description: ogp2 description
      share_description: ogp2 share_description
    - index: 3
      title: ogp3 title
      description: ogp3 description
      share_description: ogp3 share_description

  # share
  share:
    twitter:
      text: |-
        description
        #hashtag description
      hashtags: hashtag1, hashtag2
    line:
      text: |-
        description
        description

development:
  <<: *defaults

test:
  <<: *defaults

production:
  <<: *defaults
```

## トップページ以外でも表示してみる

タイトル、ディスクリプション、キーワードが変更される

```slim:app/views/site/about.html.slim
- @page_title = Settings.about.meta.title
- @page_description = Settings.about.meta.description
- @page_keywords = Settings.about.meta.keywords

h1 Site#about
p Find me in app/views/site/about.html.slim
```

# OGP量産

商品ごとにOGPを変える必要があるときなどを想定

## ルーティング

ogp/にアクセスがあったら「show」アクションのみを呼ぶ

```ruby:config/routes.rb
Rails.application.routes.draw do
  resources :ogp, :only => [:show]
end
```

## コントローラでymlから個別ページの情報のみを取得

配列形式で書いてあるymlから、indexが合致したOGP情報だけを取得する

```ruby:app/controllers/ogp_controller.rb
class OgpController < ApplicationController
  def show
    @root_url = url_for("http://"+request.host_with_port+"/")
    @ogp = Settings.ogp.find { |h| h['index'] == params[:id].to_i }
  end
end
```

## レイアウトをつくる

自動的に `application.html.slim` のレイアウトを読みにいってしまうため、OGP用に簡素にしたレイアウトを置いておく。

```slim:app/views/layouts/ogp.html.slim
doctype html
html
  head
    = render partial: 'layouts/meta_tags'
  body
    = yield
```

## viewで個別ページを生成

このページ自体は個別のmeta情報を持たせるだけで
表示される必要はないのでルートディレクトリにリダイレクト

```slim:app/views/ogp/show.html.slim
- @page_title = "#{@ogp["index"]}"
- @page_description = "#{@ogp["description"]}"
- @page_image = "#{@root_url}img/ogp/#{@ogp["index"]}.png"

javascript:
  window.location = '/';
```