炊きたてのご飯が食べたい

定時に帰れるっていいね。自宅勤務できるっていいね。子どもと炊きたてのご飯が食べられる。アクトインディでは積極的にエンジニアを募集中です。

Google Tag Manager を利用して GoogleAnalytics を導入する


Swift2.2, Xcode7

GoogleAnalytics を iPhone アプリに埋め込むことになり、せっかくだから AB テストとかも行える Google Tag Manager 経由で GoogleAnalytics を導入してみました。導入にあたっては公式ドキュメントがとても参考になりましたが、慣れないうちはつまづいた点が多かったのでまとめておきます。

Google公式ドキュメント - Getting Started Guide for Swift https://developers.google.com/tag-manager/ios/v3/swift#create-new-project

  1. Google Tag Manager のコンテナを作成し、公開する
  2. Google Tag Manager の設定ファイルをダウンロードしてアプリに埋め込む
  3. CocoaPods で Google Tag Manager をインストールする
  4. Google Tag Manager が正しく動作するか一度ビルドして、コンソールを確認する
  5. GoogleAnalytics 用の設定を Google Tag Manager の管理画面から行う
  6. Google Tag Manager に情報を push するコードをアプリに記述して、計測できているか確認
  7. 効率良く管理する為のちょっとした設定

1. Google Tag Manager のコンテナを作成し、公開する

こちらは特に迷うところはないと思います。Google Tag Manager で新規コンテナを作成してください。注意事項としては、コンテナを公開しないと Google Tag Manager が機能しないので、コンテナを作成したら公開設定を忘れずにやりましょう。

未公開のコンテナ -> アクション -> 公開

f:id:t-namikata:20160518233236p:plain f:id:t-namikata:20160518233304p:plain

2. Google Tag Manager の設定ファイルをダウンロードしてアプリに埋め込む

アクション -> ダウンロード GTM-XXXXX といったファイルがダウンロードされるので、それをプロジェクトに追加します。use_frameworks! の指定を忘れずに。

f:id:t-namikata:20160518234920p:plain f:id:t-namikata:20160518233342p:plain

3. CocoaPods で Google Tag Manager をインストールする

pod 'GoogleTagManager'

を Podfile に追加します。GoogleAnalytics のライブラリは GoogleTagManager の依存パッケージで一緒にダウンロードされるので、記述は GoogleTagManager だけで大丈夫です。use_frameworks! の指定を忘れずに。

install が終わったら、公式ドキュメントを参考に BridgingHeader に以下を追記します。

#import <GoogleTagManager/TAGManager.h>
#import <GoogleTagManager/TAGContainer.h>
#import <GoogleTagManager/TAGContainerOpener.h>
#import <GoogleTagManager/TAGDataLayer.h>
#import <GoogleTagManager/TAGLogger.h>

4. Google Tag Manager が正しく動作するか一度ビルドして、コンソールを確認する

色々な設定をした後に確認すると問題の切り分けが難しくなるので、Google Tag Manager が正しく動作しているか、アプリを起動して Xcode のコンソールでエラーが出てないかを確認します。

1. AppDelegate のクラスに TAGContainerOpenerNotifier を追記

class AppDelegate: UIResponder, UIApplicationDelegate, TAGContainerOpenerNotifier {

2. AppDelegate にコンテナをリフレッシュするメソッドを定義

func containerAvailable(container: TAGContainer!) {
  container.refresh()
}

3. AppDelegate の didFinishLaunchingWithOptions に以下を追記

let GTM = TAGManager.instance()
GTM.logger.setLogLevel(kTAGLoggerLogLevelVerbose)

TAGContainerOpener.openContainerWithId("GTM-PT3L9Z",  // change the container ID "GTM-PT3L9Z" to yours
    tagManager: GTM, openType: kTAGOpenTypePreferFresh,
    timeout: nil,
    notifier: self)

4. アプリを起動して、Xcode のコンソール画面で Warning や Error が出ていないか確認

2016-05-16 23:38:07.907 mymemo[5348:70533] [Crashlytics] Version 3.0.11 (58)
2016-05-16 23:38:07.966 mymemo[5348:70533] GoogleTagManager verbose: Loading default container from GTM-XXXXX
2016-05-16 23:38:07.994 mymemo[5348:70797] GoogleTagManager debug: Resource not on disk
2016-05-16 23:38:08.427 mymemo[5348:70533] GoogleTagManager verbose: scheduleTask: containerId=GTM-XXXXX delay=0.000000
2016-05-16 23:38:08.560 mymemo[5348:70533] GoogleTagManager verbose: Successfully loaded supplemented resource: <TAGPLegacyRawProtoSupplementedResource 0x7fb6d4099b20>: {
... 省略 ...
}
2016-05-16 23:38:08.563 mymemo[5348:70533] GoogleTagManager verbose: Setting refresh time to current time: 1463409488563.304932
2016-05-16 23:38:08.563 mymemo[5348:70533] GoogleTagManager verbose: Saving resource to disk with timestamp of 1463409488563.304932
2016-05-16 23:38:08.563 mymemo[5348:70533] GoogleTagManager verbose: scheduleTask: containerId=GTM-XXXXX delay=43200000.000000
2016-05-16 23:38:08.564 mymemo[5348:70533] GoogleTagManager verbose: Load resource from network finished

「GoogleTagManager warning: Cannot find binary resource file 'GTM-XXX​'. 」のようなエラーが出た場合は、コンテナを公開しているか確認してください。

5. GoogleAnalytics 用の設定を Google Tag Manager の管理画面から行う

正しく Google Tag Manager が読み込まれていることが確認できたら、Google Tag Manager に Google Analytics 用の設定を行います。まずはじめに行うのが、どのような値を取得するか決めることです。今回は集計する値として、2つに分類して集計したいと思います

