【Firebase】In-App Messaging・Analytics・Crashlytics・RemoteConfig・A/B Testing

この前Firebaseをつかったグロースハックの勉強会に参加したら面白かったので挑戦してみました。

とはいってもどうしたらいいのかわかんなかったので、今回はCodelab(≒Firebaseのチュートリアル集みたいなやつ)を元に試してみます
https://codelabs.developers.google.com/codelabs/grow-firebase-ios-swift/index.html?index=..%2F..index#0

<img width="357" alt="スクリーンショット 2018-12-15 21.12.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/a84e33cd-8e2b-fd5d-6140-0d9d19415a19.png">

# これが学べるらしい

- In-App Messaging
- Analytics
- Crashlytics
- RemoteConfig
- A/B Testing

*プロジェクト作成、Podfile、セキュリティルール等の設定は割愛します。

# In-App Messaging
In-App Messagingを使うとターゲットに対してコンテキストメッセージを送ることができ、何らかの施策を打つことができます。

### 準備

- Podfileにpod 'Firebase/InAppMessagingDisplay'があることを確認
- Go to Product > Scheme > Edit Schemeに遷移して、Arguments tabを選択。Arguments passed on launchにフラグを追加しRun。RunさせるとコンソールエリアのStarting InAppMessagingの後にtesting app's Instance IDが表示されるのでメモ。

### In-App Messagingを試してみる

- Firebaseのコンソールに戻って、ナビゲーションパネルからIn-App Messaging > 最初のキャンペーンを作成を選択
<img width="1440" alt="スクリーンショット 2018-12-15 18.02.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/156388a1-a85a-fec7-89b6-231fa08a3178.png">

- メッセージタイトルと本文に適当な言葉を入力し、Test on Deviceを選択。
<img width="1440" alt="スクリーンショット 2018-12-15 18.05.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/fdbfd5c0-daca-98f8-ffe7-025644326281.png">

- 端末でのテストというダイアログが表示されるので、先程メモしておいたtesting app's Instance IDを入力し入力欄右に表示される+ボタンを選択しIDが追加されたことを確認したら「テスト」を選択

- アプリがフォアグラウンドにいる場合は一度バックグラウンドに戻してから再度フォアグラウンドにすると設定したタイトルとメッセージのダイアログが表示されます。
* ただ「テスト」を選択してから一度しか表示されないので、再度テストする場合は再度IDの追加から設定して「テスト」を選択する必要がある。

<img width="356" alt="スクリーンショット 2018-12-15 18.21.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/ae947829-019b-4526-c298-c30ba18d4aaf.png">

# Firebase Analytics
Firebase Analyticsを使うことでユーザーがどこで離脱したか、またそのアプリ内のどこが一番使われているかも理解できます

### 準備
MeasurementHelper.swiftファイルを開いてコードを追加します
*実際のソースコードではsendLogoutEventメソッドですが、画面上はSignoutになっていて気持ち悪かったのでメソッド名書き換えました。それとsendSignoutEvent()メソッドは呼び出さてないので自分で呼び出すコードを追加しないと一生ログは吐き出されません。

```
  static func sendLoginEvent() {
    Analytics.logEvent(AnalyticsEventLogin, parameters: nil)
  }

  static func sendSignoutEvent() {
    Analytics.logEvent("signout確認", parameters: nil)
  }

  static func sendMessageEvent() {
    Analytics.logEvent("message確認", parameters: nil)
  }
```
これがどんな動きをしているかFirebase Console内でみたい場合は、XcodeでProduct > Scheme > Edit Schemeと遷移し、「Arguments Passed on Launch」で「+」を選択し新しいargumentとして-FIRAnalyticsDebugEnabledを追加します。
*Firebase Analyticsによるレポートはレポートがアップロードされてから約24時間後にFirebase ConsoleのAnalysisで確認できます。今回は24時間待てないので割愛(そのうち載せます)

<img width="908" alt="スクリーンショット 2018-12-15 18.37.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/0db7fd11-5949-32a1-07df-1bef1027422c.png">

### Firebase Analyticsでログを出してみる
実際の結果
一応messageが送られたときとsignoutされたときのログは取れてるけど、コンソールの情報だけだとわからない。
これがどんな内容なのかはもしかしたらFirebase Consoleで確認するのかもしれないですね。

