読者です 読者をやめる 読者になる 読者になる

アプリのアップデートに依存せずにアプリの画面を改善し続ける仕組み

検索事業部の日高(@kaa)です。
検索事業部では作りたいレシピが見つかることをひとつの目標に、レシピを探す行動を助けることに挑戦しています。 その中で、レシピ検索した際の結果画面でのコンテンツを改善していくための仕組みについて紹介します。

作りたいレシピが見つかるためへの色々なアイデア

レシピ検索結果画面でレシピを一覧で見せるだけでなく、作りたいレシピがより見つかるために考えられることはたくさんあります。

例えば

  • もし、入力ミスと思われる検索ワードだったら
    正しいと思われる検索ワードを提案、または正しいと思われるワードで検索し、元のワードも表示(Google検索のように)

  • あいまいな検索ワードだったら
    より具体的に検索できるよう検索ワードを提案。「さっぱり」だったら「冷しゃぶ」「さっぱり 麺」など。 (具体的なワードで検索するとレシピが決まりやすい傾向があります)

  • さらに小分類をもつワードなら
    「パスタ」だったら「ナポリタン」「カルボナーラ」「冷たいパスタ」といった具体的なワードを提案する。

  • 見つからない様子だったら
    もし検索結果をある程度の件数見て、まだ迷っているようなら、この食材でやってみるのはどう?といった方向性を変える提案

などなど、 それぞれのアイデアごとに、どのような検索ワードの時に、検索結果の一覧のどのあたりに出すべきかということを検討していく必要があります。 もちろん全てのアイデアに価値があるわけではありません。素早く効果を確かめ、もし駄目な場合も他の開発に影響なくクローズを行えるのが理想です。

アプリでの新機能・導線改善のよくある課題

  • アップデートの浸透具合により、コンテンツの効果判断できる時期が伸びがち(改善サイクルが遅い、段階リリースを利用するとさらに伸びる)
  • A/BテストのコンテンツのためのAPIなど、アプリ・サーバーに限らず一時的な実装が増えてしまう。
  • コンテンツ変更にアップデートが必要になってしまうので、スマホサイトで価値検証後、アプリに導入になってしまう。
  • Webで効果あった施策がアプリでも効果があるとは限らない。再度確かめる必要がなる

よくあるアプリでのA/Bテストとその課題

アプリで機能の価値評価を行なう際、A/Bテストを行なうことがあります。
基本的な流れとしては起動時などに設定用APIからフラグなどのデータを取得し、機能のONOFF、UIの切替を行ない数値検証をしていきます。 Google公式のFirebaseでもRemote configという機能が提供されるのでこれからさらに行われるようになると思います。

この場合も弱点として、フラグを処理する実装をしたバージョンからしか有効でない、機能自体はアプリに実装されていないといけないのでテストできるバリエーションが限られる、A/Bテストの結果を見てさらにテストを行ないたい場合、また次回アップデート待ちになりがち。
AパターンとBパターン、さらに手を加えたA'パターンまでアプリに実装されていないことにはWebと同じスピードで改善を続けていくことはできません。

また、クックパッドのandroidアプリでは新バージョンでの新たなクラッシュの検出のため段階的にリリースされていくようにしています。段階リリース中にクラッシュが検出された場合、その修正対応などによりアプリの全体公開の時期がずれこむこともあります。
段階リリース自体は素晴らしいのですがアップデートによる価値検証という目的ではサイクルが遅くなる要因となります。

アプリでの価値検証のスピードを上げるために

1.表示するコンテンツをAPIで指定できるようにする

検証したい価値ごとにアプリを実装していたのでは、アプリのアップデートに縛られてしまいます。 これには事前に考えられるコンテンツのデザインフォーマットを事前に用意しておくことで対応します。

コンテンツの表示方法がその機能固有になると、その実装したバージョンからしか検証ができません。
それではアイデアをすぐに試せないため今回はアプリのデザインルールに沿ったコンテンツのフォーマットを10パターン程度想定しました。
横スクロールのカルーセル型か、バナーか、一覧形式か、またはタイトル・サブタイトルになる要素、「もっと見る」的要素など各フォーマット共通に使われそうなものを整理。 画像があるのかないのか、あるなら画像サイズの自由度は、キャプション、バッジ的要素はあるのかないのか。
各コンテンツフォーマットのデザインに対してどんな利用シーンが起こりえるか想像力を働かせます。既存のデザインを見返し、どの要素が必須で、必須ではないcaptionなどの要素が空の場合でもデザインが破綻しないよう注意します。

