【Swift/iOS/Firebase】A/B Testingの実装方法!テスト結果の確認
この記事からわかること
- Swift/Firebaseで作成したiOSアプリにA/B Testingを導入する方法
- Firebaseインストール認証トークンの取得方法
index
[open]
\ アプリをリリースしました /
環境
- Xcode:26.0.1
- iOS:26
- Swift:6
- macOS:Tahoe 26.0.1
Firebaseの概要や登録方法については下記記事を参考にしてください。
おすすめ記事:Firebaseとは?登録方法や使い方、料金と注意点
A/Bテストとは?
「A/Bテスト」とは2種類以上のパターンをユーザーにランダムに表示させ表示させ、一番効果的なパターンを測定するためのテスト手法です。例えばボタンの色味を「赤」と「青」を用意してどちらの方がクリック率が高かったかなどを測定することでよりユーザーに対してよりリーチできている方を判別するために活用されます。
測定例
- クリック率(CTR):ボタンがクリックされた割合
- コンバージョン率(CVR):購入や登録などの成果率
- 滞在時間:サイトやアプリ内での滞在時間
- 離脱率:途中で離脱したユーザーの割合
- etc...
Firebase A/B Testing
Firebaseでは簡単にA/Bテストを実装・解析することができる「A/B Testing」が用意されています。内部的には「Firebase Remote Config」と「Firebase Analytics」を組み合わせて「A/Bテスト」機能の実装と解析が行えるようになっています。
- Firebase Remote Config・・・フラグ制御機能
- Firebase Analytics・・・イベント解析
Firebase A/B Testingの設定と実装方法
Firebase A/B Testingを実際に使用してA/Bテストを計測する方法を見ていきます。まずはFirebase Console側でA/B Testingを有効にします。「A/B Testing」は左メニューの「実行」の中にあります。
「テストを作成」をクリックするとサービス方法を選択できるので「Remote Config」を選択します。
最初にテスト名を入力します。今回は例として「ボタンデザインの分岐によるボタンクリック率を計測する」と仮定して進めていきます。
続いて対象のアプリを選択し、対象のアプリのアクティブユーザーに対して何%にテストを実行するかを設定します。100%を指定すれば全ユーザーに対してテストが試行されます。
続いて紐付けたい「Firebase Analytics」のイベントを指定します。既存で登録しているイベントもしくは新規で作成することができるので新規で作成したい場合はイベント名を入力して「イベント「XXXXX」を作成」をクリックします。
最後に「Firebase Remote Config」のキーと値を指定します。こちらも既存で設定済みのものもしくは新規で作成することが可能です。ここで複数の値を追加すればA/Bの2パターンだけでなく複数パターンでテストを行うことはバリアントの重み付け
設定できたら「確認」をおして作成完了しておきます。この段階ではまだ公開はされていないので「テスト開始」を押して公開してあげればテストが開始します。
iOSアプリ側の実装
iOSアプリ側では「Remote ConfigによるUIの分岐」と「Analyticsのイベント送信」を実装します。まずはRemoteConfigから値をフェッチできるように以下のようなRemoteConfigManagerクラスを定義しました。ここでは単純にRemote Configから流れてくる値をストリームとして公開しています。
import Combine
@preconcurrency import FirebaseRemoteConfig
final class RemoteConfigManager: Sendable {
private let remoteConfig: RemoteConfig
@MainActor
var buttonType: AnyPublisher<Int, Never> {
_buttonType.eraseToAnyPublisher()
}
@MainActor
private var _buttonType = CurrentValueSubject<Int, Never>(1)
init() {
// RemoteConfigインスタンスを取得
remoteConfig = RemoteConfig.remoteConfig()
let settings = RemoteConfigSettings()
// 最小フェッチ間隔 開発環境では0(制限なし)を指定
settings.minimumFetchInterval = 0
// 設定を反映
remoteConfig.configSettings = settings
}
func initialize() {
fetchRemoteConfig()
}
/// リモートサーバーから最新の設定値を取得してremoteConfigインスタンスに反映
private func fetchRemoteConfig() {
remoteConfig.fetch { [weak self] status, error in
guard let self else { return }
if status == .success {
self.remoteConfig.activate(completion: nil)
Task {
await applyButtonType()
}
} else {
#if DEBUG
AppLogger.logger.debug("Error: \(error?.localizedDescription ?? "No error available.")")
#endif
}
}
}
/// `BUTTON_TYPE`設定値を取得し公開
private func applyButtonType() async {
let version = Int(truncating: remoteConfig[RemoteConfigManager.BUTTON_TYPE].numberValue)
await MainActor.run {
_buttonType.send(version)
}
}
private static let BUTTON_TYPE = "button_type"
}
これをViewModel層ではRemote Configの値によりUIを分岐するためのフラグを公開します。
import Foundation
import Combine
@MainActor
final class ABTestViewModel: ObservableObject {
@Published var buttonType: Int = 1
private let remoteConfigManager: RemoteConfigManager
private var cancellables = Set<AnyCancellable>()
init(remoteConfigManager: RemoteConfigManager = RemoteConfigManager()) {
self.remoteConfigManager = remoteConfigManager
bind()
remoteConfigManager.initialize()
}
private func bind() {
remoteConfigManager.buttonType
.receive(on: DispatchQueue.main)
.sink { [weak self] value in
self?.buttonType = value
}
.store(in: &cancellables)
}
}
View層でViewModelの値に応じてUIを分岐させるように実装します。そしてそれぞれのボタンタップイベントにAnalytics.logEventでログイベントを送信するようにしておきます。
struct ABTestView: View {
@StateObject private var viewModel = ABTestViewModel()
var body: some View {
VStack(spacing: 20) {
// A/Bテスト対象のUI部分
if viewModel.buttonType == 1 {
Button {
print("Aボタンが押されました")
Analytics.logEvent("test_button_click_event", parameters: nil)
} label: {
Text("タイプAボタン")
}.buttonStyle(.borderedProminent)
.tint(.blue)
} else {
Button {
print("Bボタンが押されました")
Analytics.logEvent("test_button_click_event", parameters: nil)
} label: {
HStack {
Image(systemName: "star.fill")
Text("タイプBボタン")
}
}.buttonStyle(.bordered)
.tint(.orange)
}
}.padding()
}
}
任意のデバイスでテスト検証する
任意のデバイスで意図的にパターン(バリアント)を指定して検証するためにはテスト検証するには「テストデバイス管理」を選択します。ここにデバイス単位で取得できる「Firebaseインストール認証トークン」または「FCMトークン」を指定することで特定のパターンを対象のデバイスに表示させることができます。「Firebaseインストール認証トークン」は以下のようなコードで取得することが可能です。
import FirebaseInstallations
Task {
do {
let result = try await Installations.installations()
.authTokenForcingRefresh(true)
print("Installation auth token: \(result.authToken)")
} catch {
print("Error fetching token: \(error)")
}
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。





