0
0

はじめに

この記事を読んでいる皆さんは、UAのバックアップは終わりましたでしょうか?
UAは2024/07/01以降には、完全に削除されてしまいます。

なので、それまでにデータが必要であれば、バックアップする必要があります。
今回は以下APIを使用して、データをcsvに出力することをしたので、そのアウトプットとなります。

最終的には、出力したcsvをBigQueryにインポートするまで対応しますが、アウトプットはAPIの実装のみとなります。

この記事では、プロジェクトの作成方法や認証情報の取得に関しては、解説を行いません。
あくまで、APIの実装方法がメインとなります。

前提

  • サービスアカウント認証を利用
  • 認証情報をJSONファイルは取得済み

Reporting API を利用するための準備は、以下記事を参照してください。

他サービスの検討

  • BigQueryエクスポート
  • trocco
  • スプレッドシートのアドオン

BigQueryエクスポート

有料のGAを使用していれば、直接GAのデータをBigQueryにエクスポートしてくれる機能があります。
しかも、APIなどは加工されたデータしか取得できないですが、これは生データを取得することができます。

ただ使用しなかったのは、直近13ヶ月分のデータしか取得することができず、過去のデータ全てに対応することができなかったため、早々に検討から外しました。

trocco

ETLツールで、UAのデータを直接BigQueryに入れることができるので、非常に便利だと思います。
ただ、実行時間で課金がされるので、他事業で過去〇年分まで対応する...。となると、すごいことになってしまう予想をしました。

また、後ほど注意点にも記載しますが、サンプリングもあるため、troccoも検討から外しました。

スプレッドシートのアドオン

アドオンも便利ですが、これもサンプリングが問題になるのと、サンプリングがかからない期間で取得しようとすると、すごい期間になったり、実行時間が長過ぎてしまうので、これも検討から外しました。

なので、

  • サンプリングがかからない期間(1日単位)で、データを取得することができる
  • 過去のデータも取得できる

主に、この2点でAPIしかないと判断して、実装を進めました。

実装

require 'googleauth'
require 'google/apis/analyticsreporting_v4'
require 'csv'
require 'time'

VIEW_ID = '111111111'
START_DATE = Date.parse('2018-01-01')
END_DATE = Date.parse('2018-12-31')
FORMAT_NAME = 'test'
PROPATY_NAME = 'propaty_test'
TRACKING_ID = 'UA-111111111-11'

def get_analytics_data(client, analytics, date_str, dimension, page_token = nil)
  date_range = analytics::DateRange.new(start_date: date_str, end_date: date_str)
  metric = [
    analytics::Metric.new(expression: 'ga:users', alias: 'users'),
    analytics::Metric.new(expression: 'ga:pageviews', alias: 'pageviews'),
    analytics::Metric.new(expression: 'ga:totalEvents', alias: 'total_events'),
    analytics::Metric.new(expression: 'ga:sessions', alias: 'sessions'),
    analytics::Metric.new(expression: 'ga:bounceRate', alias: 'bounce_rate'),
    analytics::Metric.new(expression: 'ga:exitRate', alias: 'exit_rate'),
    analytics::Metric.new(expression: 'ga:timeOnPage', alias: 'time_on_page'),
    analytics::Metric.new(expression: 'ga:newUsers', alias: 'new_users')
  ]
  report_request = analytics::ReportRequest.new(
    view_id: VIEW_ID, metrics: metric, dimensions: dimension, date_ranges: [date_range], page_size: 100000
  )
  report_request.page_token = page_token if page_token

  request = analytics::GetReportsRequest.new(report_requests: [report_request])
  client.batch_get_reports(request)
end