```
2018-12-15 18:47:17.056057+0900 FriendlyChatSwift[6217:107112] 5.14.0 - [Firebase/Analytics][I-ACS023051] Logging event: origin, name, params: app, message確認, {
    firebase_event_origin (_o) = app;
    firebase_screen_class (_sc) = FCViewController;
    ga_screen_id (_si) = -3115657362850325446;
}

2018-12-15 19:00:42.060427+0900 FriendlyChatSwift[6779:116281] 5.14.0 - [Firebase/Analytics][I-ACS023051] Logging event: origin, name, params: app, signout確認, {
    firebase_event_origin (_o) = app;
    firebase_screen_class (_sc) = FCViewController;
    ga_screen_id (_si) = 8925318972289943464;
}
```

# Crashlytics

Firebase Crashlyticsを使うと、クラッシュが発生したときにレポートが作成され、クラッシュまでのイベントを記録できます。

### 準備

- まずPodfileに`pod 'Fabric', '~> 1.7.2' and pod 'Crashlytics', '~> 3.9.3'` があることを確認
- the run script build phaseを追加
    - Xcodeでプロジェクトを開きナビゲーターエリアにあるプロジェクトファイルを選択
    - Build Phaseタブを選択
    - 「+」を選択しNew Run Script Phaseを選択
    - # Type a script or drag a script file from your workspace to insert its path.と書かれているテキストボックスに`${PODS_ROOT}/Fabric/run` を入力
    - Xcode10を使っている場合はBuild Phaseの「input files」のフィールドにInfo.plistの場所を追加
    `$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)`
    - プロジェクトのデバッグ設定を調整する。ビルドの起動時にデバッガに接続する場合、Crashlytics はクラッシュをキャプチャできません。ビルドの設定を調整して、プロジェクトのデバッグ情報の形式を変更します。
    ①Xcode ナビゲータでプロジェクトがまだ選択されている状態で、[Build Settings] タブを開きます。
    ②すべてのビルド設定を表示するには、このタブの上部にある [All] をクリックします。
    ③「debug information format」を検索します。
    ④[Debug Information Format] 値を[DWARF with dSYM File] に設定します。

<img width="1117" alt="スクリーンショット 2018-12-15 19.46.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/dc0ae403-8b7e-f80c-8d6f-200a277556d9.png">


### クラッシュを起こしてみる
Crashlytics の動作を確認するのにクラッシュが発生するのを待つ必要はなく、アプリに `Crashlytics.sharedInstance().crash()` を追加するだけで、SDK を使用して強制的にアプリをクラッシュさせることができます。

```
// FCViewController
 @IBAction func didPressCrash(_ sender: AnyObject) {
    print("Crash button pressed!")
    Crashlytics.sharedInstance().crash()
  }
```

ここまでできたら実行。
1回目の初期インスタンスではCrashlyticsの動作を妨げるデバッガが含まれているらしいので、一度止めて再度実行させます。
起動後「Crash」ボタンを選択するとCrashlyticsAPIが呼ばれ5分以内にFirebase Consoleにクラッシュレポートが表示されるようです。
設定をカスタマイズして、オプトインのレポート、ログ、キーを追加したりすると、重大でないエラーを追跡したりすることもできるようです(今回はしません)
参考: https://firebase.google.com/docs/crashlytics/force-a-crash?hl=ja


# Remote Config

Remote Configを使うことでアプリのアップデートをユーザーにダウンロードしてもらわなくても、また、公開しなくても、アプリの動作と外観を変更できます。

ここではアプリの設定を変えずにRemote Configを使って入力できる文字数の制限を変更してみます。

### 準備
- Remote Configのルールを追加
コンソールのパネルからRemote Configを選択、「最初のパラメータを追加」を選択
<img width="1438" alt="スクリーンショット 2018-12-15 20.24.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/0e69fb9a-6c47-904b-3cbf-b887e6353b05.png">

パラメータKeyをfriendly_msg_length、値を10に設定し、「パラメータを追加」を選択。これでユーザーはフィールドに10文字までしか入力できません
<img width="1169" alt="スクリーンショット 2018-12-15 20.27.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/3c971281-72e9-d1ab-1159-4fddccb41075.png">

