SlideShare a Scribd company logo
DroidKaigi 2018 @cattaka_net
アプリを成長させるための
ログ取りとログ解析に必要なこと
Takao Sumitomo
DroidKaigi 2018 @cattaka_net2
自己紹介
DroidKaigi 2018 @cattaka_net3
自己紹介
●
住友 孝郎(Takao Sumitomo)
●
たぶんAndroidアプリ開発者
●
職歴的なもの
– SIer的なこと
– メーカー的なこと
●
– 2014年12月〜
所属
DroidKaigi 2018 @cattaka_net4
Wantedlyプロフィール
DroidKaigi 2018 @cattaka_net5
触ったことあるもの
プログラム
Java, C++, Ruby,
PHP, Python
データベース
Oracle, Sqlite3,
PostgreSQL,
MySQL, Realm
プラットフォーム等
Android,
Linux(Debian),
MFC, Struts
設計
UML, Excel方眼紙
DroidKaigi 2018 @cattaka_net6
Javaが好き
DroidKaigi 2018 @cattaka_net7
今日のお話に至った経緯
DroidKaigi 2018 @cattaka_net8
Wantedlyにジョインする前
●
いっぱいいろんなものを作った
●
作るだけならどうにかできる
DroidKaigi 2018 @cattaka_net9
不思議なことをいう人達がいた
●
良いものを作れば自然とユーザーは増える
●
面白いものを作ればバイラルで広がる
本当にそうなのか?
DroidKaigi 2018 @cattaka_net10
そんな中でWantedlyにジョインした
DroidKaigi 2018 @cattaka_net11
ジョイン直後
アプリを良くしていきましょう!
(どうやったらいいんだろう...)
DroidKaigi 2018 @cattaka_net12
最初にやったこと
●
Google Analyticsを見た
– 当時はまだFirebase Analyticsはなかった
●
TreasureData(ログ収集サービス)を見た
ほとんどWebのログ
体系化されてなくて読み取れない
わかるのはせいぜいインストール数とアクティブユーザー数
DroidKaigi 2018 @cattaka_net13
そもそも何をもって良くなったいう?
●
指標は?
●
その指標の数字を出すためには?
うん、さっぱりわからん
DroidKaigi 2018 @cattaka_net14
Wantedly Visitの例を考える
DroidKaigi 2018 @cattaka_net15
最も簡単な指標
●
マッチングアプリ
– 応募ボタンを押す
DroidKaigi 2018 @cattaka_net16
1 2 3 4 5
0.00%
10.00%
20.00%
30.00%
40.00%
50.00%
60.00%
70.00%
80.00%
90.00%
100.00%
応募にたどり着くまでのファネル
それまでの過程は?
●
1: インストール
●
2: ユーザー登録
●
3: 探す操作をする
●
4: 詳細画面を開く
●
5: 応募を押す
こんな感じ??
DroidKaigi 2018 @cattaka_net17
その過程を追うには?
●
インストール
– ユーザーIDごとの最初のイベントを探す
●
ユーザー登録
– Web側かアプリ側のログ
●
探す操作をする
– アプリ側のログ
DroidKaigi 2018 @cattaka_net18
その過程を追うには?
●
詳細画面を開く
– アプリ側のログ
– キャッシュされるとWeb側のログじゃわからない
●
応募を押す
– Web側のログ
ログがWeb側とアプリ側に散らばってる、、、
DroidKaigi 2018 @cattaka_net19
あ、、、これ闇雲にやっても無理だ、、、
DroidKaigi 2018 @cattaka_net20
そのためにやったことのお話です
DroidKaigi 2018 @cattaka_net21
どんな指標があるのか?
DroidKaigi 2018 @cattaka_net22
エンジニアリング的な指標
●
クラッシュ率
●
ANR発生率
●
レンダリング時間
●
APIのレスポンス時間
Android Vitals で確認できる
DroidKaigi 2018 @cattaka_net23
非エンジニアリング的な指標
Google Play Console,
Firebase Analytics で確認できる
DroidKaigi 2018 @cattaka_net24
インストール数
●
単純にインストール数
DroidKaigi 2018 @cattaka_net25
アクティブユーザー数
●
DAU : Daily Active User
– 1日のユニークユーザー数
●
WAU : Weekly Active User
– 7日間のユニークユーザー数
●
MAU : Monthly Active User
– 1ヶ月のユニークユーザー数
– 流派によって28日だったり31日だったりする
単純に掛け算ではないので注意
DroidKaigi 2018 @cattaka_net26
リテンション率
●
継続率とも呼ばれる
●
コホート分析とも呼ばれる
– (厳密には違うけど)
●
期間ごとにユーザーを分けて見る
DroidKaigi 2018 @cattaka_net27
リテンション率
Firebase Analyics – demo projectより
DroidKaigi 2018 @cattaka_net28
リテンション率
●
多機能なアプリの場合
– 機能ごとのリテンション率が無いと
どの機能がユーザーを繋ぎ止めてるか追えない
DroidKaigi 2018 @cattaka_net29
コンバージョン率
●
ユーザーの中でコンバージョンした率
●
コンバージョン
– そのプロダクトの成果
– たとえば
●
ECサービスなら何かが売れた
●
マッチングサービスならマッチングが成立した
プロダクトによって異なる
DroidKaigi 2018 @cattaka_net30
必要なインフラ
DroidKaigi 2018 @cattaka_net31
簡単な構成
●
ログ収集サービス
●
データストア
●
抽出環境
●
可視化
DroidKaigi 2018 @cattaka_net32
具体的なサービスやプロダクト
ログ収集系
データストア
抽出環境
可視化
Firebase
Analytics
※1
Google
BigQuery
Google Data
Studio(β) ExcelR
Domo
Fluentd
普通の
RDBMS
Treasure
Data
Hadoop
※1:Firebase Analyticsは一部可視化機能がある
DroidKaigi 2018 @cattaka_net33
ログ収集系
Treasure
Data
Google
BigQuery
最近のWantedlyの構成の紹介
データストア
抽出環境
可視化
Firebase
Analytics
Excel
Domo
普通の
RDBMS
アプリ
DroidKaigi 2018 @cattaka_net34
ここまでで、お気づきの方も
いらっしゃるかも知れませんが...
DroidKaigi 2018 @cattaka_net35
アプリの実装の話が1つも出てません
DroidKaigi 2018 @cattaka_net36
最近のWantedlyの構成の紹介
ログ収集系
Treasure
Data
Google
BigQuery
データストア
抽出環境
可視化
Firebase
Analytics
Excel
Domo
普通の
RDBMS
アプリ
この2つを考えるのに、
中間層の理解が必要だった
DroidKaigi 2018 @cattaka_net37
初めてやるなら
●
Firebase Analytics
●
Google BigQuery
●
Excel
の組み合わせから始めると無難
DroidKaigi 2018 @cattaka_net38
アプリで取るログの種類
DroidKaigi 2018 @cattaka_net39
アプリで取るログの種類
●
イベントログ
– Viewの操作
●
タップやスワイプ
– 直接的なコンバージョン
●
スクリーンログ
– 画面名
– 遷移先の画面名
– 滞在時間
DroidKaigi 2018 @cattaka_net40
イベントログ
DroidKaigi 2018 @cattaka_net41
イベントログの項目
●
ユーザー識別子
●
画面名
– アプリによってはActivity + Fragment
●
イベント名
– タップ / ロングタップ / スワイプなど
●
イベントの追加属性
– View ID / アイテムのIDなど
– 内部実装はJSONが良いかも(?)
DroidKaigi 2018 @cattaka_net42
イベントログの例
ユーザー
識別子
画面名
イベント名
イベントの
追加属性画面の
追加属性
time user_id screen screen_params event event_params
1234 ListActivity click {"view_id": "title", "item_id": 432}
1234 DetailActivity {"item_id": 432} press_back
1234 ListActivity click {"view_id": "title", "item_id": 234}
1234 DetailActivity {"item_id": 234} click {"view_id": "apply"}
1234 DetailActivity {"item_id": 234} cvt_apply {"item_id": 234}
2018/02/09
12:30
2018/02/09
12:31
2018/02/09
12:32
2018/02/09
12:33
2018/02/09
12:33
DroidKaigi 2018 @cattaka_net43
イベントログのアプローチ
●
自動的にできれば理想だけど、、、
– touchイベントをフックすればできなくはない
– 付加情報を追加せざるを得ないケースが多い
– 過度に冗長になることがある
– デザイン的な事情の独自実装に対応できない
要所要所に丹精込めて埋める
DroidKaigi 2018 @cattaka_net44
Viewの操作 vs コンバージョン
●
どっちが解析しやすいか?
– Viewの操作として記録
– コンバージョンとして記録
●
ツールに寄る
– FAはコンバージョンが扱いやすい
time user_id screen screen_params event event_params
1234 DetailActivity {"item_id": 234} click {"view_id": "apply"}
1234 DetailActivity {"item_id": 234} cvt_apply {"item_id": 234}
2018/02/09
12:33
2018/02/09
12:33
※:2つはユーザーの操作としては同じ
重要な指標だから両方取る
DroidKaigi 2018 @cattaka_net45
ライブラリごとの実装の違い
DroidKaigi 2018 @cattaka_net46
イベントログの実装:Treasure Data
Map<String, Object> event = new HashMap<>();
event.put("user_id", userId);
event.put("activity", activityName);
event.put("fragment", fragmentName);
event.put("event", "select_cotent");
event.put("item_id", itemId);
event.put("name", name);
TreasureData.sharedInstance()
.addEvent("event_log", event);
ユーザー識別子
画面
イベント名
追加属性
全部自分でやる!
DroidKaigi 2018 @cattaka_net47
イベントログの実装:Firebase Analytics
Bundle bundle = new Bundle();
bundle.putLong
(FirebaseAnalytics.Param.ITEM_ID, itemId);
bundle.putString
(FirebaseAnalytics.Param.ITEM_NAME, name);
bundle.putString
(FirebaseAnalytics.Param.CONTENT_TYPE, "image");
mFirebaseAnalytics.logEvent(
FirebaseAnalytics.Event.SELECT_CONTENT, bundle);
↓追加属性
↑イベント名
画面やユーザー識別子はやってくれる
DroidKaigi 2018 @cattaka_net48
イベントログの実装:Google Analytics
mTracker.send(new HitBuilders.EventBuilder()
.setCategory(category.category)
.setAction("select_content")
.setNonInteraction(false)
.build()); ↑イベント名
画面やユーザー識別子はやってくれる
DroidKaigi 2018 @cattaka_net49
ライブラリごとの実装の違い
●
TD, FA, GAでそれぞれ微妙に違う
●
特に画面とイベントの紐付けが異なる
DroidKaigi 2018 @cattaka_net50
スクリーンログ
DroidKaigi 2018 @cattaka_net51
スクリーンログの項目
●
画面遷移が追えるくらい取る
●
アプリからの離脱もわかるようにする
リスト画面
商品画面
item_id=3
関連商品
item_id=3
商品画面
item_id=7
アプリを起動
アプリから離脱
DroidKaigi 2018 @cattaka_net52
スクリーンログの項目
●
ユーザー識別子
●
画面名
– アプリによっては Activity + Fragment
– 追加の属性
●
次の画面名
●
滞在時間
– ミリ秒やナノ秒
DroidKaigi 2018 @cattaka_net53
スクリーンログの例
画面名
画面の
追加属性
次の画面の
追加属性
次の画面名 滞在時間
time user_id screen screen_params next_screen next_params duration
1234 ListActivity DetailActivity {"item_id": 432} 46231
1234 DetailActivity {"item_id": 432} ListActivity 82323
1234 ListActivity DetailActivity {"item_id": 234} 53341
1234 DetailActivity {"item_id": 234} 72652
2018/02/09
12:30
2018/02/09
12:31
2018/02/09
12:32
2018/02/09
12:33
DroidKaigi 2018 @cattaka_net54
スクリーンログのアプローチ
●
ActivityやFragment単位で取る
●
トラッカーを埋める場所
– onStart / onResume
– onStop / onPause
●
onStart 〜 onStop で滞在時間が出せる
– FAは滞在時間は自動でやってくれる
DroidKaigi 2018 @cattaka_net55
ライブラリごとの実装の違い
DroidKaigi 2018 @cattaka_net56
スクリーンログの実装:Treasure Data
Map<String, Object> event = new HashMap<>();
event.put("user_id", userId);
event.put("activity", activity);
event.put("fragment", fragment);
event.put("params", params);
event.put("next_activity", nextActivityName);
event.put("next_fragment", nextFragmentName);
event.put("next_params", nextParams);
event.put("duration", duration);
TreasureData.sharedInstance()
.addEvent("screen_log", event);
全部自分でやる!
ユーザー識別子
画面
次の画面
滞在時間
※:onStopなどに書く
DroidKaigi 2018 @cattaka_net57
スクリーンログの実装:Firebase
Analytics
mFirebaseAnalytics.setCurrentScreen(
activity, // Activity
"DetailActivity", // screenName
null // screenClassOverride
);
滞在時間や次の画面の遷移、
ユーザー識別子はやってくれる
←画面名
※:onStartなどに書く
DroidKaigi 2018 @cattaka_net58
スクリーンログの実装:Google Analytics
mTracker.setScreenName("DetailActivity");
mTracker.send(
new HitBuilders.ScreenViewBuilder().build());
←画面名
※:onStartなどに書く
DroidKaigi 2018 @cattaka_net59
トラッカーの実装Tips
DroidKaigi 2018 @cattaka_net60
トラッカーのコードは簡潔安全にしたい
DroidKaigi 2018 @cattaka_net61
WHY
●
機能の実装者の負荷を減らしたい
●
トラッカー起因のクラッシュは0にしたい
●
トラッカーはミスなく動いてほしい
DroidKaigi 2018 @cattaka_net62
FAでベタで書いたときの問題
Bundle bundle = new Bundle();
bundle.putLong ( "item_id", id );
bundle.putString( "item_name", name );
mFirebaseAnalytics.logEvent("select_content", bundle);
イベント名を定数にしたい
属性名を定数にしたい
値を型安全にしたい
これらは一度コードに散らばると回収不可能になる
DroidKaigi 2018 @cattaka_net63
アプローチ
●
トラッカー用の便利メソッドを作る
– イベントをenum化する
– 属性をGenericsで型のある定数にする
– Generics芸を使った便利メソッドを作る
DroidKaigi 2018 @cattaka_net64
イベントをenum化する
public enum Event {
SELECT_CONTENT("select_content"),
CLICK("click"),
// TODO: イベントはここに追加していく
;
public final String key;
Event(String key) {
this.key = key;
}
}
DroidKaigi 2018 @cattaka_net65
属性をGenericsで型のある定数にする
public class Param<T> {
public static final Param<Long> ITEM_ID =
new Param<>("item_id", BaseBundle::putLong);
public static final Param<String> ITEM_NAME =
new Param<>("item_name", BaseBundle::putString);
String key;
IFunc<T> putFunc;
private Param(String key, IFunc<T> putFunc) {
this.key = key;
this.putFunc = putFunc;
}
public interface IFunc<V> {
void put(Bundle dest, String key, V value);
}
}
DroidKaigi 2018 @cattaka_net66
Generics芸を使った便利メソッドを作る
public <V1, V2> void logEvent(
Event event,
Param<V1> k1,
V1 v1,
Param<V2> k2,
V2 v2
) {
Bundle bundle = new Bundle();
k1.putFunc.put(bundle, k1.key, v1);
k2.putFunc.put(bundle, k2.key, v2);
mFirebaseAnalytics.logEvent(event.key, bundle);
}
// イベント名
// 属性1
// 値1
// 属性2
// 値2
型安全が守られる
型安全が守られる
DroidKaigi 2018 @cattaka_net67
便利メソッドを使った場合
MyTracker.getInstance().logEvent(
Event.SELECT_CONTENT,
Param.ITEM_ID, id,
Param.ITEM_NAME, name);
●
だいぶ短くなった
●
イベント名と属性名が定数化された
●
属性の値が型安全になった
DroidKaigi 2018 @cattaka_net68
このアプローチの課題の考察
●
メソッドチェーンの方が良くない?
●
属性の個数は可変だよね?
DroidKaigi 2018 @cattaka_net69
メソッドチェーンの方が良くない?
MyTracker.getInstance()
.logEvent(Event.SELECT_CONTENT)
.put( Param.ITEM_ID, id )
.put( Param.ITEM_NAME, name )
.send();
たしかに、いいかもしれない、、、けど、、、
これを忘れる事故が起こる
DroidKaigi 2018 @cattaka_net70
属性の個数は可変だよね?
●
諦めて属性の
数ごとに作る
●
RxJavaも
似たことをしてる
●
0〜7個あれば
実用十分
public <V1, V2, V3, V4, V5, V6>
void logEvent(
Event event,
Param<V1> k1, V1 v1,
Param<V2> k2, V2 v2,
Param<V3> k3, V3 v3,
Param<V4> k4, V4 v4,
Param<V5> k5, V5 v5,
Param<V6> k6, V6 v6
) {
Bundle bundle = new Bundle();
k1.putFunc.put(bundle, k1.key, v1);
k2.putFunc.put(bundle, k2.key, v2);
k3.putFunc.put(bundle, k3.key, v3);
k4.putFunc.put(bundle, k4.key, v4);
k5.putFunc.put(bundle, k5.key, v5);
k6.putFunc.put(bundle, k6.key, v6);
mFirebaseAnalytics.logEvent(event.key,
bundle);
}
例:属性が6つの場合
DroidKaigi 2018 @cattaka_net71
僕の結論
●
便利メソッドが泥臭くなるのは諦める
●
機能の実装者の負担を下げることを最優先
DroidKaigi 2018 @cattaka_net72
複数のライブラリを使うときのアプローチ
DroidKaigi 2018 @cattaka_net73
ログ収集サービスは何個入れる?
●
本発表でも既に複数が出ている
– Firebase Analytics
– Google Analytics
– Treasure Data
●
他にも広告用のものも使うことがある
●
理想は1つに絞るべきだが、そうも行かない
DroidKaigi 2018 @cattaka_net74
複数のログ収集サービスへの送り分けは?
●
専用の便利クラスを作る
Firebase
Analytics
Treasure
Data
Google
Analytics
便利クラスイベント
個別にコードを書くと長くなるので
送り分けのコードはここにまとめる
後々、どんな計測系サービスを使うかわからないので、
1つしか使わない場合も作っておいたほうが良い
DroidKaigi 2018 @cattaka_net75
スクリーンログのトラッカー
DroidKaigi 2018 @cattaka_net76
個別にコードを入れるのは大変
●
対策1
– BaseActivity や BaseFragment を作る
●
onStart や onStop などに仕込む
public class BaseFragment extends Fragment {
@Override
public void onStart() {
super.onStart();
MyTracker.getInstance().logScreen(this);
}
}
↑画面用のメソッド
DroidKaigi 2018 @cattaka_net77
個別にコードを入れるのは大変
●
対策2
– LifeCycleCallbacks を使う
●
ActivityLifecycleCallbacks
●
FragmentLifecycleCallbacks
DroidKaigi 2018 @cattaka_net78
FragmentLifecycleCallbacks
public class TrackFragmentLifecycleCallbacks extends
FragmentManager.FragmentLifecycleCallbacks {
@Override
public void onFragmentStarted(
FragmentManager fm, Fragment f) {
super.onFragmentStarted(fm, f);
MyTracker.getInstance().logScreen(f);
}
}
↑画面用のメソッド
DroidKaigi 2018 @cattaka_net79
FragmentLifecycleCallbacks の問題
●
1つの画面に2つFragmentがあると衝突する
●
対策
– マーカーインターフェースを計測の要否に使う
DroidKaigi 2018 @cattaka_net80
マーカーインターフェースを使う
@Override
public void onFragmentStarted(
FragmentManager fm, Fragment f) {
super.onFragmentStarted(fm, f);
if (f instanceof ITrackScreen) {
MyTracker.getInstance().logScreen(f);
}
}
public interface ITrackScreen {}
DroidKaigi 2018 @cattaka_net81
ViewPagerの問題
●
左右のFragmentがstart状態になる
●
対策
– 中のFragmentのonResumeでは計測しなくする
– 親側で泥臭くハンドリングする
●
onStartで最初のFragmentを記録
●
onPageSelectedで切り替わりを記録
DroidKaigi 2018 @cattaka_net82
パッと確認できるようにしておく
DroidKaigi 2018 @cattaka_net83
logcatに出しておく
●
トラッカーの確認を検証作業に含めるのは酷
●
実装者がチラ見でもチェックできるようにする
DroidKaigi 2018 @cattaka_net84
Firebase AnalyticsのDebugViewを使う
●
デバッグを有効にしたデバイスの操作が
Webブラウザ上でリアルタイムに確認できる
DroidKaigi 2018 @cattaka_net85
通信についての気遣い
DroidKaigi 2018 @cattaka_net86
実装上の気をつけないといけないこと
●
再送制御
– 雑に独自実装するとエラーが出たときに欠損する
●
送信タイミング
– 都度通信するとバッテリーに優しくない
– 適当なタイミングでまとめてやって欲しい
FA, GA, TDは全部やってくれる
DroidKaigi 2018 @cattaka_net87
Firebase Analyticsへの気遣い
DroidKaigi 2018 @cattaka_net88
Firebase Analyticsへの気遣い
●
Firebase Analyticsには地味に制約が多い
– 制約を守らないとエラーになってログが送れない
●
主な制約
– イベント名の種類は500個まで
– イベント名と属性名
●
英数とアンダースコアで40文字まで
– 属性の値は100文字まで
– 同一属性名の型は揃えること
DroidKaigi 2018 @cattaka_net89
銀の弾丸は無い、筋肉でカバー
DroidKaigi 2018 @cattaka_net90
ログ取りで気をつけてること
DroidKaigi 2018 @cattaka_net91
1つの指標は最低3系統で確認できること
●
おかしな値は割と出る
●
最低3つあれば多数決ができる
●
よく使う系統
– アクションログ
– コンバージョンログ
– Web側のログやDB
DroidKaigi 2018 @cattaka_net92
ログだけでユーザーの操作を
把握できるようにする
●
おかしな数字がでたときは生ログを見る
●
計測がおかしいユーザーを探し、
その行動ログから異常を探る
DroidKaigi 2018 @cattaka_net93
機密情報は入れないこと
●
取扱に困るものはログにいれないこと
– パスワード
– メッセージ
– 利用規約やプライバシーポリシーに反するもの
DroidKaigi 2018 @cattaka_net94
定量的な数字も必要ならとる
●
RecyclerView
– 何処までスクロールしたか
– どのViewが何秒表示されたか
– getGlobalVisibleRectで頑張って実装
DroidKaigi 2018 @cattaka_net96
可視化する
DroidKaigi 2018 @cattaka_net97
最初はExcelとSQL
●
Google BigQueryからSQLでデータを取り出す
●
ピボットテーブルでパッと項目別に集計する
DroidKaigi 2018 @cattaka_net98
Excelは強い
●
数十MB、数十万レコードのCSVを開ける
●
そのサイズでもピボットテーブルが動く
DroidKaigi 2018 @cattaka_net99
Google Data Studio(beta)
●
データをダッシュボードやレポートにできる
●
BigQueryやRDBMSからデータを引っ張れる
DroidKaigi 2018 @cattaka_net100
Domo
●
ビジネス管理プラットフォーム
●
データの可視化や集約、共有できるサービス
●
RDBMSやBigQueryに繋いでグラフが作れる
DroidKaigi 2018 @cattaka_net101
その他
●
Jupyter notebook
●
R
●
Tableau
●
Metabase
●
re:dash
●
Chartio
他にもたくさんあるのでググってください
DroidKaigi 2018 @cattaka_net102
過去に起こった失敗
DroidKaigi 2018 @cattaka_net103
Notificationでスパイク
●
アクティブユーザーに誤検知されていた
●
操作ではないイベントはNonInteractiveにする
– Receive, Open, Cancel など
DroidKaigi 2018 @cattaka_net105
0
50
100
150
200
250
300
350
400
count
荒ぶるグラフ
●
いろんな要因でグラフは壊れる
– アプリの改修時の実装ミス
– Web側のDBの構成変更
– APIの改修時の構成変更
壊れたら直す
リリース日
DroidKaigi 2018 @cattaka_net106
ProGuard先生ェ...
●
ログ上の画面名が a とか b になっていた
– 雑にclass.getSimpleName()でログを取っていた
– 何かの弾みで除外指定が外れて難読化されていた
DroidKaigi 2018 @cattaka_net108
onClickイベントが他所から叩かれていた
●
トラッカーは暗黙的にonClickに埋めていた
●
一部の実装がonClickを直接叩いていた
●
画面を開いただけでトラッカーが発火していた
DroidKaigi 2018 @cattaka_net109
広告媒体の違いは怖い
●
広告媒体ごとにユーザーの質が異なる
– CPI(Cost Per Install)と継続率は別
●
対策
– インストール時のリファラーを記録する
●
com.android.vending.INSTALL_REFERRER
– 広告の計測ライブラリを使う
DroidKaigi 2018 @cattaka_net110
A/Bテストは同時期にやる
●
時間で分けたA/Bテストは恐ろしい
– 「先週と今週で比較」は良くない
– 広告を使っていると顕著
●
同じ期間じゃないと徒労に終わる
– Firebase Remote Config的なもので
サクッと切り替えられるようにする
DroidKaigi 2018 @cattaka_net112
Next Action
DroidKaigi 2018 @cattaka_net113
ディープラーニングで!
DroidKaigi 2018 @cattaka_net114
ごめんなさいよくわかりません
DroidKaigi 2018 @cattaka_net115
アプリエンジニア的アプローチ
●
改善したい数字を決める
●
仮設を立てる
●
効果を見積もる
●
施策を実装してリリースする
●
結果を確認する
DroidKaigi 2018 @cattaka_net116
べき論では良くならない
●
「ガイドラインではこう言われています」
●
「デザインパターンではこう言われています」
●
本当にそれが人を幸せにするのか?
DroidKaigi 2018 @cattaka_net117
まとめ
DroidKaigi 2018 @cattaka_net118
アプリにはたくさんの人が関わる
●
エンジニア
●
デザイナー
●
ディレクター
●
マーケター
●
ビジネス
●
カスタマーサポート
●
etc
DroidKaigi 2018 @cattaka_net119
それぞれの意図が
正しく成功したか失敗したかを
指し示せるかはログに掛かっている
DroidKaigi 2018 @cattaka_net120
アプリエンジニアが
ログをちゃんと取れば
メンバーが動きやすくなり
プロダクトの成長に繋がる
DroidKaigi 2018 @cattaka_net121
皆さんのプロダクトの成長が
人類のQoLを上げると信じてます
DroidKaigi 2018 @cattaka_net122
ログを取ろう
DroidKaigi 2018 @cattaka_net123
WANTEDLY TECH BOOK 配布中
●
技術書典1〜3で
頒布した記事の中から
アプリ向けのものを激選
DroidKaigi 2018 @cattaka_net124
ご清聴ありがとうございました
Takao Sumitomo

More Related Content

アプリを成長させるためのログ取りとログ解析に必要なこと