目標指標に定義したAnalyticsEventを使用しFirebaseでA/BTestを行う手順(iOS向け)

#概要
この記事では**iOS向け**にFirebaseでA/BTestを行う際に、
AnalyticsEventをA/BTestの目標指数として使用してTestする方法の手順について説明します。

記事を書いた目的は、
開発者側がリリース前に仕込んだAnalyticsEventでA/BTestを行う方法について触れている記事がないなと思い記事にしてみようと思ったからです。


Firebaseプロジェクト作成の話は割愛し、
AnalyticsEventをA/BTestの目標指数として使用してTestする方法のみの内容になります。
[Firebase](https://firebase.google.com/)プロジェクトの作成はリンクより公式の説明を元に行なった方がわかりやすいのでやってみてください。

# 前置き
FirebaseでA/BTestを行う方法について説明する際に、とあるストーリーベースで進めていきたいと思います。

### ストーリー
FirstViewからSecondViewへ遷移するアプリがある。
FirstViewには"Login"と書かれたボタンが配置されこのボタンを押すことでSecondViewへ遷移する。
SecondViewへ遷移した際のログを取っておりログを見る限りSecondViewへ遷移しているユーザ数が少ない。


そこで、FirstViewに配置してあるボタンを"FaceBookLogin"であることがわかるUIに差し替えた場合
SecondViewへ遷移するユーザは増えるのかどうかをテストする。

<img width="1000" alt="スクリーンショット 2018-08-14 0.24.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/5349f67e-c050-8151-4aa6-d8e1a960e7d2.png">

# FirebaseAnalyticsにEventを通知

`Analytics.logEvent("showSecondView", parameters: nil)`
この一行でSecondViewに遷移した際に、
**showSecondView**というEventがFirebaseコンソールのEventへ通知されます。

```FirstViewController.swift

import UIKit
import Firebase

class SecondViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        Analytics.logEvent("showSecondView", parameters: nil)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

```
# EventをConversionに設定

### showSecondViewがEventとして通知されているか確認しConversionとして設定
※通知が届くまで時間がかかります
<img width="1447" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/2c1b2553-e4d4-6c6a-8352-6bca11918f42.png">
### showSecondViewがConversionに登録されているか確認
<img width="1433" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/86fb95c2-ac17-004e-f619-7d382957c70f.png">



# A/BTestを作成
テストを作成ボタンを押すと、NotificationsとRemoteConfigどちらか選択できるのでRemoteConfigを選択してください。
<img width="1436" alt="3.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/7d68ee1f-5204-7a30-d639-cf0600968cbc.png">

### バリアントの設定
対象となるユーザから均等に分類されます。
50%がコントロールグループ(変更がない今までのバージョン)残りの50%がfaceBookBtn(変更があるバージョン)となります。
A/B/Cテストの場合はそれぞれ33.333%となります。


<img width="1437" alt="スクリーンショット 2018-08-13 22.57.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/ffacbb94-0983-e4fc-5876-f7c7c768088c.png">

### 目標設定

<img width="1456" alt="5.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/b4b23678-9759-5116-2977-a3aa795038fb.png">


# コードの準備
`remoteConfig.setDefaults(["btnType": "typeA" as NSObject])`
初期値として変更がない今までのバージョン(typeA)を設定しています。

`remoteConfig.fetch(withExpirationDuration: TimeInterval(0)`
TimeInterval(X)はX秒RemoteConfigの設定値をローカルキャッシュとしてもつことを示します。
今回は、0秒なのでSecondViewControllerに遷移するたびRemoteConfigから値を取ってくるのでその度通信が発生します。

```FirstViewController.swift

import UIKit
import Firebase
class FirstViewController: UIViewController {
    
    var remoteConfig: RemoteConfig!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.remoteConfig = RemoteConfig.remoteConfig()
        let remoteConfigSettings = RemoteConfigSettings(developerModeEnabled: true)
        remoteConfig.configSettings = remoteConfigSettings
        remoteConfig.setDefaults(["btnType": "typeA" as NSObject])
        remoteConfig.fetch(withExpirationDuration: TimeInterval(0), completionHandler: { (status, error) -> Void in
            if status == RemoteConfigFetchStatus.success {
                self.remoteConfig.activateFetched()
                
                if let type = self.remoteConfig["btnType"].stringValue {
                    if type == "typeA"{
                        //何も変化無し
                    }else{
                        //FaceBookLogin
                    }
                }
                
            } else {
            }
        })
    }
}
```

# 計測結果
※通知が届くまで時間がかかります
この結果より、faceBookBtnグループの方がSecondViewControllerへ遷移することがわかります。
<img width="1435" alt="スクリーンショット 2018-08-13 20.26.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/c46d5790-4dbe-ad8c-193a-9e0ebb89f6f2.png">

# 全ユーザに適用するまでの手順
### テストの範囲を広げていく

テストを配信するユーザの割合を設定します。
以下のスクショ通りであれば、全ユーザの50%にテストが実施されます。
全ユーザ数が100人とすると、50人のユーザがテスト対象となり、ABそれぞれのパターンが25人ずつ反映される
<img width="1434" alt="11.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/52e1fb37-603a-b1a8-9978-9e19ff28bbff.png">

### テスト結果が十分である場合、全ユーザに効果がある方を反映
<img width="1433" alt="２２.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/6af6bf87-1fb5-2ceb-441a-8ce4733bb3b5.png">



#まとめ
1:Eventを通知
2:EventをConversionとして設定
3:A/BTestを作成
4:A/BTestの結果より配信数を伸ばすか撤退か決める
5:十分に効果が見込める場合、全ユーザに配信

手順としては5つ！
今回は、A/BTestを行う方法についての説明でしたが、
重要なのは、どこをテストするか(どこにログを仕込むか)ということなので
テスト箇所についてはチームで議論して実装フェーズまで持っていければあとは環境を整える。
この環境作りの際にこの記事がお役にたてば幸いですmm


# 最後に
今回のA/BTestではRemoteConfigを用いてテストを行なっているので以下ライブラリを使ってみるとスマートにかけたりするのかなとも思ってたり(まだ試してはいないですが、ゆくゆくは試したい)
[Lobster](https://github.com/sgr-ksmt/Lobster)

Firebaseが絡むライブラリをOSSとして展開。。。イイなぁ！