次の画面で「Publish Changes」を選択

- Podfileに `pod 'Firebase/RemoteConfig'`があることを確認
- Remote Configの設定

FCViewController.swiftにコードを追加

```
  func configureRemoteConfig() {
    remoteConfig = RemoteConfig.remoteConfig()
    let remoteConfigSettings = RemoteConfigSettings(developerModeEnabled: true)
    remoteConfig.configSettings = remoteConfigSettings
  }
```

- リクエストを作成して Remote Config から先程設定した制限値を取得。その値をアプリで使用できるようにするため completion handlerを追加する

```
FCViewController.swift
  func fetchConfig() {
    var expirationDuration: TimeInterval = 3600
    // 開発者モードの場合、cacheExpiration(キャッシュの有効期限)は0に設定される
    if self.remoteConfig.configSettings.isDeveloperModeEnabled {
      expirationDuration = 0
    }

    remoteConfig.fetch(withExpirationDuration: expirationDuration) { [weak self] (status, error) in
      if status == .success {
        print("Config fetched!")
        guard let strongSelf = self else { return }
        strongSelf.remoteConfig.activateFetched()
        let friendlyMsgLength = strongSelf.remoteConfig["friendly_msg_length"]
        if friendlyMsgLength.source != .static {
          strongSelf.msglength = friendlyMsgLength.numberValue!
          print("Friendly msg length config: \(strongSelf.msglength)")
        }
      } else {
        print("Config not fetched")
        if let error = error {
          print("Error \(error)")
        }
      }
    }
  }

```

### Remote Configを試してみる
実行して文字を入力。最初に文字数の制限を10に変更したから11文字目は入力できない。
この状態で再度Firebase のRemote Configでfriendly_msg_lengthの値を30に変更し、アプリで「Fresh Config」をタップ。
今度は30文字まで入力できれば成功<img width="987" alt="スクリーンショット 2018-12-15 22.48.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/a5b9d667-ac52-5cdc-7427-571d42dcba85.png">


# A/Bテスト
Firebaseを使ってA/Bテストを行うことができます。
A/Bテストを行うことで製品やマーケティングの実験を簡単に実行、分析、拡張し、アプリでのユーザー体験を最適化できます。

### A/Bテストをしてみる

- アプリを実行しXcodeのコンソールから"Remote instance ID token"を取得
- Firebase ConsoleのナビゲーションパネルからA/B Testing > テストを作成 を選択
- ダイアログが表示されるので、今回はRemote Configを選択

- テスト名に"max msg length"、説明に"What is the best max msg length"と入力し次へ
<img width="987" alt="スクリーンショット 2018-12-15 22.48.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/f0d3f938-acca-8044-f6fa-d1d5fb98c530.png">


- ターゲットに作成したアプリ(ここではFriendlyChat)を選び次へ
<img width="1114" alt="スクリーンショット 2018-12-15 22.48.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/ed725b0d-2e5b-323d-7690-d2e8ee364a98.png">

- テストの目的を選択し、次へ
<img width="1117" alt="スクリーンショット 2018-12-15 22.47.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/5e4849d6-8381-f4b5-748b-0a5a9d319ae6.png">

- コントロールグループに"friendly_msg_length"を選択。バリアントBの場合はvalueに10を設定する。`Add another variant`を選択しvalueに3を設定し、確認を選択
<img width="928" alt="スクリーンショット 2018-12-15 22.47.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/115a7366-9f47-2de0-11c0-6f353d97f5d2.png">

- 下書き下のDetailを選択し展開、「テスト端末を管理」を選択する
<img width="1142" alt="スクリーンショット 2018-12-15 22.40.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/2735ad50-74a0-73fc-9497-dc7a14530ecc.png">

- 先程のインスタンスIDをペースト、テスト用にバリアントAを選択。追加、保存の順で選択
<img width="505" alt="スクリーンショット 2018-12-15 22.44.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/a563be5d-e919-8720-c1a0-e98a82f05d61.png">

- 今度はアプリ側で `Fetch Config`を押して、テキストフィールドがVariant Aの値に制限されていることを確認


# おわり

とりあえずいくつかさらっと試してみたけど、それぞれ組み合わせることでより効果的な施策が打てそうなのでまたどこかで詳しく触ってみたい