こんにちは。僕のアプリ開発の進め方としては、Helpshitなどを使ったユーザーフィードバックと、自分が使い易いかどうかを基準に改良していくのが中心なのですが、そろそろ数字もみていこうかなと思いました。

参考
*使いやすいアプリを作る簡単な方法

そこで、最近アプリのリテンション(ユーザがどれだけアプリに戻ってきてるか)の見方とか、実際にABテストのやり方を研究して実際にやってみたので、どういったツールを使って、どういった手順で、どういう風にデータを見ればよいかを書いてみたいと思います。

今回はiOSアプリでやったけど、Androidアプリでも使うツールがほぼ同じなので参考にはなると思う。

ちなみに、こういったデータ解析って、具体的なやり方よりも、どういう状況で、なんのためにやるかのほうがよっぽど重要なので、まずはそのことについて。

比べる対象を明確にして、その後の対策をイメージする

まず、ABテストってよく聞くけど、何と何を比べたいかを明確に定義しないといけない。

その上で、そのABテストを実施する手間(例えば信頼に足るデータ量と必要な時間、実装するコストなど)を考えても、その結果が知りたいかを考えないといけない。

そして、もっと重要なのは、その結果を見て、「ふーん」で終わらず、その結果に基づいてその後なにを実行するかまでイメージできているのが重要。

数値を見た後、何をするかはとても重要で、LeanAnalyticsではActionable Metricsと呼ばれている。逆にいえば、数値を見た後のアクションが考えられないデータは、「ふーん」で終わるから、そこまで価値がないということになります。

*参考
Lean Analytics 虚構の数字と改善に繋がる数字

*この本ガチでオススメ

例えば、アプリのバージョン1.0と1.1で、ユーザのリテンション率が変わるか比べることができたとしても、具体的に何が原因で変化が起こったのかは掴みにくい。同じように、国同士でアプリのリテンション率が違うことを比べても、それを見て次に何をするかがイメージできてないと意味がない。

でも、これはそんなに難しい話でもなくて、アプリのアップグレード画面の説明文をAパターンとBパターン作り、それをABテストした場合を考えてみるとわかりやすい。

この場合、比べる対象が明確なので、どちらかの結果がよければ原因もハッキリする。Aパターンのほうが購入率が高かったという結果であれば、これからはAパターンを使うという、その後のアクションも明確です。

ABテストの対象を絞る

これは、僕のPHPプログラマ時代の師匠であるエランさんからアドバイスしてもらったことなんだけど、ABテストする時は一度に一つのテストをするぐらいのイメージでいいらしい。

というのも、まず初めに、信頼性のあるデータを得るには十分なデータの母数が必要となる。さらに、リテンションのような何日間にも渡って見るデータ解析の場合、日数がたつほどアプリに戻ってくる人数が減るから、なおさらデータ量の母数が必要となる。

もう一つは、複数のABテストを同時に回そうとすると、それぞれのテストがお互いのテストに影響する可能性も考えないといけないので、さらにデータ量が必要となり、信頼性も下がってしまう。もちろん、データの設定方法が複雑になるという問題も。

というわけで、よっぽどデータ量が多いとか、お互いのテストがお互いに影響しないなどの場合を除いて、ABテストは一度にひとつだけするという考え方がよいと。

ここまで書いてきたけど、ABテストはそれなりにコストも時間もかかるので、何でも悩んだらテストすればいいってもんじゃないのがわかります。基本的にほとんどのUI・UXの判断基準は、過去の経験則やじっくり考えた結果から、ABテストなしでやっていかないと何も進まない。

*参考
ABテストしないと分からない?

そんなわけで、本当にABテストのコストをかける意味がある部分、自分の予想が合っているか確認する価値のある部分に絞ってテストしていったらいいと思う。

前置きが長くなってしまったが、ここから具体的にどうやってやっていくかを書いていきたい。

リテンション(ユーザ維持率)がフィルタリングできるツールを使う

最近のデータ解析ツールは無料で使えるものが多く、データ量が必要となる時はありがたい。と思いきや、結果的に無料で使えるデータ解析ツールは今回使えませんでした。

リテンションを見たい場合、ユーザがアプリに戻ってきているかを見るわけなので、結構トラックする回数が多くなってしまう。この点、Mixpanelみたいな、トラックする回数に応じて課金されるサービスを使っている場合、ケチケチ使わないと一気に無料枠使ってしまうという悲しい事態になります。

なので、最初に試したのはFabricのAnswerとFirebaseAnalytics。どちらも無料で使えて、リテンションを見ることができる。

しかし、使ってみたらわかるんだけど、リテンション画面が見れるのはいいとして、自分が比べたい値を使ってフィルタリングができないんですね。これが。

例えば、リテンションの簡単に見方としては、何パーセントのユーザが1日目、2日目、3日目とアプリに戻ってきているかというのを見る。

FirebaseAnalyticsだとこんな感じ。

Answerだとこんな感じ。

ただ、これ見ても、そうですかという感想しかでない。Answerとか綺麗にデータが見れて気持ちいいんだけど、ここから何かを変えて、それでどう変わるかっていう具体的なアクションと結果を見ることができないんですね。

