[Ruby] GoogleアナリティクスAPIでレポートを取得する

概要

RubyでGoogle アナリティクス Reporting API v4を利用して、集計情報を取得する。

本記事では、本日のページごとのアクセス数(ユーザ数)を集計し、それをチャットワークで通知するスクリプトを作成する。

前提

以下環境で動作確認済み

要素 バージョン
debian 8.6
ruby 2.2.2
google-api-client 0.15.0

ざっくりと用語確認

具体的なコード例を示す前に、ざっくりとGoogleアナリティクス及びコード中に出現するワードについて確認する。

プロジェクト

Google関連サービスに関する、API管理、リソース管理、課金管理などを束ねる単位。とりあえず個人で遊ぶ分には、MyProjectとか適当に作っておけばよい。本記事の内容は全て無料で、課金が必要な操作は一切しない。

サービスアカウント

通常のGoogleアカウントとは異なる、Googleのサービスを利用するアプリケーションや仮想マシンに紐づく特殊なアカウント。本記事内では、APIを利用するためのユーザと捉えれば良い。

ビューID

Googleアナリティクスにおける、集計対象のサイトのユニークなID

メトリック(metric)

集計する対象データの種別。Googleアナリティクスのトップ画面だと以下のようなものが確認できる。

  • ユーザ数
  • セッション数
  • ページビュー数
  • 平均セッション時間
  • 直帰率

メトリックは他にも数多くのものがあり、眺めてると「こんな集計方法もあるのか」とワクワクする。
Dimensions & Metrics Explorer

API利用時は、どんなデータが欲しいか(ユーザ数が欲しい、直帰率が欲しい)などを、メトリックで指定する。

ディメンション(dimension)

ディメンションは、条件ごとのメトリックを集計するための仕組み。
例えばディメンションをga:browser(ブラウザ)に、メトリックをga:sessions(セッション数)に指定してレポートを作成すると、ブラウザごとのセッション数の集計を行うことができる。

本記事ではページごとのユーザ数を集計するので、メトリックにユーザ数を、ディメンションにページパスを指定する。

GoogleアナリティクスAPIの準備

GoogleアナリティクスAPIを利用する準備として、以下の作業を行う必要がある

  • プロジェクトの作成
  • サービスアカウントの作成
  • Googleアナリティクスにユーザを追加
  • ビューIDの確認

以上については、以下記事が非常に参考になったので、本記事ではそのままリンクを貼るだけにする。

Google Analytics API を叩いてデータを取得するまでの流れ(Ruby)

実装

とりあえずAPIを使ってみる

GoogleアナリティクスAPIを使うためのgemをインストールする。以下は各種GoogleサービスのAPIの共通のもの。

$ gem install google-api-client

おもむろに以下コードを実行すると

require 'pp'
require 'google/apis/analyticsreporting_v4'

view_id = '158527891'
scope = ['https://www.googleapis.com/auth/analytics.readonly']
analytics =Google::Apis::AnalyticsreportingV4

client = analytics::AnalyticsReportingService.new
client.authorization = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open('auth.json'),
  scope: scope
)

date_range = analytics::DateRange.new(start_date: '7DaysAgo', end_date: 'today')
metric = analytics::Metric.new(expression: 'ga:sessions', alias: 'sessions')
dimension = analytics::Dimension.new(name: 'ga:browser')
request = analytics::GetReportsRequest.new(
  report_requests: [analytics::ReportRequest.new(
    view_id: view_id, metrics: [metric], dimensions: [dimension], date_ranges: [date_range]
  )]
)
response = client.batch_get_reports(request)

pp response.reports

以下のような実行結果が得られる

vagrant$ bundle exec ruby hoge.rb
[#<Google::Apis::AnalyticsreportingV4::Report:0x007f8216df28f8
  @column_header=
   #<Google::Apis::AnalyticsreportingV4::ColumnHeader:0x007f8216df1598
    @dimensions=["ga:browser"],
    @metric_header=
     #<Google::Apis::AnalyticsreportingV4::MetricHeader:0x007f8216de2a98
      @metric_header_entries=
       [#<Google::Apis::AnalyticsreportingV4::MetricHeaderEntry:0x007f8216de10d0
         @name="sessions",
         @type="INTEGER">]>>,
  @data=
   #<Google::Apis::AnalyticsreportingV4::ReportData:0x007f8216dd8700
    @maximums=
     [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216dcdc10
       @values=["355"]>],
    @minimums=
     [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216dc94d0
       @values=["1"]>],
    @row_count=9,
    @rows=
     [#<Google::Apis::AnalyticsreportingV4::ReportRow:0x007f8216dc5b00
       @dimensions=["Android Webview"],
       @metrics=
        [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216dc24f0
          @values=["1"]>]>,
      #<Google::Apis::AnalyticsreportingV4::ReportRow:0x007f8216dc0178
       @dimensions=["Chrome"],
       @metrics=
        [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216dbdea0
          @values=["355"]>]>,
      #<Google::Apis::AnalyticsreportingV4::ReportRow:0x007f8216dbbd08
       @dimensions=["Edge"],
       @metrics=
        [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216db92d8
          @values=["5"]>]>,
      #<Google::Apis::AnalyticsreportingV4::ReportRow:0x007f8216db6e70
       @dimensions=["Firefox"],
       @metrics=
        [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216db50e8
          @values=["39"]>]>,
      #<Google::Apis::AnalyticsreportingV4::ReportRow:0x007f8216db2e10
       @dimensions=["Internet Explorer"],
       @metrics=
        [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216db0b60
          @values=["32"]>]>,
      #<Google::Apis::AnalyticsreportingV4::ReportRow:0x007f8216dae9a0
       @dimensions=["Opera"],
       @metrics=
        [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216dacba0
          @values=["1"]>]>,
      #<Google::Apis::AnalyticsreportingV4::ReportRow:0x007f8216daad78
       @dimensions=["Safari"],
       @metrics=
        [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216da8e38
          @values=["101"]>]>,
      #<Google::Apis::AnalyticsreportingV4::ReportRow:0x007f8216da7308
       @dimensions=["Safari (in-app)"],
       @metrics=
        [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216da46d0
          @values=["7"]>]>,
      #<Google::Apis::AnalyticsreportingV4::ReportRow:0x007f8216da2718
       @dimensions=["Samsung Internet"],
       @metrics=
        [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216da0440
          @values=["2"]>]>],
    @totals=
     [#<Google::Apis::AnalyticsreportingV4::DateRangeValues:0x007f8216d9b710
       @values=["543"]>]>>]

