38.7K Views
September 13, 24
スライド概要
DroidKaigi 2024 で発表したスライドです。
https://2024.droidkaigi.jp/timetable/678050/
当日の発表動画
https://www.youtube.com/watch?v=Pi5qSRCHKyQ
Android Engineer at Kyash Inc.
データに基づく意思決定を支える、 Google Analytics for Firebase のイベント送信 DroidKaigi 2024 ©2024 Kyash Inc. ©2024 Kyash Inc.
自己紹介 自己紹介 ● 高田 晴彦 ● @tfandkusu ○ Qiita/Zenn/note/GitHub/X ● 株式会社Kyash ● Androidエンジニア ● スプラトゥーンが好き ©2024 Kyash Inc. 2
アウトライン データに基づく意思決定を支える Kyash アプリを例に解説 モバイルエンジニアは どこに注力するべきか ©2024 Kyash Inc. 3
アウトライン Google Analytics for Firebase のイベント送信 予備知識 ©2024 Kyash Inc. 適切な実装 ● 送信データ形式 ● 画面遷移イベント ● 保存先 ● ユーザIDの設定 ● 集計ツール 4
アウトライン 適切に実装し続けるチームを作る 自動化 GitHub Actions / コード生成 / detekt カスタムルール ©2024 Kyash Inc. 5
データに基づく意思決定 ©2024 Kyash Inc. 6
データに基づく意思決定 アウトライン ● 弊社 Kyash アプリの紹介 ● KPI 分析 ● ファネル分析 ● A/B テスト ● 意思決定フローのバリエーション ©2024 Kyash Inc. 7
データに基づく意思決定 - Kyash アプリ デジタルウォレットアプリ Kyash ©2024 Kyash Inc. 8
データに基づく意思決定 - Kyash アプリ 入金 決済 銀行口座 コンビニ 等 VISA QUICPay ©2024 Kyash Inc. 9
データに基づく意思決定 - Kyash アプリ 送金 ©2024 Kyash Inc. 家計簿 後払い決済 懸賞 10
データに基づく意思決定 - KPI 分析 事業の売上 ● 決済手数料 ● 後払い決済の手数料 ©2024 Kyash Inc. 各種 KPI を集計 効率的に伸ばしたい 11
データに基づく意思決定 - KPI 分析 KPI Key Performance Indicator 重要業績評価指標 目標までの達成状況を定点観測するための、定量的な指標 ©2024 Kyash Inc. 12
データに基づく意思決定 - KPI 分析 KPI の例 ● ユーザ登録数 ● 新規ユーザ ● 入金したユーザ数 ● 既存ユーザ ● 決済したユーザ数 ● 入金手段別の金額 ©2024 Kyash Inc. 13
データに基づく意思決定 - KPI 分析 新規ユーザの初回決済を増やしたい 広告 ©2024 Kyash Inc. インストール ユーザ登録 決済 売上 14
データに基づく意思決定 - KPI 分析 KPI を確認 新規 入金 決済 ユーザ数 ユーザ数 ユーザ数 詳しく見たい ©2024 Kyash Inc. 15
データに基づく意思決定 - ファネル分析 入金までのステップが多い ● ● ● ©2024 Kyash Inc. 法律 マネーローンダリング対策 セキュリティ ● ● 本人確認 認証 16
データに基づく意思決定 - ファネル分析 ファネル分析 離脱の多いステップを把握するデータ分析 カード発行 入金手段選択 銀行選択 ユーザ 登録 本人確認 … 離脱が多い。重点的に検討。 ※ 説明のため、実際のアプリから一部ステップを省略し、離脱の大小も実際とは異なります。 ©2024 Kyash Inc. 17
データに基づく意思決定 - ファネル分析 離脱が多い ● 仮説を立てる ○ 新たな機能や訴求 説明が不足していてユーザ が求める機能にたどり着け 検討 実装 リリース ていない ○ ある表現でユーザが不安に なり先に進まない ● ユーザインタビュー ©2024 Kyash Inc. 18
データに基づく意思決定 - A/B テスト 以前の実装 新しい実装 リリース後 効果を 比較する A/B テスト ©2024 Kyash Inc. 19
データに基づく意思決定 - A/B テスト 以前の実装 新しい実装 50%ユーザ 50%ユーザ A/B テスト 効果を比較 ©2024 Kyash Inc. 20
データに基づく意思決定 - A/B テスト A/B テストで複数 A B 手間を省く 遅延手数料を防ぐ の訴求を比較検討 後払い決済の自動口座引落し設定 を推奨して未収を減らす施策 ©2024 Kyash Inc. 21
データに基づく意思決定 - A/B テスト 効果あり 採用 ユーザ全員に適用 A/B テスト 効果なし 逆効果 ©2024 Kyash Inc. 再検討 22
データに基づく意思決定 - 意思決定のバリエーション 意思決定の起点にはバリエーションがある ユーザの声 社内で思いついた 仮説 ©2024 Kyash Inc. データで 裏付け 新たな機能や 訴求を検討 23
データに基づく意思決定 - まとめ、次の話 データに基づく意思決定を支える モバイルエンジニアは ● KPI 分析 ● ファネル分析 ● A/B テスト どこに注力するべきか 次の話 データはどのように 集計されるか ©2024 Kyash Inc. 24
支える ©2024 Kyash Inc. 25
支える 一般的なアプリサービスにおける KPI の集計方法 バックエンド モバイル アプリ KPI 分析 ©2024 Kyash Inc. API サーバサイド アプリケーション 大規模データ集計特化 データベース (BigQuery 等) リレーショナル データベース (MySQL 等) 同期 26
支える バックエンドのデータ 保存されている ● ● 本人情報 ○ 本人確認情報 ○ 外部サービス連携情報 サービス提供 のために 保存必須 保存されていない ● 画面遷移 ● 操作内容 取引履歴 ○ 入金 ○ 決済 ○ 送金 ©2024 Kyash Inc. 27
支える 画面遷移、操作内容 アプリ計測ソリューション Google Analytics for Firebase ©2024 Kyash Inc. 28
支える データに基づく意思決定を 「支える」ために注力 アプリ計測ソリューション モバイルエンジニアが予め実装 操作 ユーザ ©2024 Kyash Inc. イベント送信 データ活用 29
Google Analytics for Firebase のイベント送信 ©2024 Kyash Inc. 30
Google Analytics for Firebase のイベント送信 アプリ計測ソリューション Google Analytics for Firebase ● ● イベント ○ 送信データ形式 ○ 保存先 集計ツール ©2024 Kyash Inc. 31
スライドのアクセス先 スライドを手元で見る この先、SQL やソースコードが表示されるスライドがあります または X で検索 ● 高田 晴彦 ● tfandkusu アイコンはスプラ トゥーンのイカちゃん。 今日が無事に完了した らグランドフェスに参 加します。 ©2024 Kyash Inc. 32
Google Analytics for Firebase のイベント送信 Google Analytics for Firebase モバイルアプリ向け API を提供 ©2024 Kyash Inc. ● Google の計測ソリューション ● Web サイト向けにも提供 33
Google Analytics for Firebase のイベント送信 Firebase とは ● Google が提供 ● アプリ開発全体をサポートするプラットフォーム ○ PUSH 通知 ○ クラッシュ分析 ○ ホスティング ○ データベース ©2024 Kyash Inc. 34
Google Analytics for Firebase のイベント送信 Google Analytics for Firebase このセッションでは Analytics と省略して呼びます ©2024 Kyash Inc. 35
Google Analytics for Firebase のイベント送信 イベントのデータ形式 イベント イベント名 Key 複数 Firebase SDK の 具体的なメソッド名は 公式ドキュメント参照 ©2024 Kyash Inc. イベント パラメータ Value 基本的な型 (String, Int, Float) 36
Google Analytics for Firebase のイベント送信 イベント 手動/自動付与 自動付与 アプリを使用している個人 デバイスの情報 OSバージョン等 あとで詳しく説明 ©2024 Kyash Inc. 37
Google Analytics for Firebase のイベント送信 イベントの保存先 すべての イベントを エクスポート ©2024 Kyash Inc. BigQuery 38
Google Analytics for Firebase のイベント送信 コンソールで 基本的な分析が可能 BigQuery 自由に様々な分析が可能 ©2024 Kyash Inc. 39
Google Analytics for Firebase のイベント送信 BigQuery への保存のされかた リレーショナルデータベースと同様にテーブルがあり、SQL で集計できる 1日1テーブル firebase-kyash.analytics_123456789.events_20240913 Google Cloud の プロジェクト名 ©2024 Kyash Inc. データセット名(自動付与) テーブル名(自動付与) 後ろの8桁数字は日付 40
Google Analytics for Firebase のイベント送信 レコード 1回のイベント送信は 1レコード イベント名 event_name タイムスタンプ event_timestamp … screen_view 1721463361915024 … select_bank 1721463361915025 … kyc_top 1721463361915026 … マイクロ秒の UNIX 時間 ©2024 Kyash Inc. 41
Google Analytics for Firebase のイベント送信 イベントパラメータの独特な保存形式 例: 懸賞詳細画面の表示イベント イベント名 = reward_detail イベントパラメータ ● type = “daily” ● id = 13 ©2024 Kyash Inc. 42
Google Analytics for Firebase のイベント送信 イベントパラメータの独特な保存形式 ネストされた列 (= レコードの中に配列があるイメージ) イベントパラメータの value は 型に合わせた列に格納 float_value double_value … event_name event_params. key event_params. value. string_value event_params. value. int_value … … reward_detail type daily null … id null 13 … SQL で取り出すときは UNNEST というキーワードを使う。あとで説明。 ※ イベントが発生した画面もイベントパラメータとして持っています。 ©2024 Kyash Inc. 43
Google Analytics for Firebase のイベント送信 アプリを使用している個人 読み方は「スードウ」 … user_id user_pseudo_id … … 8736592 4f7a1e2b… … … 2941365 7c2d1e8f… … … 1721463 1d3e7c9a… … Firebase SDK の FirebaseAnalytics.setUserId メ ソッドで設定した文字列 ● ● 自動で設定 同じデバイスの同じアプリはずっ と同じ文字列 ※ 乱数で作ったデータです。実際のデータではありません。 ©2024 Kyash Inc. 44
Google Analytics for Firebase のイベント送信 アプリを使用している個人 活用方法 ● ある操作をした人数を調べる ● 特定個人の行動に注目した分析 setUserId メソッド ● バックエンド側で付与して保存された ユーザIDを設定すると、バックエンドの データと結合して分析することができて 便利 ● ©2024 Kyash Inc. 注意点もあるので、あとで改めて説明 45
Google Analytics for Firebase のイベント送信 デバイスや OS の情報 … device. mobile_model_name device. operating_system device. operating_system_version … … Pixel 8 Pro Android Android 14 … … iPhone 15 Pro iOS iOS 17.5.1 … … Pixel 6a Android Android 13 … iOS / Android 別に 人数を集計 minSdk を上げるに当たってサポート対象外 になる人数を集計することができる。 ※ フィールドは一部抜粋 ©2024 Kyash Inc. 46
Google Analytics for Firebase のイベント送信 BigQuery の SQL の例 直近2週間で銀行選択画面を見た人数を iOS / Android 別に集計 ● SQL は長いので、今回は完璧な理解を目指さず、イメージだけ持ち帰って頂けると幸いです ○ ● この発表の主題は分析することでなく、イベントを送ること 付録に参考資料を紹介しているので、必要に応じてご参照ください ©2024 Kyash Inc. 47
Google Analytics for Firebase のイベント送信 OS と人数 SELECT device.operating_system AS os, COUNT(DISTINCT user_pseudo_id) AS count FROM テーブル名の日付部分は WHERE 句で _TABLE_SUFFIX を限定 firebase-kyash.analytics_153671808.events_*, UNNEST(event_params) AS p WHERE イベントパラメータは UNNEST で分解 _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 14 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)) AND event_name = 'screen_view' AND p.key='firebase_screen' AND event_name, key, value を限定 p.value.string_value='BankList' GROUP BY os ©2024 Kyash Inc. OS 別集計にする 48
Google Analytics for Firebase のイベント送信 BigQuery の集計に使えるツール BigQuery Studio (Google Cloud の画面) ©2024 Kyash Inc. 49
Google Analytics for Firebase のイベント送信 BigQuery の集計に使えるツール 表やグラフをチームで共有したい ファネル分析スプレッドシート Google スプレッドシート (クラウド表計算ソフト) 1. 上部メニュー 2. データ 3. データコネクタ 4. BigQuery に接続 5. カスタムクエリを作成 6. SQL を入力することで数字を取り込める ©2024 Kyash Inc. 50
Google Analytics for Firebase のイベント送信 A/B テストで使うツール もっと簡単に実行したい BigQuery Google スプレッドシート ©2024 Kyash Inc. Firebase A/B Testing 51
Google Analytics for Firebase のイベント送信 少し統計学の話 10人 10人 1000人 1000人 A B A B 4人 6人 偶然 期待する操作 ©2024 Kyash Inc. 600人 偶然でない 期待する操作 面倒見てくれる 有意差検定 400人 Firebase A/B Testing 52
Google Analytics for Firebase のイベント送信 A B Firebase Remote Config ● ● 期待する操作 ユーザの振り分け コード上の分岐 期待する操作 Firebase A/B Testing イベント送信 イベント送信 ● ● ユーザ数を集計 有意差検定 詳細な設定方法は公式ドキュメントをご参照ください ©2024 Kyash Inc. 53
Google Analytics for Firebase のイベント送信 予備知識の紹介完了 保存、分析、活用 ユーザ 操作 イベント送信 ● ● ● BigQuery Google スプレッドシート Firebase A/B Testing 実装が不適切ならば データの活用どころでは ない ©2024 Kyash Inc. 54
適切なイベント送信実装 ● 画面遷移イベント送信 ● ユーザID設定 ©2024 Kyash Inc. 55
適切なイベント送信実装 - 画面遷移イベント送信 画面遷移イベント送信 Activity クラス名が自動設定 iOS では ○○ViewController イベントパラメータ screen_class = BankListActivity イベント名 screen_view 任意に設定 イベントパラメータ SDK に定数定義 screen_name = BankList イベントパラメータ名は BigQuery では firebase_screen_class, firebase_screen になる ©2024 Kyash Inc. 56
適切なイベント送信実装 - 画面遷移イベント送信 オススメ 画面遷移イベントはすべての画面について送る ©2024 Kyash Inc. 57
適切なイベント送信実装 - 画面遷移イベント送信 すべての画面で画面遷移イベントを送っていない場合 KPI改善 したい イベント 送信実装 リリース イベント 蓄積 この間1ヶ月 ©2024 Kyash Inc. 58
適切なイベント送信実装 - 画面遷移イベント送信 すべての画面で画面遷移イベントを送っている場合 KPI 改善 したい ©2024 Kyash Inc. ファネル分析 59
適切なイベント送信実装 - 画面遷移イベント送信 Android における3種類の画面遷移 Activity ©2024 Kyash Inc. Fragment Compose Jetpack Navigation Navigation Compose 60
適切なイベント送信実装 - 画面遷移イベント送信 Firebase SDK による自動イベント送信 自動送信 Activity イベント名 screen_view イベントパラメータ(BigQuery) firebase_screen_class = Activity クラス名 iOS では ViewController クラス名 ©2024 Kyash Inc. 61
適切なイベント送信実装 - 画面遷移イベント送信 Fragment Compose Jetpack Navigation Navigation Compose 自分で 画面遷移イベント送信を 実装 ©2024 Kyash Inc. 62
適切なイベント送信実装 - 画面遷移イベント送信 画面遷移イベント送信の実装方法 ライフサイクル onCreate ここでイベント送信 ● onStart ● 公式ドキュメントで推奨 ○ スクリーンを手動で追跡する 別の画面を呼び出し、そこから戻ってきた時もイベント送信 onResume ©2024 Kyash Inc. 63
適切なイベント送信実装 - 画面遷移イベント送信 画面遷移イベント送信の実装例 ©2024 Kyash Inc. Fragment Compose Jetpack Navigation Navigation Compose 64
適切なイベント送信実装 - 画面遷移イベント送信 Fragment の画面遷移イベント送信実装例 fun Fragment.sendScreenEvent( analyticsEventSender: AnalyticsEventSender, screenName: String, ) { this.viewLifecycleOwner.lifecycle.addObserver( object : DefaultLifecycleObserver { override fun onResume(owner: LifecycleOwner) { // Firebase の SDK をラップしたメソッドを呼び出し analyticsEventSender.sendScreen(screenName) } }, ) } ©2024 Kyash Inc. 65
適切なイベント送信実装 - 画面遷移イベント送信 Fragment の画面遷移イベント送信実装例 @AndroidEntryPoint class BankListFragment : Fragment() { @Inject lateinit var analyticsEventSender: AnalyticsEventSender } override fun onViewCreated( 文字列リテラルでの画面名指定 view: View, が気になるが、あとでより良い 方法を紹介 savedInstanceState: Bundle?, ) { super.onViewCreated(view, savedInstanceState) sendScreenEvent(analyticsEventSender, “BankList”) } ©2024 Kyash Inc. 66
適切なイベント送信実装 - 画面遷移イベント送信
Compose の画面遷移イベント送信実装例
@Composable
書き方は公式ドキュメント
fun SendScreenEvent(
analyticsEventSender: AnalyticsEventSender, DisposableEffect: クリーン
アップが必要な作用
screenName: String,
を参考にした
) {
val owner = LocalLifecycleOwner.current
DisposableEffect(owner) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME) {
analyticsEventSender.sendScreen(screenName)
}
}
owner.lifecycle.addObserver(observer)
onDispose { owner.lifecycle.removeObserver(observer) }
}
}
©2024 Kyash Inc.
67
適切なイベント送信実装 - 画面遷移イベント送信 Compose の画面遷移イベント送信実装例 @Composable fun BankListScreen( viewModel: BankListViewModel, analyticsEventSender: AnalyticsEventSender, ) { SendScreenEvent(analyticsEventSender, “BankList”) Scaffold(/* 略 */) { /* 略 */ } } ©2024 Kyash Inc. 68
適切なイベント送信実装 - 画面遷移イベント送信 実装を忘れそう ユーザIDを 適切に設定する 自動チェックの 仕組みを紹介 ©2024 Kyash Inc. 69
適切なイベント送信実装 - ユーザID設定 バックエンドのデータ ● ● ユーザの状態 ○ 本人確認済み ○ 有料サブスクリプション契約 過去に経験 ○ 取引履歴 ○ コミュニケーションの履歴 得意とするデータ分析が異なる ©2024 Kyash Inc. Analytics のデータ ● 画面遷移 ● 操作内容 ユーザの行動を追うような 分析が得意 結合して分析したい 70
適切なイベント送信実装 - ユーザID設定 ユーザIDを付与、保存 バックエンド サーバサイド アプリケーション FirebaseAnalytics. setUserId を使用 リレーショナル データベース ユーザID 受け取り モバイルアプリ ©2024 Kyash Inc. 71
適切なイベント送信実装 - ユーザID設定 Analytics のデータ バックエンドのデータ … event_name user_id … user_id kyc subscription … kyc_top 36592 … 94007 true false … select_bank 41365 … 36592 false false … screen_view 21463 … 87148 true true user_id で結合して集計 ※ 乱数で作ったデータです。実際のデータではありません。 ©2024 Kyash Inc. 72
適切なイベント送信実装 - ユーザID設定 setUserId メソッドを呼び出すタイミング ● ユーザ登録 ● ログイン ○ 端末変更のため、アプリを新たにインストールあとのログイン プロセス復帰時に自動ログインするケースでは Firebase SDK にユーザIDが保持されているので不要 ©2024 Kyash Inc. 73
適切なイベント送信実装 - ユーザID設定 setUserId メソッドを呼び出すタイミング ● ログアウト ● 退会 ©2024 Kyash Inc. null を設定 74
適切なイベント送信実装 - ユーザID設定 基本的な内容では🤔 ● setUserId メソッド呼び出しは、機能改修やリファクタリングが行われる中で、失われることがあ る ○ 実際そうなってしまったアプリを見たことがある ○ ユーザ登録やログインは開発初期に作られて、歴史があるアプリだと RxJava や AsyncTask など古い技術が使われていて、あるタイミングで大規模にリファクタリングが 行われることが多い Firebase SDK へのユーザID設定を適切に実装することを 開発メンバーが入れ替わっても途絶えず継承したい ©2024 Kyash Inc. 75
適切なイベント送信実装 - ユーザID設定 setUserId メソッド呼び出し抜け対策 ● ソースコードに注意書きのコメントを付ける ● 自動監視を設定 バックエンドから アクティブユーザ数を取得 Analytics のユーザIDの ユニーク数を集計 毎週 Bot が比較 開発者に通知 ©2024 Kyash Inc. 76
適切なイベント送信実装 - ユーザID設定 これまでの話 1. 「データに基づく意思決定」の例 2. モバイルエンジニアがそれを「支える」ため 最後の話 適切に実装し続けるチームを作る にイベント送信に注力 3. 「Google Analytics for Firebase の イベント送信」の予備知識 4. 画面遷移イベント送信とユーザIDの設定 自動化 GitHub Actions / コード生成 / detekt カスタムルール ©2024 Kyash Inc. 77
適切に実装し続ける チームを作るための 自動化 ©2024 Kyash Inc. 78
適切に実装し続けるチームを作るための自動化 イベント送信実装の課題 1. 文字数制限やイベント名の種類数制限を超えたイベントを送信してしまう 2. iOS と Android でイベント名やイベントパラメータが違う 3. イベントの仕様が適切に共有されてない ○ 4. PdM など Analytics イベントを分析するすべての人が対象 画面遷移イベント送信の実装が抜けたままリリースしてしまう ©2024 Kyash Inc. 79
適切に実装し続けるチームを作るための自動化 文字数制限 最大40文字 イベント イベント名 超えると エラー 最大40文字 Key 複数 イベント パラメータ Value String 型の Value も100文字制限があり、別途注意が必要 ©2024 Kyash Inc. 80
適切に実装し続けるチームを作るための自動化 イベント名は最大500種類 Firebase 公式ドキュメントに記載 細かい条件は[GA4] イベントの収集に適用される上限に記載あり ● 1ユーザ1日の種類数制限 ● 自動送信のイベントは上限の対象に含まない ©2024 Kyash Inc. 81
適切に実装し続けるチームを作るための自動化 イベント名500種類を超えないイベント設計 すべてのイベントについてイベント名を割り当てると、500種類は容易に超える 上限 画面遷移イベント 画面内操作 500種類 400種類 100種類 ©2024 Kyash Inc. 82
適切に実装し続けるチームを作るための自動化 イベントパラメータで画面や操作を区別 Kyash 独自の運用 画面遷移イベント 画面内操作イベント イベント名 イベント名 screen_view select_content イベントパラメータ イベントパラメータ screen_name = 画面名 kyash_action_name = 操作名 ©2024 Kyash Inc. 83
適切に実装し続けるチームを作るための自動化 イベント名を使いたい時 A B 期待する操作 期待する操作 イベント送信 イベント送信 Firebase A/B Testing ● ● ユーザ数を集計 有意差検定 集計はイベント名のみ ©2024 Kyash Inc. 84
適切に実装し続けるチームを作るための自動化 イベント名は必要な時だけ定義 そうで無い時はイベントパラメータの value で区別 ©2024 Kyash Inc. 85
適切に実装し続けるチームを作るための自動化 イベント送信実装の課題 文字数制限 イベント種類数制限 iOS / Android で イベントが違う イベントの仕様共有 自動コード生成を用いたソリューション Kyash 社の先人が構築、運用 ©2024 Kyash Inc. 86
適切に実装し続けるチームを作るための自動化 イベント構造体 YAMLファイル イベント仕様を定義 検証 ● ● 文字数 イベント種類数 SwiftPoet KotlinPoet イベントクラス イベント仕様書 ©2024 Kyash Inc. 87
適切に実装し続けるチームを作るための自動化 リポジトリ構成 iOSアプリ リポジトリ イベント定義 リポジトリ ● ● ● YAMLファイル 検証 コード生成 ©2024 Kyash Inc. main マージ GitHub Actions プルリク作成 Androidアプリ リポジトリ 88
適切に実装し続けるチームを作るための自動化 Android 向け自動生成コード object AnalyticsEvent { Analytics に送る文字列 sealed class Screen( public val eventName: String, public val isConversionEvent: Boolean, ) { イベント名か イベントパラメータのvalueか (Firebase A/B Testing 利 用、500種類制限回避) data object BankList : Screen("BankList", false) data object DepositSuccess : Screen("DepositSuccess", true) } // 続く } ©2024 Kyash Inc. 89
適切に実装し続けるチームを作るための自動化 iOS 向け自動生成コード protocol AnalyticsEventScreen { var eventName: String { get } var isConversionEvent: Bool { get } protocol は Kotlin でいう interface } enum AnalyticsEvent { enum Screen { enum は名前空間としての 利用 struct BankList : AnalyticsEventScreen { let eventName: String = "BankList" let isConversionEvent: Bool = false } } // 以下略 ©2024 Kyash Inc. 90
適切に実装し続けるチームを作るための自動化
画面内操作イベントの自動生成コード(Android)
object AnalyticsEvent {
sealed class Action(
val eventName: String,
パラメータを持てるようにしている
val eventParameters: Map<String, Any>,
val isConversionEvent: Boolean,
) {
// 次のページで紹介
}
}
©2024 Kyash Inc.
91
適切に実装し続けるチームを作るための自動化 画面内操作イベントの自動生成コード(Android) object BankList { 所属する画面 data class ClickBank( イベント パラメータの value val bankCode: String, ) : Action( 銀行選択画面で 銀行がクリックされたら 銀行コードと一緒に イベント送信 eventName = "BankListClickBank", eventParameters = mapOf("bank_code" to bankCode), 画面名 + 操作名で 自動生成される isConversionEvent = false, ) } ©2024 Kyash Inc. 92
適切に実装し続けるチームを作るための自動化 イベント送信担当インターフェース(Android) interface AnalyticsEventSender { fun sendScreen(screen: AnalyticsEvent.Screen) fun sendAction(action: AnalyticsEvent.Action) } 未定義のイベントは送信できない ©2024 Kyash Inc. 93
適切に実装し続けるチームを作るための自動化 - description: 銀行選択画面 YAML ファイル class: BankList value: BankList description は説明文 ● ● ● class, property は Swift / Kotlin 上での表現 value は Analytics に送信するイベ ント名 key は Analytics に送信するイベント パラメータの key 可読性と40文字制限の両立のために、違うも のを設定することが可能 conversion は500種類制限のあるイベン ト名にするかのフラグ ©2024 Kyash Inc. conversion: false actions: - description: 銀行がクリックされた class: ClickBank value: ClickBack parameters: - description: 銀行コード property: bankCode key: bank_code type: string 94
適切に実装し続けるチームを作るための自動化 KotlinPoet 使用イメージ ● ● SwiftPoet も同じような使用方法 詳細は最後に紹介するサンプルコード参照 生成するコード KotlinPoet /** * Analytics イベントクラス群 */ public object AnalyticsEvent { /* 次のページ */ } TypeSpec .objectBuilder("AnalyticsEvent") .addKdoc("Analytics イベントクラス群 ") .addType( /* ネストするクラスを追加 */ ).build() ©2024 Kyash Inc. 95
適切に実装し続けるチームを作るための自動化 KotlinPoet 使用イメージ 生成するコード /** * 銀行選択画面 */ public data object BankList : Screen("BankList", false) ©2024 Kyash Inc. 96
適切に実装し続けるチームを作るための自動化 KotlinPoet 使用イメージ KotlinPoet TypeSpec .objectBuilder("BankList") .addKdoc("銀行選択画面 ") .addModifiers(KModifier.DATA) // data object にする .superclass(ClassName(PACKAGE, "AnalyticsEvent").nestedClass("Screen")) // 親クラスのコンストラクタパラメータを設定 .addSuperclassConstructorParameter("%S", "BankList") .addSuperclassConstructorParameter("%L", false) .build() ©2024 Kyash Inc. 97
適切に実装し続けるチームを作るための自動化 SwiftPoet / KotlinPoet のメリット 文字列結合よりも直感的で保守しやすい Swift / Kotlin コード自動生成システムを作ることができ る。 ©2024 Kyash Inc. 98
適切に実装し続けるチームを作るための自動化 画面遷移イベント送信の実装抜けを防ぐ自動化 ● うっかり実装を忘れてリリースしてしまうことを防ぐ ● メンバーが入れ替わっても適切にイベント送信を実装し続けるチーム体制を 作る ©2024 Kyash Inc. 99
適切に実装し続けるチームを作るための自動化 プルリクに自動コメント ©2024 Kyash Inc. 100
適切に実装し続けるチームを作るための自動化 チェック対象の画面遷移イベント送信実装 // 1画面に1つの Screen で終わる Composable 関数 @Composable fun BankListScreen( viewModel: BankListViewModel, analyticsEventSender: AnalyticsEventSender, ) { // 画面遷移イベント送信を行う SendScreenEvent(analyticsEventSender, AnalyticsEvent.Screen.BankList) } Scaffold(/* 略 */) { /* 略 */ } チェック項目 Screen で終わる Composable 関数内で SendScreenEvent 関数が呼ばれている ©2024 Kyash Inc. 101
適切に実装し続けるチームを作るための自動化 detekt カスタムルールを使用 detekt とは カスタムルール ● Kotlin 言語の静的コード解析ツール ● Kotlin で開発 ● 1関数が長すぎる、マジックナンバーを ● Android プロジェクトにカスタムルール ● 使っている等のコードの匂いを検出してレ を追加する方法の参考文献 ポートとして出力する ○ reviewdog でプルリクにコメント Detekt for Android— How To Make Your Own Custom Rule ● ©2024 Kyash Inc. 今回は実装のコアな部分を紹介 102
適切に実装し続けるチームを作るための自動化 detekt カスタムルールの作り方 Kotlin の抽象構文木(AST)に対する処理を作成 Property val b = BinaryExpression 1 + BinaryExpression Kotlin ソースコード val b = 1 + 2 * a 2 ©2024 Kyash Inc. * a 103
適切に実装し続けるチームを作るための自動化 抽象構文木の閲覧方法 Android Studio で閲覧可能 PSI Viewer という機能を使う (PSI = Program Structure Interface) デフォルト設定ではアクセス出来ないので 公式ガイドの Enabling Internal Mode を参考に有効化する 抽象構文木を見たいファイルを開いて Tool → View PSI Structure of Current File ©2024 Kyash Inc. 104
適切に実装し続けるチームを作るための自動化 カスタムルールの実装コード(一部抜粋) class SendScreenEvent(config: Config) : Rule(config) { /** * 抽象構文木から関数定義を見つけたときに呼ばれる。 */ override fun visitNamedFunction(function: KtNamedFunction) { } /** * 抽象構文木から関数呼び出しを見つけたときに呼ばれる。 */ override fun visitCallExpression(expression: KtCallExpression) { } } ©2024 Kyash Inc. 105
適切に実装し続けるチームを作るための自動化
カスタムルールの実装コード(一部抜粋)
private var sendScreenEventIsCalled = false
override fun visitCallExpression(expression: KtCallExpression) {
super.visitCallExpression(expression)
expression.getCalleeExpressionIfAny().let { func ->
if (func?.text == "SendScreenEvent") {
// SendScreenEvent 関数呼び出しが見つかったらフラグを true にする
sendScreenEventIsCalled = true
}
}
}
©2024 Kyash Inc.
106
適切に実装し続けるチームを作るための自動化
カスタムルールの実装コード(一部抜粋)
override fun visitNamedFunction(function: KtNamedFunction) {
super.visitNamedFunction(function)
中身は
@Composable
アノテーションの確認
// Screen で終わる Composable 関数を見つけたら
if (function.name?.endsWith("Screen") == true && isComposable(function)) {
// 先ほどの SendScreenEvent 関数が呼ばれたフラグをチェック。
// false の場合は Issue として報告する。
// 階層が深い方が先に処理される - 関数定義よりも関数呼び出しのチェックの方が先に行われるので
// この実装で要件を満たせる。
if (!sendScreenEventIsCalled) {
report(CodeSmell(issue, Entity.from(function), REPORT_MESSAGE))
}
}
sendScreenEventIsCalled = false
}
©2024 Kyash Inc.
107
まとめと補足 ©2024 Kyash Inc. 108
まとめ データに基づく意思決定 ● ● ● KPI分析 ファネル分析 ABテスト ● ● 画面遷移イベント ユーザIDの設定 予備知識 ● 保存形式 ● 分析ツール モバイルエンジニアが注力 Analytics のイベント送信 課題 ● ● ● ● 文字数、種類数制限の超過 iOS / Android でイベントが違う 仕様の共有 実装抜け ©2024 Kyash Inc. 自動化で解決 109
まとめ 2つの自動化ソリューションを紹介 画面遷移イベントイベント送信 YAML ファイルにイベント仕様定義 実装抜けを検出 ● 検証 ● 仕様書、Swift 構造体、Kotlin クラス自 ● detekt カスタムルールを活用 動作成 ©2024 Kyash Inc. 110
補足 ソリューションはひとつでない イベント構造体 YAML ファイル detekt カスタムルール コード生成 イベントクラス 一例であり唯一の選択肢ではない ©2024 Kyash Inc. 111
補足 Kotlin Multiplatform でイベント定義 iOSアプリ Kotlin でイベントクラス作成 CI で文字数チェック イベント仕様書 ©2024 Kyash Inc. ライブラリ提供 Androidアプリ 詳細は付録の サンプルコード参照 112
補足 イベント送信実装抜けチェックに Konsist を使えるか検討 detekt カスタムルール Konsist 概要 抽象構文木をチェック ローカル単体テストで 実行時型情報をチェック チェックできる項目 多い 少ない 導入ハードル 少し高い 低い ● ● ● ©2024 Kyash Inc. カスタムルール専用モ ジュールを作成 XML ファイルによる設定 抽象構文木に対する理解 ● konsist ライブラリ使ったロー カル単体テストを追加 113
補足 Konsist の使用例 この import 文の 存在をチェック import co.kyash.analytics.sendScreenEvent class BankListFragment : Fragment() { override fun onViewCreated( view: View, savedInstanceState: Bundle?, ) { super.onViewCreated(view, savedInstanceState) sendScreenEvent( analyticsEventSender, AnalyticsEvent.Screen.BankList ) } } ©2024 Kyash Inc. 114
補足 Konsist の使用例 @Test fun checkScreenEventFromFragment() { Konsist.scopeFromProject() // プロジェクトすべてを対象 .files // Kotlin ファイルを列挙 .withNameEndingWith("Fragment") // Fragment で終わるファイルに限定 .assertTrue { // 条件に合致するか確認 it.imports.withName( "co.kyash.analytics.sendScreenEvent", ).isNotEmpty() // 画面遷移イベント送信拡張関数を import している } } // (ワイルドカードインポート不使用はフォーマッタで保証する ) ©2024 Kyash Inc. 115
補足 ソースコード ● イベント定義リポジトリ ○ ● iOS アプリリポジトリ ○ ● https://github.com/tfandkusu/ga913-ios detekt カスタムルールと Konsist の活用もこちら Android アプリリポジトリ ○ ● https://github.com/tfandkusu/ga913-yaml https://github.com/tfandkusu/ga913-android Kotlin Multiplatform によるイベント定義リポジトリ ○ ©2024 Kyash Inc. https://github.com/tfandkusu/ga913-kmp 116
まとめ Analytics イベント送信を 適切に実装し続けるチームを作る データに基づく意思決定を支える ©2024 Kyash Inc. 117
ありがとうございました 続いて付録と謝辞です ©2024 Kyash Inc. 118
付録 BigQuery に保存された Analytics イベントを分析する SQL の解説リンク event_params フィールドの取り扱い方について、分かりやすく解説している記事を紹介します。 ● GoogleAnalytics 4 のイベントを BigQuery で集計する ● BigQuery の UNNEST 関数を使って GoogleAnalytics のデータを取得する方法 ©2024 Kyash Inc. 119
付録 Analytics イベント送信のデバッグ方法 Analytics イベント送信のデバッグ方法に公式では logcat を使う方法と DebugView を使う方法 がありますが、アプリにオーバレイデバッグ表示機能を実装する方法を提案したことがあります。 ©2024 Kyash Inc. 120
謝辞 発表内容への助言 ● 株式会社Kyash ○ モバイルチームの皆様 ○ 執行役員 VPoE の Konifar さん ○ PdM の ikushige さん ○ デザイナーの hosoda さん ©2024 Kyash Inc. 発表準備の息抜き スプラトゥーンのいつメン 121