rcmdnk's blog
Last update

Analytics: Data Science, Data Analysis and Predictive Analytics for Business (Algorithms, Business Intelligence, Statistical Analysis, Decision Analysis, ... Data Mining, Big Data) (English Edition)

GoogleのRuby用APIライブラリの google-api-ruby-client がアップデートされ、 ちょっと仕様が変更されていたのでそれについて。

Sponsored Links

Google API Clientのアップデート

GoogleのAPIを色々使うためのRuby用ライブラリですが、 これまで0.8.6だったバージョンが0.9にアップデートされ、 それらの間で互換性が無いのでちょっと問題が起こりました。

このOctopressのサイトではビルド時にページビュー数を取ってきて リストを作ったりしてますが、 その際にAnalyticsのAPIを使っています。

以下のプラグインを使っています。

この中で

1
require 'google/api_client'

を使ってますが、これが0.9ではなくなっています。

0.9では

1
require 'google/apis/analytics_v3'

みたいな感じで各サービスごとに読み込む様になっています。 書くサービスの名前やバージョンは以下のディレクトリを見ることで分かります。

google-api-ruby-client/generated/google/apis at master · google/google-api-ruby-client

また、認証の仕方にはAPI Keyを用いていましたが、 今後、googleauth というOAuth 2.0認証を使った方法に変えていくべきだ、とのこと がIssueで言われています。

Missing loading pkcs keys · Issue #252 · google/google-api-ruby-client

ただ、今のところ、取り敢えずAPI Keyを使うためのKeyUtilsが残される事になったので、

1
require 'google/api_client/auth/key_utils'

を読み込むことで今までのようにAPI Keyを使って

1
2
3
4
5
6
7
8
key = Google::APIClient::KeyUtils.load_from_pkcs12(pv['key_file'], pv['key_secret'])
client.authorization = Signet::OAuth2::Client.new(
  :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
  :audience => 'https://accounts.google.com/o/oauth2/token',
  :scope => 'https://www.googleapis.com/auth/analytics.readonly',
  :issuer => pv['service_account_email'],
  :signing_key => key)
...

みたいな事をすることは出来ます。

OAuth 2.0だとUIが必要なので、werckerに投げてそこで実行、的な事は出来ません。

なので、ローカルで認証して認証情報ファイル自体をBitbucket等に送る事も出来ない わけではないですが、認証が切れる度に手動で行わなくてはならないし、 そもそもそのようなファイルを送るならAPI Keyで良いと。

ということで取り敢えずサポートされてる間はAPI Keyを使った形で使っていきます。

使っている octopress-page-view という中のプラグインの変更は以下の様な感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 require 'jekyll'
 require 'jekyll/post'
 require 'rubygems'
-require 'google/api_client'
+require 'google/apis/analytics_v3'
+require 'google/api_client/auth/key_utils'
 require 'chronic'

 module Jekyll
...
         pv['name'][i] = '_pv_' + pv['start'][i].gsub(' ', '-')+'-to-'+pv['end'][i].gsub(' ','-')
       end

-      # API client
-      client = Google::APIClient.new(
-        :application_name => 'octopress-page-view',
-        :application_version => '1.0',
-      )
+      # Analytics service
+      service = Google::Apis::AnalyticsV3::AnalyticsService.new

       # Load our credentials for the service account
       key = Google::APIClient::KeyUtils.load_from_pkcs12(pv['key_file'], pv['key_secret'])
-      client.authorization = Signet::OAuth2::Client.new(
+      service.authorization = Signet::OAuth2::Client.new(
         :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
         :audience => 'https://accounts.google.com/o/oauth2/token',
-        :scope => 'https://www.googleapis.com/auth/analytics.readonly',
+        :scope=> Google::Apis::AnalyticsV3::AUTH_ANALYTICS_READONLY,
         :issuer => pv['service_account_email'],
         :signing_key => key)
-      analytics = client.discovered_api('analytics','v3')

       # Request a token for our service account
-      client.authorization.fetch_access_token!
+      service.authorization.fetch_access_token!

       for i in 0..(pv['start'].size-1)
-        params = {
-          'ids' => pv['profileID'],
-          'start-date' => Chronic.parse(pv['start'][i]).strftime("%Y-%m-%d"),
-          'end-date' => Chronic.parse(pv['end'][i]).strftime("%Y-%m-%d"),
-          'dimensions' => "ga:pagePath",
-          'metrics' => pv['metric'],
-          'max-results' => 100000,
-        }
-        if pv['segment']
-          params['segment'] = pv['segment']
-        end
-        if pv['filters']
-          params['filters'] = pv['filters']
-        end
-
-        response = client.execute(:api_method => analytics.data.ga.get, :parameters => params)
-        results = Hash[response.data.rows]
+        response = service.get_ga_data(
+          pv['profileID'],
+          Chronic.parse(pv['start'][i]).strftime("%Y-%m-%d"),
+          Chronic.parse(pv['end'][i]).strftime("%Y-%m-%d"),
+          pv['metric'],
+          dimensions: "ga:pagePath",
+          max_results: 100000,
+          segment: pv['segment'],
+          filters: pv['filters']
+        )
+        results = Hash[response.rows]

         site.config[pv['name'][i]] = 0

analytics_v3key_utilsapi_client*の代わりにrequireし、 中ではAPIClientオブジェクトを作る代わりにAnalyticsService を使っています。

認証の所は基本、同じですが、親が上の様に変わっているのと、 Google::Apis::AnalyticsV3::AUTH_ANALYTICS_READONLY という値がAPIの中で定義されていて、これは https://www.googleapis.com/auth/analytics.readonly になっています。

なので、そこ変数を使うように。

後は、結果を取ってくる関数とかがちょっと変わってきますが、 基本的には同じような引数を渡してあげれば同じような回答が帰ってきます。

ただし、get_ga_dataという関数は ids, start_date, end_date, metricsという引数を必ず取り、 後はオプションで渡す形になります。

取り敢えずGoogleでAPI Keyを使って情報にアクセスしている場合なんかは こんな感じでアップデートすればGoogle API Client 0.9でも 使える様になる感じです。

もしくはGemfile

gem 'google-api-client', '~> 0.8.6'

とでも書いて古いバージョンを使う、と言う手もありますが。 (今のGemfileではgoogle-api-clientのバージョン指定をしてません。)

Sponsored Links
Sponsored Links

« werckerでのbundle-installにおけるトラブルシューティング Mac版Sophos Anti-VirusのCaskが削除されてた »