上記は、直近1週間のブラウザ別セッション数を集計した結果である。

実行結果をよく見ると、トータルセッション数が543で、例えばInternet Explorerからのセッション数が32であることが確認できる。

GoogleアナリティクスAPIでは、複数のレポートをまとめて生成できたり、個々のレポートについて複数のメトリクス、複数のディメンションを指定できたりするため、深い階層構造になって読みづらくなってしまうのは仕方ない。

コード解説

レポート作成対象のビューIDを定義しておく

view_id = '158527891'

次に、GoogleアナリティクスAPIの認証を受けて、利用できる状態にする。認証には、秘密鍵を含んだJSONファイルを指定する必要がある。ここでは同ディレクトリにauth.jsonというファイルを設置している。

scope = ['https://www.googleapis.com/auth/analytics.readonly']
analytics =Google::Apis::AnalyticsreportingV4
 
client = analytics::AnalyticsReportingService.new
client.authorization = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open('auth.json'),
  scope: scope
)

レポートの集計範囲を指定する。start_date及びend_dateには、日付文字列を入れることも出来るが、下記のように7DaysAgoや、todayと言った相対日時を指定することも出来る。

date_range = analytics::DateRange.new(start_date: '7DaysAgo', end_date: 'today')

メトリックを指定する。今回はセッション別にするので、ga:sessionsを指定する。aliasはデータ取得時のキーになるのでわかりやすいものを振っておく。
指定できるメトリックはこちらを参照

metric = analytics::Metric.new(expression: 'ga:sessions', alias: 'sessions')

ディメンションを指定する。ブラウザ別のセッション数を得るために、ここではga:browserを指定してる。
指定できるディメンションはこちらを参照

dimension = analytics::Dimension.new(name: 'ga:browser')

定義したビューID、期間、メトリック、ディメンションを用いて、APIリクエストを生成する。それぞれを配列で渡しているのを見て分かる通り、これらは複数指定することができ、より柔軟な集計を行うことができる。

request = analytics::GetReportsRequest.new(
  report_requests: [analytics::ReportRequest.new(
    view_id: view_id, metrics: [metric], dimensions: [dimension], date_ranges: [date_range]
  )]
)

APIを実行して結果を出力する

response = client.batch_get_reports(request)
pp response.reports

本日のページ別ビュー数を取得する

次に、前項のコードを一部修正して、本来の目的である「本日のページ別ユーザ数」を取得する。

まず、ページごとのフルパスを表示したいので、BASE_URL(このブログ)を定義しておく。

BASE_URL = "http://qs.nndo.jp"

期間を本日のみにする。start_dateとend_dateをどちらもtodayにすれば良い

date_range = analytics::DateRange.new(start_date: 'today', end_date: 'today')

メトリックをユーザに変更する

metric = analytics::Metric.new(expression: 'ga:users', alias: 'users')

ディメンションはページパス別にする

dimension = analytics::Dimension.new(name: 'ga:pagePath')

前項のサンプルには出てこなかったが、ソート順も以下のように指定できるので、メトリックを指定して、降順になるようにする。

order_by = analytics::OrderBy.new(field_name: 'ga:users', sort_order: 'DESCENDING')

レポートを取得。変更点はソート順の指定が追加された部分のみ。

request = analytics::GetReportsRequest.new(
  report_requests: [analytics::ReportRequest.new(
    view_id: view_id,
    metrics: [metric],
    date_ranges: [date_range],
    dimensions: [dimension],
    order_bys: [order_by],
  )]
)
response = client.batch_get_reports(request)

いい感じに整形して出力する

data = response.reports.first.data
puts "累計ユーザ数: #{data.totals.first.values.first}"
data.rows.each do |row|
  puts "#{row.metrics.first.values.first}: #{BASE_URL + row.dimensions.first}"
