ElectronアプリケーションにGoogleAnalyticsを導入したい
簡単に導入出来ると思ってた時期が僕にもありました。
Electronでアプリケーションを作る際に、公開することを見越してアクセス解析を仕込もうと思いました。
ElectronもWebの技術で作成されているので、簡単に入れれるだろうと思っていましたが、結構ハマったので備忘録として記事に残したいと思います。
試したこと
まずは、それっぽいnpmモジュールがあったのでいろいろ試しました。
electron-google-analytics やvue-analytics など試しましたが、ローカルでは動いたのですがビルドしてアプリケーション化すると動かなくなったり、ページ遷移が別のユーザーとして集計されてしまったりと、思い通りの動きになりませんでした。(筆者の実装の問題かもしれませんが。orz)
ビルドするとドメインを持たない
Electornは開発時はローカルにサーバーを立てて動いているので、http通信によるドメイン(localhost)が自動振られますが、アプリケーション化するとhttp通信では無くなるので、ドメインが振られなったり、ブラウザキャッシュが使えなくなったり、正常にGoogleAnalyticsへの送信が出来ない原因と思われる事象がネット上に転がっており先駆者の方達も結構苦労しているようでした。
開発者ツールのRequest URLとRequest Headersを見ると違いがわかると思います。
ローカル起動の場合

アプリケーション起動の場合

universal-analyticsで全て解決
そんな中、universal-analyticsを使ってみたところ特に苦労せずにGoogleAnalyticsの導入を実現する事が出来ました。
universal-analytics A node module for Google's Universal Analytics tracking via the Measurement Protocol.This module allows tracking data (or rather, users) from within a Node.js application. Tracking is initiated on the server side and, if required, does not require any more tracking in the browser.universal-analytics - npm
手順
universal-analyticsをインストール
まずはyarnコマンドでuniversal-analyticsを依存関係に追加しましょう。
yarn add v1.17.3
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning " > sass-loader@7.3.1" has unmet peer dependency "webpack@^3.0.0 || ^4.0.0".
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ universal-analytics@0.4.20
info All dependencies
└─ universal-analytics@0.4.20
$ electron-builder install-app-deps
• electron-builder version=21.2.0
✨ Done in 3.76s.
遷移時のイベント送信の追加
次に、Vue-Routerで遷移が発生した際にGoogleAnalyticsにイベントを送信する処理を追加します。
...
(省略)
...
import ua from "universal-analytics";
import { machineIdSync } from "node-machine-id";
const original: boolean = true;
const uuid = machineIdSync(original);
let visitor = ua("UA-XXXXXXXXX-YY", uuid, { strictCidFormat: false });
const isProduction = process.env.NODE_ENV === "production";
if (isProduction) {
router.afterEach((to, from) => {
visitor
.pageview(to.path, "http://localhost", to.name)
.send();
});
}
...
(省略)
...
router.afterEachを使えば、定義している全てのrouteに対して遷移時に共通処理を差し込むことが可能になります。
今回はto変数に入っている遷移先のパスと名称を渡すようにしています。
ClientIDの付与
今回はGoogleAnalyticsへのClientIDを生成するためにnode-machine-idというモジュールを使ってマシンに対するUUIDを取得・発行しています。
Cross-platform unique machine (desktop) id discoverynode-machine-id - npm
また、その際にstrictCidFormat: trueとしてClientIDの値をUUID以外も許容するようにしています。
ここでポイントなのは、第二引数のホストをhttp://localhostにすることです。
他の指定でも良いのかもしれませんが、Electronアプリは前述の通りビルドしてしまうと、ホストを持たないのでとりあえずはこれで良い気がしています。
また、開発時の操作はGoogleAnalyticsに送信したくないので、process.env.NODE_ENVがproductionの場合のみ送信するようにしました。
確認
では、実際にビルドしてアプリを立ち上げて機能遷移してみましょう。
起動時

遷移時

正常に、同一ユーザーとしてアクセス解析がされるようになりました♪
ClientID
CliendIDもしっかりと送られていますね♪
GoogleAnalytics

Electronログ

終わりに
以上のように、 universal-analyticsを使えば簡単にElectronアプリの機能単位の利用具合を集計・解析する事が可能になりました。
どのような機能がどれだけ使われているか?という数字も、いずれは武器になったり機能改善に繋がるので、皆さんも是非入れてみてはいかがでしょうか♪
