MBaaS徹底入門――Kii Cloudでスマホアプリ開発

第11回Kii Cloudを用いたチャットアプリケーションの開発その7]アプリケーションのデータ分析(実装編)

第10回では、Kii Cloudが提供しているデータ分析機能について概要を説明しました。第11回となる今回は、データ分析を利用した機能改善の例として、第8回で実装したスタンプ機能に焦点を当てます。スタンプの利用状況を収集して、人気のあるスタンプを分析します。またアプリケーションから分析結果を利用してスタンプを人気順にソートする機能を実装してみましょう。

なお、今回使用したソースコードについては、GitHubで公開しています。こちらもあわせてご覧ください。

分析ルールの作成

前回の分析ルールの定義で解説した手順に従って実際にスタンプの利用状況を分析するためのルールを作成してみましょう。

今回の例ではスタンプの利用回数をカウントするだけの非常にシンプルなルールを作成します。

もし、サインアップ時にユーザの属性情報等(性別、年齢、住所)を入力してもらうように拡張すれば、イベントデータにそれらの情報を付加して分析することで、より多角的な分析が可能になります。⁠性別、年齢層で人気のスタンプに差があるかどうかなど)

分析ルールの作成画面
分析ルールの作成画面

分析ルールについて詳しく見ていきましょう。

Name

分析ルールの名前を設定します。わかりやすい名前を設定してください。

今回は「スタンプの利用状況」という名前にしました。

Data

分析対象データのソースの種類を設定します。KiiChatアプリで使用してきたchat_stampsやchat_roomに保存されているデータはすべてApp Dataに分類されます。今回はEvent Dataという分析専用のアプリケーション全体で共有されるデータを使用します。

Aggregate using

集計する対象と、その集計方法を設定します。今回は使用されたスタンプ(スタンプのURI)の件数をカウントしたいので「"Count" of "stamp_uri"」と設定します。またstamp_uriは文字列のデータなので、型は"string"を選択します。

Filter by type

Event Dataは1つの共通のバケットに複数の種類のイベントデータを保存していくようなイメージになります。これらのイベントの種類を区別するためにTypeを設定します。今回はスタンプを送信したタイミングで発生するイベントなので「stamp_usage」としました。今回のサンプルでは分析する対象のイベントが1種類なのであまり意味がありませんが、複数のイベントを分析する場合に役に立ちます。

Dimensions

分析結果をグルーピングする設定です。今回はスタンプの人気を分析する為に、スタンプごとの使用回数を計算したいので、⁠stamp_uri」を設定します。

イベントデータの送信

分析ルールを作成した後は、分析対象のイベントデータをアプリケーションから送信するコードを実装しましょう。今回、実装する機能のデータフローは以下のようになります。

イベントデータ送信のデータフロー
イベントデータ送信のデータフロー

まずイベントデータを送信するメソッドをChatStampクラスに実装します。

public static void sendUsageEvent(ChatMessage message) {
    if (message.isStamp()) {
        try {
            KiiEvent event = KiiAnalytics.event("stamp_usage");
            event.set("stamp_uri", message.getStampUri());
            event.push();
        } catch (IOException ignore) {
            Logger.w("failed to send event");
        }
    }
}

最初にKiiAnalytics#event(String)メソッドにイベントタイプを指定してKiiEventのインスタンスを生成します。KiiEventには任意のkey-valueを設定することができます。

先ほど分析ルール作成で集計の対象として設定した⁠stamp_uri⁠をキーに、値にはChatStampのURIを設定します。最後にKiiEvent#push()でイベントデータを送信します。

ここで実装したメソッドは、メッセージを送信する処理であるChatActivity.SendMessageTask#doInBackground()から呼ぶようにします。

private class SendMessageTask extends AsyncTask<Void, Void, Boolean> {
    private final ChatMessage message;
    private SendMessageTask(ChatMessage message) {
        this.message = message;
    }
    @Override
    protected Boolean doInBackground(Void... params) {
        try {
            this.message.getKiiObject().save();
            // イベントデータの送信
            ChatStamp.sendUsageEvent(this.message);
            return true;
        } catch (Exception e) {
            Logger.e("failed to send messsage", e);
            return false;
        }
    }
}

分析結果の確認

Flex Analyticsの分析結果は、開発者ポータルから確認できます。

以下の図は、作成した分析ルール「スタンプの利用状況」の結果画面です。スタンプのURIごとに利用回数が集計されて表示されています。

このようなデータの分析はアプリケーションをマネタイズする上でとても重要な要素になります。例えばゲームアプリなどの場合は、課金アイテムなどの売れ行きなどを分析して、イベントをうったりと、運営戦略を決めるヒントになります。

分析結果表示画面
分析結果表示画面

分析結果のアプリケーションからの利用

Flex Analyticsの分析結果はアプリケーションから利用することも可能です。

ここではサンプルとしてスタンプを人気順(使用回数が多い順)にソートする機能を実装してみます。

スタンプ一覧の取得処理は既に実装済みなので、取得したスタンプのListを人気順にソートするためのComparatorを実装します。このComparatorオブジェクトをArrayAdapter#sort()メソッドに渡すことで人気順にソートすることができます。