end

実行すると以下のようにいい感じに出力される。ユーザ数少ない。

累計ユーザ数: 37
9: http://qs.nndo.jp/qiita-posts-3
3: http://qs.nndo.jp/2017/03/30/401/
3: http://qs.nndo.jp/2017/05/21/544/
2: http://qs.nndo.jp/
2: http://qs.nndo.jp/2017/02/27/298/
1: http://qs.nndo.jp/?p=1081&preview=true
1: http://qs.nndo.jp/2017/01/28/106/
1: http://qs.nndo.jp/2017/02/05/148/
1: http://qs.nndo.jp/2017/02/16/234/
1: http://qs.nndo.jp/2017/04/09/424/
1: http://qs.nndo.jp/2017/04/18/440/
1: http://qs.nndo.jp/2017/05/03/494/
1: http://qs.nndo.jp/2017/05/14/531/
1: http://qs.nndo.jp/2017/08/14/658/
1: http://qs.nndo.jp/2017/08/21/681/
1: http://qs.nndo.jp/2017/09/09/809/
1: http://qs.nndo.jp/2017/09/10/819/
1: http://qs.nndo.jp/2017/09/15/838/
1: http://qs.nndo.jp/2017/09/16/849/
1: http://qs.nndo.jp/2017/10/01/906/
1: http://qs.nndo.jp/export-backlog-issues
1: http://qs.nndo.jp/use-google-analytics-api-by-ruby?preview=true
1: http://qs.nndo.jp/use-payjp-by-ruby

クラス化して拡張しやすくする

ここまでは1つのファイルにダラダラとコードを書いてきたので、今後別の集計方法を定義する場合も容易に拡張できるように、以下のようにクラス化する。
Analyticsクラスは、レポート対象のサイトURLと、そのビューIDを指定してオブジェクトを生成する。後は実装したレポート生成メソッドを随時呼び出すだけ。

require 'google/apis/analyticsreporting_v4'

class Analytics

  #
  # レポート対象を指定してオブジェクトを生成
  # @param [String] base_url  レポート対象サイトのURL
  # @param [String] view_id   ビューID
  #
  def initialize(base_url, view_id)
    @base_url = base_url
    @view_id  = view_id
    @analytics = Google::Apis::AnalyticsreportingV4
    auth
  end

  #
  # 指定した日のページごとのユーザ数を集計する
  # @param  [String] date 日付を表す文字列(todayなども可)
  # @return [Hash]   累計ユーザ数及びページごとのユーザ数
  #
  def report_users_count_by_date(date)
    date_range = @analytics::DateRange.new(start_date: date, end_date: date)
    metric = @analytics::Metric.new(expression: 'ga:users', alias: 'users')
    dimension = @analytics::Dimension.new(name: 'ga:pagePath')
    order_by = @analytics::OrderBy.new(field_name: 'ga:users', sort_order: 'DESCENDING')
    request = @analytics::GetReportsRequest.new(
      report_requests: [@analytics::ReportRequest.new(
        view_id: @view_id,
        metrics: [metric],
        date_ranges: [date_range],
        dimensions: [dimension],
        order_bys: [order_by],
      )]
    )
    response = @client.batch_get_reports(request)
    data = response.reports.first.data
    return {
      total: data.totals.first.values.first,
      pages: data.rows.map do |row|
        {
          url: @base_url + row.dimensions.first,
          views: row.metrics.first.values.first
        }
      end
    }
  end

  private

    #
    # GoogleアナリティクスAPIに認証する
    # 同ディレクトリにauth.jsonを配置すること
    #
    def auth
      scope = ['https://www.googleapis.com/auth/analytics.readonly']
      @client = @analytics::AnalyticsReportingService.new
      @client.authorization = Google::Auth::ServiceAccountCredentials.make_creds(
        json_key_io: File.open('auth.json'),
        scope: scope
      )
    end

end

集計結果をチャットワークで通知する

ここからはオマケ。チャットワークAPIを用いて、本日のページ別ユーザ数をチャットワークに通知する。

チャットワークAPIの利用には、手前味噌のchatworkクラスを用いる。詳細は以下記事参照。
チャットワークAPIをRubyで利用する

前項のAnalyticsクラスと、上記Chatworkクラスを用いて、集計結果をチャットワークに通知するスクリプトは以下の通り。

require_relative './analytics'
require_relative './chatwork'

# ページ別ユーザ数をGoogleアナリティクスから取得
BASE_URL = "http://qs.nndo.jp"
view_id = '158527891'
analitics = Analytics.new(BASE_URL, view_id)
report = analitics.report_users_count_by_date('today')

# 結果を整形してチャットワークに通知
chatwork = Chatwork.new(ENV['CHATWORKAPI'])
room_id  = '59255776'
chatwork.sendMessage(room_id, <<EOS
累計 #{report[:total]}
#{report[:pages].map {|page| "#{page[:views]}: #{page[:url]}"}.join("\n")}
EOS
)

実行すると、以下のようにチャットワークに集計結果が投稿される。

ソースコード(Github)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です