この記事は東京理科大学 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なので利用しません。
「認証情報を作成」ボタンが出てくるのでこれを押します。
認証情報の入力に移ります。
以上のように入力して認証情報を作成します。
作成すると認証用のjsonがダウンロードされるので紛失しないよう管理しておいてください。
さて、このままrailsから認証を行おうとしても
Error - #<Google::Apis::ClientError: forbidden: User does not have any Google Analytics account.>
となり怒られてしまいます。
これは、先程作成したアカウントとGoogle Analyticsのアカウントが紐ついてないためです。
Google Analyticsのページから左下から管理に移動してアカウント、プロパティ、ビューのいずれかのユーザー管理者の設定に移って新しくアカウントを登録します。
先程ダウンロードしたjsonファイルの中身を見てclient_email
に記述されているメールアドレスを入力します。権限は表示と分析のみで構いません。
以上で認証情報の用意は終了です。
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です。
先ほどの管理のページからビューの設定にいけば確認することができます。
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)の会誌を頒布します。電気街電子部品価格比較とか書いてます。興味あればぜひおこしください!