LoginSignup
2

More than 5 years have passed since last update.

Staccato を使ってサーバーサイドからGoogleAnalyticsに直接送信する

Last updated at Posted at 2017-12-12

こんにちは、Misocaの @lulu-ulul です。
Misoca Advent Calendar 2017 の12日目の記事になります。

GoogleAnalytics に関する記事になります。

ちょっと前まではGAとは代行で設置して初期設定して終わり!くらいの付き合い方くらいしかしてませんでした。
最近はちょこちょこ弄る様になり、数字の増減やチャートの動きを見てニヤニヤする人達の気持ちが少し分かってきた今日この頃です。
同僚から Staccato っての使うと良さそうって教えてもらったので試してみました。

GoogleAnalytics によるトラッキング

通常はトラッキング用のスクリプトを埋め込まみ、クライアントサイドでページビューやイベントをGAのサーバに送信させます。
ただ view が無いactionでは取れないですし、処理終了後にリダイレクトでダッシュボード等に飛ばしているとそれぞれを識別するのが困難ですよね。
そこで今回はサーバーサイドから直接送信してトラッキングする方法を試してみます。

Google Analytics Measurement Protocol(以下GAMP)

Google が提供しているHTTPリクエストで直接送信するためのプロトコルです。
詳しくはGoogle先生が丁寧なドキュメントを提供してくれているのでそちらを見て下さい。
Google Analytics Measurement Protocol

Staccato

GAMPを扱うためのgemである staccato を使いました。
同じ作者の方が staccato-rails も公開しているので、そちらを利用すると手軽にGETリクエストをpageviewとしてサーバサイドから送る事ができる様になります。

私の場合は以下の理由で staccato を使い送信する形にしました。

  • Tracker のcreate時にパラメータを指定したい
  • pageviewについては複数のTrackerを使いたい
  • view 側で送る必要があるので結局スクリプトの埋め込みが必要
  • GAに送りたくないGETリクエストがあるが除外するのが面倒

:muscle: 手を動かす

gateway の作成

Gemfile 周りや application.rb へのpathの追加等は割愛します。

controller で直接Staccatoを呼び出してtracker 作るのはアレなので以下の様なgatewayを定義しました。

app/gateways/google_analytics_tracking_gateway.rb
# frozen_string_literal: true

class GoogleAnalyticsTrackingGateway
  def initialize(client_id: nil, user_id: nil, user_ip: nil)
    @staccato_tracker = Staccato.tracker('UA-XXXXXXXX-X', client_id, user_id: user_id, user_ip: user_ip)
  end

  def tracker
    @staccato_tracker
  end
end

今回はお試しなのとStaccatopageviewメソッドが直感的だったので Staccato::Tracker のオブジェクトを返す形で手抜きしています :sweat_drops:

GA における client id と user id

ざっくり説明すると前者はcookieベースでブラウザ/デバイス単位で追跡するための識別子で、
後者はサービス側の一意のID(ユーザレコードのID等)を渡してブラウザやデバイス・セッションを超えてユーザを追跡するための識別子です。
詳しくはこちらの公式docを。

これを埋め込みscript側と共通の値にしたいためStaccatoを使っています。
staccato-rails はコード追った所そのままでは user idが設定できない様でした。
client id も標準だと session で管理しているため staccato 独自の値が設定されてしまいますが、こちらは簡単に変更できます

controller で client id と user id, リクエスト元のIPを渡す

先程のドキュメントを見ると client id は cookies['_ga'] から取り出せば良さそうです。

hoges#create 成功時に pageview を送信するexampleを書いてみます。

app/controllers/hoges_controller.rb
...

def create
  ...

  if result.success?
    cookies['_ga'] ||= { value: Staccato.build_client_id, domain: '.example.com', expires: 2.years.from_now }
    tracker = GoogleAnalyticsTrackingGateway.new(client_id: cookies['_ga'], user_id: current_user.id, user_ip: request.remote_ip).tracker
    tracker.pageview(path: '/hoges/create', title: 'hogeの作成成功')

    # 通常の作成成功時の処理
    ...
  else
    # 作成失敗時の処理
    ...
  end
end

ここで気をつけないといけないのが parameter のkey名です。
Staccato はparameterを一度定義したkey名のものに絞り込み、その後 GAMP 用の key 名に変換します。
そのためpageview メソッドに直接GAMP側の uid パラメータを指定しても捨てられてしまうので、 user_idパラメータとして指定する必要があります。

README に一覧はありますが、 Googleのリファレンスこちらの key-value の組を突き合わせて確認するのが確実です。

user_ip もリクエストから取り出して設定しないと別セッション扱いされてしまうので設定しておきます。


tracker の取得自体はcookie と current_user を見るだけですし外でも使いたいので、concerns に定義して applications_controller でincludeします。

app/controllers/concerns/send_hit_to_google_analytics.rb

def send_pageview_to_ga(path:, title: nil)
  cookies['_ga'] ||= { value: Staccato.build_client_id, domains: '.example.com', expires: 2.years.from_now }

  tracker = GoogleAnalyticsTrackingGateway.new(client_id: cookies['_ga'], user_id: current_user.id, user_ip: request.remote_ip).tracker
  tracker.pageview(path: path, title: title)
end

app/controllers/hoges_controller.rb
...

def create
  ...

  if result.success?
    send_pageview_to_ga(path: '/hoges/create', title: 'hogeの作成成功')

    # 通常の作成成功時の処理
    ...
  else
    # 作成失敗時の処理
    ...
  end
end

すっきりしましたね。
これで終了です。

実際に rails server を立ち上げて create に成功するとGAに送信されていると思います。
スクリーンショット 2017-12-11 6.17.04.png


何故こんなことしてるの?

ユーザの一連の動きを目標に設定してコンバージョン率を見るためです。

view の無いページは通常のpageviewだけだと遷移後のページを指定して間接的に観測するしかありませんが、今回の様にしてGAにhitを送信することで直接記録することができます。

何でpageviewなの?

GoogleAnalyticsでは通常ユーザのクリックイベントをeventを使ってトラッキングします。
しかしpageview と eventを混じえた一連の動き(例. ページ:a: からページ:b:に遷移してイベント :one: 発生後 ページ:a:に遷移する) を追う事ができません。
目標は一連のページ遷移もしくは単発のイベント発生の有無のどちらか、イベントフローはイベントの発生順序しか追えません

これを回避するための手法の一つとして、仮想的なURL等を使い全てをpageviewで揃えて目標に設定するというものがあります。
目標到達プロセスやゴールフローを使える様になるのでおすすめです。

何か影響ないの?

仮想的なページへ遷移した事になるので、前後のページの離脱率や滞在時間に影響は出ますので注意する必要はあります。
ただviewの無いactionに仕込むだけでしたら、今まで前のページに丸められていたものが分離するだけなので問題ないかなと思います。

まとめ

Staccato を使ってサーバサイドからGAへpageviewのhitを送信し、viewが存在しないactionも直接的に観察できる様になりました。
必要であれば同様にしてDelayedJob等から送信する事もできますね。

トラッキングを防止する拡張等の影響をうけなくなるので、view 側のイベントで送っているものも含め全てサーバサイドから送る様にしたい気持ちはあるのですが、
今までクライアントサイドで送って貰っていたものが全てサーバサイドから送る事になるので少し考え中です。


Misoca Advent Calendar 2017、明日の担当は @mzp で少しスピリチュアルな感じの記事をお届けする予定です。

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
2