# CSV output
def save_to_csv(all_rows, response, date_str)
  filename = "#{VIEW_ID}/analytics_data_#{date_str}_#{FORMAT_NAME}.csv"
  dimension_header = response.reports.first.column_header.dimensions

  CSV.open(filename, 'w', force_quotes: true) do |csv|
    header = ['property_name', 'tracking_id', 'view_id'] + dimension_header + response.reports.first.column_header.metric_header.metric_header_entries.map { |entry| entry.name }
    csv << header

    all_rows.each do |row|
      dimensions = row.dimensions
      metrics = row.metrics.first.values

      csv << [PROPATY_NAME, TRACKING_ID, VIEW_ID] + dimensions + metrics
    end
  end

  puts "データが #{filename} に保存されました。"
end

# 実行開始時刻を記録
start_time = Time.now

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('test-analysis-abc123456789.json'),
  scope: scope
)

# 実行回数をカウントする変数
total_execution_count = 0
execution_count = 0

sleep_time = 30
execution_limit = 95
# 各日付ごとにデータを取得しCSVに保存
(START_DATE..END_DATE).each do |date|
  # 日付の文字列変換
  date_str = date.strftime('%Y-%m-%d')

  original_dimension = [
    analytics::Dimension.new(name: 'ga:date'),
    analytics::Dimension.new(name: 'ga:deviceCategory'),
    analytics::Dimension.new(name: 'ga:pagePath'),
    analytics::Dimension.new(name: 'ga:sourceMedium'),
    analytics::Dimension.new(name: 'ga:landingPagePath')
  ]

  client_dimension = [
    analytics::Dimension.new(name: 'ga:dimension27')
  ]

  dimension = original_dimension + client_dimension

  # データ取得
  response = get_analytics_data(client, analytics, date_str, dimension)

  all_rows = response.reports.first.data.rows
  puts response.reports.first.data.row_count

  while response.reports.first.next_page_token
    next_page_token = response.reports.first.next_page_token
    next_response = get_analytics_data(client, analytics, next_page_token)
    all_rows.concat(next_response.reports.first.data.rows)
    response = next_response
  end

  # データをCSVに保存
  save_to_csv(all_rows, response, date_str) unless all_rows.nil?
end

# 実行終了時刻を記録
end_time = Time.now
execution_time = end_time - start_time
puts "プログラムの実行時間: #{execution_time} 秒"

ディレクトリ構成

- VIEW_ID(フォルダ)
    - この配下にcsvが出力される
- script.rb
- test-analysis-abc123456789.json

環境

  • ruby:3.2.2
  • Gem:google-api-client
    • 3.4.10
gem install google-api-client

解説

複数のプロパティ・ビューを取得したい場合、主に定数を変更するだけで良いようにしています。

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

上記で認証を行っています。
このrubyファイルと同じディレクトリに、事前に作成したjsonファイルを置いていただければ、問題ございません。

report_request = analytics::ReportRequest.new(
  view_id: VIEW_ID, metrics: metric, dimensions: dimension, date_ranges: [date_range], page_size: 100000
)
report_request.page_token = page_token if page_token

APIは、最大行数を超えると、別ページとなり、再度リクエストを送らないと取得することができません。
今回は、page_size: 100000としているので、この行よりも多く返ってきてしまった場合も、もう一度リクエストを走らせて取得できるよう実装しています。

あとは、利用制限を気をつけつつ、メトリクス・ディメンションを設定していただければ、csvに出力できるかなと思います。

注意点

1日の利用制限

利用制限を超えてしまうと、データが取得できなかったり、エラーになってしまいます。
ここはしっかり読んで、把握しておきましょう。

サンプリングがかかってしまう

長い期間を設定して、一気にデータを取得しようとすると、GA側で全てのデータの中からある程度のデータで計算されてしまう仕様がサンプリングになります。
そのため、1年間を一気に取得しようとすると、1日ずつ取得したデータと差異を生じることがあります。

なので、1日ずつ取得するよう、APIは実装しています。

まとめ

データを取得するだけですが、考慮しないといけない点が多く、とても時間がかかる作業です。
今回アウトプットした実装を例に、皆様がやりやすいように修正して、使っていただけたら幸いです。

最後までご覧いただき、ありがとうございました。

0
0
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
0
0