17
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

東京理科大学Advent Calendar 2018

Day 22

Google Analyticsを使って記事ランキング機能を実装する

Last updated at Posted at 2018-12-28

この記事は東京理科大学 Advent Calendar 2017 12/28の記事です。嘘です。22日の記事です。
つまり遅刻しています。年を越さなくてよかったです。

はじめに

自身のブログなどで記事人気ランキングを表示したい……。でも実装が面倒……。みたいなことはありませんか?
今回はruby on rails上でGoogle Analyticsを利用してランキング機能を実装してみます。

注)実際に用いたコードから省略して記載しているので動作しない等あれば指摘お願いします。

環境

ruby 2.5.1
rails 5.2.1

Google Analyticsを導入する

まずウェブアプリにGoogle Analyticsを導入しておいてください。Google Analyticsではpageview(ページアクセス数)とuniqpageview(ページにアクセスしたセッション数)を記録しているので、これを利用して記事ランキング機能を実装します。
タグを埋め込んで導入する、gemによって導入するなどの方法がありますがどれでも構いません。導入方法は割愛します。

APIの認証情報を用意する

現在(2018/12)の最新はv4なので、v4のapiを利用していきます。

[APIのページ](https://console.developers.google.com/projectselector/Google AnalyticsAPIs/dashboard)にアクセスしてプロジェクトを選択します。
プロジェクトを作成していない場合は作成するよう言われるので作っておいてください。

APIとサービスの有効化よりanalyticsと検索してGoogle Analytics Reporting APIを選択してください。Reporting APIとなっているものはv3のAPIなので利用しません。
image.png

有効にするを押します。
image.png

「認証情報を作成」ボタンが出てくるのでこれを押します。
image.png
認証情報の入力に移ります。
image.png
image.png

以上のように入力して認証情報を作成します。

作成すると認証用のjsonがダウンロードされるので紛失しないよう管理しておいてください。

さて、このままrailsから認証を行おうとしても
Error - #<Google::Apis::ClientError: forbidden: User does not have any Google Analytics account.>
となり怒られてしまいます。
これは、先程作成したアカウントとGoogle Analyticsのアカウントが紐ついてないためです。

Google Analyticsのページから左下から管理に移動してアカウント、プロパティ、ビューのいずれかのユーザー管理者の設定に移って新しくアカウントを登録します。
image.png

先程ダウンロードしたjsonファイルの中身を見てclient_emailに記述されているメールアドレスを入力します。権限は表示と分析のみで構いません。
image.png

以上で認証情報の用意は終了です。

Google AnalyticsAPIを利用してgoogleanalyticsに接続する

googleではGoogle AnalyticsAPIの認証が共通なのでGemfileに以下のgemを追加します。

gem 'google-api-client'

ネットで情報を集める際はv3でなくv4のAPIで認証を行うことに注意してください。

認証を行うコードを実装します。
rails5ではapp以下が自動で読み込まれるのでapp/lib以下にファイルを追加するのが良いかと思います。

require 'google/apis/analyticsreporting_v4'

class Analytics
  def initialize(view_id)
    @view_id  = view_id
    scope = 'https://www.googleapis.com/auth/analytics.readonly'
    json_path = Rails.root.join("app", "lib", "analytics.json") //任意の場所にjsonファイルを配置

    @analytics = Google::Apis::AnalyticsreportingV4
    @client = @analytics::AnalyticsReportingService.new
    @client.authorization = Google::Auth::ServiceAccountCredentials.make_creds(
      json_key_io: File.open(json_path),
      scope: scope
    )
  end
end

先程のjsonファイルを任意の場所に配置し、読み込んで認証を行います。

reportを作成してデータを取得する

参考:Reporting API v4 デベロッパー ガイド

先程と同じファイルにレポートを作成する関数を実装します。

class Analytics
  def initialize(view_id)
    ...
  end

  def get_uniq_pageview(start_date='2005-01-01', end_date='today')
    date_range = @analytics::DateRange.new(start_date: start_date, end_date: end_date)
    metric     = @analytics::Metric.new(expression: 'ga:uniquePageviews', alias: 'uniquePageviews')
    dimension  = @analytics::Dimension.new(name: 'ga:pagePath')
    order_by   = @analytics::OrderBy.new(field_name: 'ga:uniquePageviews', sort_order: 'DESCENDING')
    dimension_filters = @analytics::DimensionFilterClause.new(
      filters: [
        @analytics::DimensionFilter.new(
          dimension_name: 'ga:pagePath',
          expressions: ['^/article/\w{20}']
        )
      ]
    )

    report_request = @analytics::GetReportsRequest.new(
      report_requests: [
        @analytics::ReportRequest.new(
          view_id: @view_id,
          metrics: [metric],
          date_ranges: [date_range],
          dimension_filter_clauses: [dimension_filters],
          dimensions: [dimension],
          order_bys: [order_by],
        )
      ]
    )

    response = @client.batch_get_reports(report_request)
    data = response.reports.first.data

    pageview = data.rows&.map{ |row| [ row.dimensions.first.slice(/\w+{20}/), row.metrics.first.values.first ] }.to_h
    return pageview
  end
end

daterangeの日付はISO8601の日付形式です。またtoday、yesterdayなどの表現も利用できます。おそらくadword Google AnalyticsAPIで利用できる表現と同様と思います。

また、filterで期待するデータを絞ることができます。
参考:メソッド: reports.batchGet
今回は記事のページ以外のデータは必要ないのでDimensionFilterClauseで記事のurlを正規表現でフィルタしています。この場合は/article/{20文字の英数字}にマッチします。

時間帯を更に細かく絞りたい場合はfilterで時間関連の指標を絞り込むといいと思います。
他にも色々と表現できるのでdocumentを参照してください。

APIのテストは ここ から簡単に試せるのでやってみてください。

また、デフォルトでは一度のリクエストで1000件までの取得なのでそれを超える場合はページの切り替え処理をする必要があります。

記事にview数を保存するタスクを作成する

アクセス毎にAPIを叩くわけには行かないのでタスク化して定期実行しDBにデータを持つようにします。
まずview数を保存するためのカラムを追加します。

rails g migration add_day_pageview_to_article

migrationファイルは以下のようにしました。

class AddDayPageviewToArticle < ActiveRecord::Migration[5.2]
  def change
    add_column :articles, :day_pageview, :integer, null: false, default: 0
  end
end

これでテーブルにday_pageviewカラムが追加されます。

更に、taskを作成します。

$ rails g task analytics

lib/tasks/以下にファイルが生成されるので編集していきます。
先程書いたクラスを使ってデータを読み込んで保存します。

namespace :analytics do
  desc 'import day uniq view'
  task :update_day_pageview_from_ga => :environment do

    view_id = ENV['GOOGLE_ANALYTICS_VIEW_ID']
    ga = Analytics.new(view_id)
    report = ga.get_uniq_pageview('yesterdat', 'yesterdat')

    pageview = Article.ids.map{|m| [m, 0]}.to_h
    pageview.merge(report)

    ActiveRecord::Base.transaction do
      pageview.each do |k, v|
        if article = Article.find(k)
          article.update!(day_pageview: v)
        end
      end
    end

    Rails.logger.info '閲覧数を更新しました'
  rescue => e
    Rails.logger.error '閲覧数更新に失敗しました'
    Rails.logger.error e.backtrace.join("\n")
  end
end

単純にデータを取ってきて保存するだけです。ga.get_uniq_pageview('yesterdat', 'yesterdat')の引数を変更すれば全期間や今月などの指定もできます。
実際には保存の部分はactiverecord-importでbulk insertしたほうがいいかもしれません。

ここでのview_idはGoogle AnalyticsのビューIDです。
image.png
先ほどの管理のページからビューの設定にいけば確認することができます。

wheneverでタスクを定期実行する

wheneverというgemでcronを管理します。

gem 'whenever', require: false

初期設定を入れます。

wheneverize

詳しい使い方は割愛します。
config/schedule.rbに以下を追記します。

every 1.day, at: '0:10 am' do
  rake "rails analytics:update_day_pageview_from_ga"
end

これで毎日0:10分に前日のアクセス数が更新されます。
以下のコマンドでバッチ処理させるサーバにcrontabを反映します。

bundle e whenever -i

crontabの内容は以下のコマンドで確認できます。

crontab -l

利用する

後は、

@articles = Article.all.order(day_pageview: :desc)

などのように利用できます。

あとがき

Google Analyticsを利用することで簡単にアクセス数を取得できました。特にセッション数などは実装が面倒なのでそれがないだけで大分楽だと思います。

東京理科大学 Advent Calendarということで告知を。コミックマーケット95 2日目(日) 12/30 タ36a で東京理科大学葛飾電気工学同好会(EIC)の会誌を頒布します。電気街電子部品価格比較とか書いてます。興味あればぜひおこしください!

17
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?