  1. ViewController が表示された回数
  2. Button や Cell がタップされたイベントの回数

Google Tag Manager でこの 1,2 に対応するのが「タグ」になります。そして Button がタップされた際の集計として、

  • MainViewController の Navigation の Edit ボタンが押された

といった具合に具体的に計測したい場合が多いかと思います。Google Tag Manager でそのような項目に対応するのが「変数」になります。Event(デフォルトで作成されている) , EventAction , EventLabel といった変数を作成して「タグ」の Button Press に設定してあげる形になります。

  • TableViewController -> Event
  • Navigation -> Event Action
  • Edit -> Event Label

といった具合です。詳しい設定方法は公式ドキュメントに書いてあるので、公式ドキュメントを参照してください。 https://developers.google.com/tag-manager/ios/v3/swift#create-new-project

以下を設定したコンテナが出来上がると思うので、公開してください。

タグ 変数
Screen View Screen Name
Button Pressed Event , EventAction , EventLabel

6. Google Tag Manager に情報を push するコードをアプリに記述して、計測できているか確認

計測用の dataLayer.push メソッドを記述したら、アプリを起動して Google Tag Manager でエラーが出ていないかコンソールを確認してください。設定してすぐに確認した場合は、

2016-05-17 23:50:45.328 test[1773:49030] GoogleTagManager info: GoogleAnalytics 3.14 -[GAIBatchingDispatcher didSendHits:response:data:error:] Hit(s) dispatched: HTTP status -1

HTTP status -1 といかにもエラーのようなものが返ってくることがあります。これはどうやら、設定が反映されるまで 24時間程度かかるようで、上記のエラーが出た際は 24 以上待ってから再度動作確認してみてください。また、実機で確認しないと Google Analytics の集計対象にならないといった話も聞いたことがあるので、確認はできれば実機で行いましょう。まずは HTTP status -1 だった部分が HTTP status 200 に変われば正常に取得できていると思います。

7. 効率良く管理する為のちょっとした設定

Google Analytics 用のタグは様々な箇所で利用するので、なるべく書く手間を減らせるように

  1. Screen View を ViewController のクラス名で計測する為に各 UIViewController で継承する CoreViewController.swift の作成
  2. GoogleAnalytics の計測用メソッドを定義する AnalyticsUtility.swift の作成
  3. Enum を使って手入力を極力避ける AnalyticsEventType.swift

といったことをしています。実際のコードは以下のような感じです。

・ AnalyticsUtility.swift

struct AnalyticsUtility {
    private static let dataLayer: TAGDataLayer = TAGManager.instance().dataLayer
    
    static func analyticsEvent(viewControllerName: String, action: AnalyticsEventAction, label: AnalyticsEventLabel) {
        self.dataLayer.push(["event": viewControllerName, "eventAction": action.name, "eventLabel": label.name])
    }
    
    static func analyticsScreenView(viewControllerName: String) {
        self.dataLayer.push(["screenName": viewControllerName])
    }
}

・ AnalyticsEventType.swift

enum AnalyticsEventAction: String {
    case Navigation
    case Button
 
    var name: String {
        return self.rawValue
    }
}

enum AnalyticsEventLabel: String {
    case Edit
    case Login
    case Cancel

    var name: String {
        return self.rawValue
    }
}

・ CoreViewController

class CoreViewController: UIViewController {
  
    var viewControllerName: String {
        return self.getViewControllerName()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // ViewController の表示回数をカウント        
        AnalyticsUtility.analyticsScreenView(self.viewControllerName)
    }

    private func getViewControllerName() -> String {
        guard let viewControllerName = NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last else {
            return "unknown"
        }
        return viewControllerName
    }

・ MainViewController.swift

class MainViewController: CoreViewController {
    @IBAction func edit() {
        // Event: MainViewController
        // EventAction: Navigation
        // EventLabel: Edit で計測される
        AnalyticsUtility.analyticsEvent(self.viewControllerName, action: .Navigation, label: .Edit)
        print("edit")
    }
}

こんな感じで計測が出来ます。

f:id:t-namikata:20160518234035p:plain f:id:t-namikata:20160518234043p:plain