重要なのは、バージョン1.0と1.1などで比べて、1.1のほうがユーザの定着率が高くなってるなとか、少なくとも何かの値でフィルタリングして比べたいので。

特に、ABテストする時は、AとBの違いを見るわけだから、フィルタリングができないとそもそも話にならないわけで、残念ながらどちらもできなかった。(もしかしたら、いろいろやると出来るのかもしれないけど、やり方が見つからなかった。)

というわけで、結局一番使いやすくて、リテンションでもフィルタリングができるのはMixpanelだったというオチになりまして、久々にMixpanelを本格的に使うことにしました。結局有料のものを使わなければいかぬのか。

Mixpanelはフリーミアムだけど、Mixpanelのリンクを適当に作ったブログに貼り付けると200,000データポイントまで無料で使えるので、短期的に絞った解析なら結構無料枠でもいける。

次は、具体的な手順と、何をABテストしていくかを書いてみたい。

バナー広告があると離脱率はどれぐらい高まるか

さて、手間も時間もそれなりにかかるABテストをするならば、意味のある事を調べないといけないということで、今回はアプリに広告をつけるとどれぐらい離脱率が高まるかというのをお題にしてみました。

そして、結果を見てその後どうするかのイメージも重要なので、もし離脱率が大幅に高かったら、広告の出し方を考え直すことにします。例えば、出す頻度とか、最初は出さないなどいろいろとありますが。

今回は、僕が二年前にリリースして、それからちょこちょこと改善しているListTimerでやってみます。最近は日々のダウンロード数も結構多く、母数も確保できそうということで。

ListTimerはワンタップでセットできるのと、終了時刻も表示されるのがウリの、タイマー&アラームアプリ。どんなアプリかはこのスクショをザッと見るとわかるかも。

以下のように、バナー広告がタイマーセットする時のリストの下、タイマー終了時のダイアログなどに表示されます。

概要としては、既存のユーザには影響しないようにし、新しいユーザだけを対象にABテストする。1日100ダウンロードあったとすれば、50人は広告なし、50人は広告ありにして、1日目、2日目、3日目、4日目、と離脱率が変わるかを調べる。

ついでに、タイマーをセットするという動作も軸にして、1回セット => 5回セット => 10回セット => 15回セットのように、アプリをたくさん使い続けてくれるかどうかの軸でも、広告ありとなしで差が出るかを見る。

ちなみに、広告なしユーザもある程度日数がたって、規定の回数タイマーを使うと、いつも通り広告が表示されるようにしておいた。

実際のコードの例(iOS)

一応、iOSで使ったコードの例を参考までに書いておくけど、プログラマじゃない人は別に読み飛ばしてもOK。

まず、初回起動時だけMixpanelでトラックするコードを書く。そして、ABテスト用に、SkyLabというライブラリを使って、起動時に50%の確率でAとBに分けます。

https://mixpanel.com/
https://github.com/mattt/SkyLab

そこで、ここがMixpanelで重要な部分なんだけど、peopleタグで、広告有無のプロパティをセットしておきます。Mixpanelのpeopleタグは上限数が決まっているので、superPropertyで代用できないかと思ったけど、リテンションのフィルタリングはpeopleタグじゃないと出来ないです。


- (void)trackFirstLaunch {
    
    //set mixpanel first endpoint
    if (![[NSUserDefaults standardUserDefaults] boolForKey:@"First Launch Done"]) {
        
        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"First Launch Done"];
        
        // Set indetify for people
        [[Mixpanel sharedInstance] identify:[Mixpanel sharedInstance].distinctId];
        
        [[Mixpanel sharedInstance] track:@"First Launch"];
        
        // Track first launch date
        [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:kFirstLaunchDateKey];
        
        [SkyLab abTestWithName:@"AdTest" A:^{
        
            [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kNoBannerAdsTestUserKey];
            [[Mixpanel sharedInstance].people set:@{@"DisableAdAtFirst":@"YES"}];
        } B:^{
            [[Mixpanel sharedInstance].people set:@{@"DisableAdAtFirst":@"NO"}];
        }];
    }
}

そして、リテンションを取るために、起動のたびにMixpanelでトラックすると、一気に無料枠をぶち破ってしまいそうなので、数時間以内の起動であればスキップするようにする。今回は前回の起動から5時間以上たっていればトラックすることにした。

下記のコードをAppDelegateのdidFinishLaunchingWithOptionsとapplicationWillEnterForegroundにセット。


- (void)trackRetention {
    
    NSString *trackedDateKey        = @"trackedDateKey";
    NSDate *previousTrackedDate     = [[NSUserDefaults standardUserDefaults] objectForKey:trackedDateKey];
    NSDate *nextTrackDate           = [previousTrackedDate dateByAddingHours:5];
    
    // NSDate+Escortというライブラリ使用
    if ([nextTrackDate isInFuture]) {
        return;
    }
    
    [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:trackedDateKey];
    [[Mixpanel sharedInstance] track:@"App Opened"];
}

あとは、タイマーをセットする時にもMixpanelでトラックするコードを書いておく。毎回トラックすると枠がすぐなくなるので、こんな感じで5回タイマーがセットされるごとにトラック。