今回は以下のようなテンプレートを用意しました。
上部には共通でlabel要素、アイコン、more(もっと見る等)の要素とその下に各フォーマットの情報。
これで全てではありませんが一例として。 f:id:futura24pt:20160729124517p:plain

各要素の名前も出来る限り汎用的に考えます、label,lead,caption,thumbなど。ここでもしrecipe_titleといった意味を持った名前を採用してしまうとそのフォーマットを別の用途で利用しようとした際に混乱を生んでしまいます。
ただ汎用性を高めすぎると使いにくかったり複雑な構成になりやすいため、今回はレシピを表示するrecipe_list,recipe_singleは別に用意しました。

価値評価後、最終的にはさらに適していると考えられるそのコンテンツの専用デザインを作成する可能性はありますが、評価段階では汎用的なもので進めます。
これらがアプリに実装された状態が出来てしまえば、APIの変更のみでコンテンツを入れ替え価値検証していくことが可能になります。

2.APIを検証したい機能ごとに用意しない

APIの種類が増えると表示速度の低下、通信エラーリスクの増加、コードの複雑化といった問題が起きますし、APIを叩く実装をしたバージョンでの動作に限定されます。 それでは価値検証したいコンテンツの評価に次バージョンを待たなくてはいけません。
また後々使わない可能性がある、しかし特定のバージョンでのみ利用しているAPIといったものができてしまうとサーバーサイドの実装もいつまでも残す必要ができてしまい、負債になってします。そのバージョンを利用するユーザーはアプリアップデート後も残ることになりますので。

運用していくために

仕様をドキュメント化する

あるデザインフォーマットのコンテンツを追加したい場合、コンテンツの各要素の指定方法がわからないといけません。 各要素の必須、任意なのかもまとめておきます。
この仕様さえ共有できてしまえば、価値検証時にアプリエンジニアの稼働がゼロで、アプリリリース時期に依存せず新たなコンテンツを提供していくことが可能です。もちろんバッティングしないよういまどういったコンテンツをレシピ検索結果に表示しているかの共有は大事ですが。
サーバーサイドとしてはどのようなJSONを出力すると望んだ表示ができるのか把握できることが望ましいので、サンプルのJSONと画面キャプチャも用意しておきます。

各デザインフォーマットをプレビューできるようにする

全デザインフォーマットが実運用で常に使われるわけではありません。 どのような表示が可能なのか、確認できるようになっていないと困ります。
クックパッドでは開発版ビルドでのみ各デザインフォーマットの確認ができるダミー画面を実装し、どのような表示が可能なのか見当できる画面を用意してあります。

各デザインフォーマットの対応バージョンを明記する

いくらデザインフォーマットを色んな想定したとしても、追加したいデザインはでてきます。
また、特定の機能のためのデザインを追加したくなることもあります。 もちろんそのデザインが実装されたバージョン以降からしか利用できませんので、どのフォーマットがどのバージョンから利用可能なのかまとめておきます。 これにより新しいコンテンツを配信した際、どの程度の数のユーザーがそのコンテンツを利用できることになるのか判断できます。
APIを一本化したことにより、もし古いバージョンのアプリを利用していて、最新版のアプリでしか対応していないコンテンツを受け取ってしまうとどうするか、という問題がありますがアプリが知らないコンテンツフォーマットのデータに関しては無視する、表示しないといった方針にしています。

まとめ

このようにアプリでの表示とAPIのルールを定義することで、以前はスマホサイトで価値検証後にそれぞれAPI開発し、アプリに実装し次回アップデート後に反映、といった進め方から最初からアプリで価値を検証し、改善していく進め方ができるようになりました。

クックパッドでは職種問わずサービス改善に取り組み続けることに興味のある方を募集しています 。もしすぐに採用でなくても、アプリでのサービス改善について興味ある方がいらっしゃいましたら@kaaまでお気軽にどうぞ。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/