/**
 * 人気順でソートする為のComparatorを取得します。
 * Analyticsの結果を元に人気順を判定するため、KiiCloudとの通信が発生します。メインスレッドでは実行しないでください。
 *
 * @return ChatStampを人気順でソートするためのComparator
 */
public static Comparator<ChatStamp> getPopularityComparator() {
    try {
        // 直近1ヶ月のスタンプの利用データを取得
        Calendar cal = Calendar.getInstance();
        SimpleDate end = new SimpleDate(cal.get(Calendar.YEAR),
            cal.get(Calendar.MONTH) + 1,
            cal.get(Calendar.DATE));
        cal.add(Calendar.MONTH, -1);
        SimpleDate start = new SimpleDate(cal.get(Calendar.YEAR),
            cal.get(Calendar.MONTH) + 1,
            cal.get(Calendar.DATE));
        DateRange dateRange = new DateRange(start, end);
        ResultQuery query = ResultQuery
            // スタンプのURIごとにグルーピング
            .builderWithGroupingKey(“stamp_uri”)
            // 直近1ヶ月のデータのみ取得
            .withDateRange(dateRange)
            .build();
        GroupedResult result = KiiAnalytics.getResult(ApplicationConst.AGGREGATION_RULE_ID, query);
        List<GroupedSnapShot> snapshots = result.getSnapShots();
        // Analyticsの結果をMapに格納する、key=スタンプのURI, value=スタンプが使用された回数
        final Map<String, Long> stampUsageMap = new HashMap<String, Long>();
        for (int i = 0; i < snapshots.size(); i++) {
            try {
                // Analyticsの結果は日別(pointInterval)に分割されて配列として取得されるので、合計値を計算する
                long usage = 0;
                for (int j = 0; j < snapshots.get(i).getData().length(); j++) {
                    usage += snapshots.get(i).getData().getLong(j);
                }
                stampUsageMap.put(snapshots.get(i).getName(), usage);
            } catch (JSONException e) {
                stampUsageMap.put(snapshots.get(i).getName(), 0L);
            }
        }
        // スタンプの使用回数でソートする
        return new Comparator<ChatStamp>() {
            @Override
            public int compare(ChatStamp lhs, ChatStamp rhs) {
                // 比較対象のスタンプの使用回数を比較する
                long lhsUsage = stampUsageMap.get(lhs.getUri()) == null ?
                    0L : stampUsageMap.get(lhs.getUri());
                long rhsUsage = stampUsageMap.get(rhs.getUri()) == null ?
                    0L : stampUsageMap.get(rhs.getUri());
                // 使用回数が多い順(降順)にソートしたいので、通常のComparatorの定義とは逆の戻り値を返す
                if (lhsUsage > rhsUsage) {
                    return -1;
                } else if (lhsUsage < rhsUsage) {
                    return 1;
                } else {
                    return 0;
                }
            }
        };
    } catch (KiiAnalyticsException ignore) {
        // Analytics結果の取得に失敗した場合は、デフォルトの新着順のComparatorを返す
        Logger.w("failed to get analytics result", ignore);
        return getNewlyComparator();
    }
}

人気順の定義ですが、ここでは直近1ヶ月間で使用回数が多いスタンプを人気のスタンプと定義します。

まず、1ヵ月前から今日までを表すDateRangeのインスタンスを生成します。

次に作成したDateRangeオブジェクトとグルーピングの単位“stamp_uri”を指定してResultQueryのインスタンスを生成します。

最後にKiiAnalytics#getResult()にResultQueryと分析ルールのIDを指定することで分析結果を取得します。

分析結果はGroupedSnapShotクラスで表現されます。少しわかりづらいですが、JSONで表現すると以下の様な構造になっています。

{
    "snapshots" : [
        {
            "name" : "kiicloud://buckets/chat_stamps/objects/xxxxx1",
            "data" : [ 4, 10, 8, 12 ],
            "pointStart" : 1385823600000,
            "pointInterval" : 86400000
        },
        {
            "name" : "kiicloud://buckets/chat_stamps/objects/xxxxx2",
            "data" : [ 0, 2, 1, 4 ],
            "pointStart" : 1385823600000,
            "pointInterval" : 86400000
        }
    ]
}

nameフィールドにスタンプのURIが設定されており、dataフィールドに使用回数が設定されています。使用回数が配列になっているのは、pointStartが表す日時から、pointIntervalの間隔ごとに結果が分割されているからです。上記の例では2013/12/1(1385823600000)から1日ごと(86400000ms)に分割されています。よって配列の第1要素が12/1の使用回数、第2要素が12/2の使用回数を意味しています。

これらをもとに、スタンプごとに過去1ヵ月間の使用回数の合計を計算します。そして算出した使用回数を元にComparator#compare()メソッド内で人気順での比較を実現しています。

まとめ

今回は、データ分析機能について解説し、分析結果をアプリケーションで活用する方法を説明しました。このようなデータ分析機能はアプリケーションを改善していく上で非常に有益な情報になります。一般的に開発者が想定したユーザの行動と、実際のユーザの行動との間にはどうしてもギャップが生まれがちです。

ユーザの行動を収集、分析することでこのギャップを埋め、よりよいアプリケーションを開発することが可能になります。

おすすめ記事

記事・ニュース一覧