[[Mixpanel sharedInstance] track:@"New Timer Set" properties:@{ @"Count": @(count) }];

これでだいたいの準備ができました。次は、アプリをリリースして一週間ぐらいたってからグラフで確認。

Mixpanelのリテンション画面で確認

まず、Mixpanelのリテンションという項目をタップするとこんな画面が表示されます。

しかし、これ見ても重要なことはよくわかりません。リテンション分析の画面ってこれが基本なんだけど、僕は、これ見ても何も参考にならないなといつも思っておりました。少なくとも、バージョンとか、なにかの値でフィルタリングしないと、なにとなにでリテンションが違うのかが掴めない。

でも、最近、このフィルタリング方法がわかりました。

今回の広告ありと広告なしで比べるとこんな感じになる。

Mixpanelのリテンションで、写真上でRecurringとなっているところをクリックして、First Timeに切り替えます。

そして、Show me people who didのところに、初回起動時にトラックした”First Launch”をセット。(今回の解析は1.4.3でしかやってないので、AppVersionを1.4.3で起動した人に限定)

Then came back and didのところはAnythingを選ぶと、Mixpanelでトラックしたすべてのデータポイントをカバーするから、”SetTimer”とか、”App Opened”とか、すべてを対象にしているので、ようはまたユーザがアプリを使いに戻ってきてくれたかを意味します。

そして、ここが一番重要なポイントなんだけど、左下の +Segmentというところをクリックして、peopleでセットしておいた”DisableAdAtFirst”(最初は広告を消す)を選択。これでYESとなっているのが広告消えてるユーザ、NOとなっているのが広告ありのユーザ。

やっと、リテンション率を使ってABテストすることができました!

さて、結果をみると、広告ありとなしでリテンションにそこまで違いがない。<1dayのところは1日以内に戻ってきた人の割合。1が1日たって戻ってきた割合となる。5,6,7日目でちょっと違いが出ているけど、このへんになると母数も少なくなってきくるので、あまり参考にならない誤差の範囲な気がする。

ファネル分析からABテスト

次に、ファネル分析も使って二つの値を比べてみたい。リテンションが1日ごとに、何パーセントのユーザが戻ってきたかを見る分析とすると、ファネル分析は時間軸関係なく、何らかの行動をしたかを順番に設定できる。

今回は、初回起動 => タイマーセット (1回目) => タイマーセット (5回目) => タイマーセット (10回目) => タイマーセット (15回目)といったコンバージョン率を基準に、広告ありとなしでどういった違いが出てくるかをみてみる。

結果はこちら。新しいバージョンをリリースして一週間ぐらいの時にみた数値。

さて、今回もpeopleでセットしておいた”DisableAdAtFirst”(最初は広告を消す)をプロパティで選んで選択。これでYESとなっているのが広告消えてるユーザ、NOとなっているのが広告ありのユーザ。

それぞれの到達ポイントごとのコンバージョン率が比べられます。結果をみたところ、広告を消しているほうが若干コンバージョン率が高いけど、それほど違いがあるわけでもない。

今回の分析だけで判断すると、リテンションとファネル分析で比べてみたところ、思ったより広告の有無で離脱率に違いがなかったという結果になった。これは当初想定してた予想と若干違っていたので軽い驚き。

まあListTimerの場合、操作中にできる限り気にならないような広告の付け方を最初にじっくり考えていたというのも大きいかもしれない。

さて、重要だと強調していた、この結果を受けて次にどうするかのアクションですが、そこまで変わらないので今まで通りでいいかなというのが今のところの考え。もっと違ってたら、ある程度使ってもらうまで広告は出さないほうがいいのかなとも考えてたけど、このへんは検討中です。

ただ、この結果はあくまで、この時期に、ListTimerという特定のアプリで、限定された母集団でやったものなので、違うアプリや違う状況なら結果はころっと変わる可能性が高いです。

まとめ

今回のようにABテストは時間も手間もかかるので、ちょっと迷ったらなんでもすぐABテストするぞというのは愚の骨頂だとは思いますが、重要な判断を要する部分では有効なものとなります。

重要なUIの変更とか、大切なメッセージ部分の文章とか、どっちがよいか分からない部分、自分の直感を疑って確かめてみたい時などによいんじゃないでしょうか。

僕が、面白いなと思ったのは、メルカリというフリマアプリで、すでに売り切れている商品を表示する、表示しないという2つのパターンで、売り切れの商品を表示したほうが圧倒的にユーザの定着率がよかったという記事でした。

世界3,200万ダウンロード、単月黒字化も達成。フリマアプリ「メルカリ」が語るマーケティング、検索結果にあえて「売り切れたモノ」を置いている理由。

ちなみに、今回は書いてないけど、アプリ内に埋め込んだコードの値をWeb側から変更する時には、FirebaseのRemoteConfigというサービスが便利です。アプリをアップデートせずに値を変更したかったり、全体の2割の割合でここの値をYESにしたいとかできるので、ABテストする時にぴったり。


*家計簿読み上げのアプリ作ってます。自己紹介と過去ログはこちら