iOSアプリでカジュアルにGoogleAnalyticsを埋め込んでる話

[スピカ Advent Calendar 2015 | Qiita](http://qiita.com/advent-calendar/2015/spika)の2日目の投稿です。

# iOSアプリでカジュアルにGoogleAnalyticsを埋め込んでる話

![Google-Analytics.jpg](https://qiita-image-store.s3.amazonaws.com/0/46751/9562115b-d842-ce88-aae2-b631a1d9fb11.jpeg)

## はじめに

みなさんはiOSアプリを開発されている際に[GA(GoogleAnalytics)](https://www.google.com/intl/ja_jp/analytics/)は使われていますか？
GAとはみなさんご存知の通りGoogleが出してる無料で使える高機能なアクセス解析ツールですね、当社スピカが出しているネイルブック・サロンブックでももちろん利用しておりますが、この記事では当社のiOSアプリであるサロンブックがどのようにしてカジュアルにGAをアプリに埋め込んで運用しているのかを説明していきます。

## サロンブックでのGoogleAnalyticsの運用方法

![スクリーンショット 2015-12-01 21.11.57.png](https://qiita-image-store.s3.amazonaws.com/0/46751/6640b6ab-3b77-8126-94bf-3ce5b2310f32.png)

### GoogleSpreadSheetでGAの定義を管理

GAの定義をGoogleSpreadSheetで管理していて、以下のような定義書になっております

![スクリーンショット 2015-12-01 21.26.54.png](https://qiita-image-store.s3.amazonaws.com/0/46751/9b7b5040-0bd7-29b1-59d5-a4bf8d1cb9e2.png)

まず主要な定義の説明をしていきます

* 利用中
    * `1:利用中`、`0:未利用`という風に管理しており利用中である場合のみ動的にコードからGAを埋め込むための定義を生成するようになってます
* カテゴリ
    * GAで解析する際のカテゴリ欄の説明です
* 項目
    * GAで解析する際の項目欄の説明です
* GAカテゴリ
    * 動的にコードからGAの定義を生成する際に利用する、カテゴリの識別子です
* GAアクション
    * 動的にコードからGAの定義を生成する際に利用する、アクションの識別子です
* GAラベル
    * 動的にコードからGAの定義を生成する際に利用する、ラベルの識別子です
* GA値
    * 動的にコードからGAの定義を生成する際に利用する、バリューの識別子です

* iOS:Class
    * 動的にコードからGAの定義を生成する際に利用する、iOSアプリのGAの埋め込みを動的に行う対象のクラス名です
* iOS:MethodSignature
    * 動的にコードからGAの定義を生成する際に利用する、iOSアプリのGAの埋め込みを動的に行う対象のメソッドシグニチャ名です

このようにただのドキュメントの定義書だけではなく、実際に動くコードの自動化を助けるためのリソースの側面としても合わせて運用を行なっております、これをどのようにコードに持っていくかを次に説明していきます。

### GoogleSpreadSheetをplistに変換

もちろんこのままじゃGoogleSpreadSheetからGAの定義を取得することは難しいのでtsvファイルとしてダウンロードしてきます。そしてそのtsvファイルに対してRubyのスクリプトを実行することでplistの形式に変換していきます。
plistの形式に変換する際のフォーマットは[こちら](http://qiita.com/__moai/items/e980ff8e3ecad3be0f32#%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88)を参照、見てわかるようにGoogleAnalyticsをアスペクト指向的に埋め込むことを助けてくれるライブラリであるGADIを利用しております。

### plistから実際にiOSアプリにGAを埋め込む

```swift
GADInjector.injectWithTrackingID(GLOBAL.GA_TRACKING_ID,
    configPropertyListPath:NSBundle.mainBundle().pathForResource("GoogleAnalyticsConfig.plist", ofType:nil)) {
        (config: [NSObject : AnyObject]!, field: GADField!) -> Bool in
        let status = userRepository.loginUserStatus
        field.addCustomDimension(GACustomDimension.loginUserStatus(status))
                
        field.addCustomDimension(GACustomDimension.installSource(attributes.installSource.value!))
        
        return true
}
        
GADInjector.injectWithTrackingID(GLOBAL.GA_TRACKING_ID,
    configPropertyListPath:NSBundle.mainBundle().pathForResource("GAEventTrackingConfig.plist", ofType:nil)) {
        (config: [NSObject : AnyObject]!, field: GADField!) -> Bool in
        let status = userRepository.loginUserStatus
        field.addCustomDimension(GACustomDimension.loginUserStatus(status))
        
        field.addCustomDimension(GACustomDimension.installSource(attributes.installSource.value!))
        
        return true
}
```

実際のコード例でいくと上のようになります、GADIはカスタムディメンションの埋め込みにも対応できるようになってるのでサロンブックアプリではGAの定義を流しこみつつ、どこからの流入か、ログインの状態を把握するための対応をこれだけの行数で済ませることができています。
アスペクト指向の応用が上手くハマってるパターンではないかと考えており、このようなトラッキングのような要件に対して柔軟に使っていけるのではないでしょうか。
ちなみに当初はカスタムディメンションは入れておらず運用してましたが、ログイン率が見たいという要件に対して1週間かからない工数で対応することができたので大幅な作業の短縮に貢献してくれました。

## さいごに

普通だったらチマチマコードに埋め込まないといけないGAですが、当社ではこのようにカジュアルにGAを扱えるようにしたことによって短縮できた時間を使って他の問題を取り組むことを可能にしています。
是非興味がありましたらこのようなシステム作りをして幸せなアプリ開発を実現していきましょう！

## 関連リンク

* [単純に呼べば使えるAOPライブラリMOAspectsを作った](http://qiita.com/__moai/items/efcd43016b9320cf6d63)
* [MOAspects - SwiftでViewControllerに対してアスペクト的にログを出してみる](http://qiita.com/__moai/items/5c4aae78cf03bacd7369)
* [iOS用のGAのトラッキング埋め込みライブラリ作った - GADI](http://qiita.com/__moai/items/e980ff8e3ecad3be0f32)
* [SwiftとRealmによるアプリ開発実践ノウハウ](http://sssslide.com/speakerdeck.com/hayashitatsuya/swifttorealmniyoruapurikai-fa-shi-jian-falseuhau)