1 pixel|サイバーエージェント公式クリエイターズブログ

サイバーエージェントのクリエイターの取り組みを紹介するオフィシャルブログです。最新技術への挑戦やサービス誕生の裏話、勉強会やイベントのレポートなどCAクリエイターの情報が満載です。


Theme:

みなさん、こんにちは。サイバーエージェントでフロントエンド・サーバーサイドを実装したり、オフィスを作ってみたりしている@herablogです。今回は、Amebaアプリでアメブロの記事をネイティブ化したプロジェクトをご紹介したいと思います。多くの方がご存知のようにアメブロは2005年にPCブラウザ向けサービスとして提供され、インターネット上に個人やグループの記録を残す、まさしく THE Web といったサービスです。この記事では、10年以上のデータが蓄積されたWebサービスをどのようにしてネイティブアプリとして組み込んだかご紹介します。

 

 

コンセプト

ネイティブ化するにあたって、大事にしたことは以下の点です。

  • 表示がはやい
  • 記事を読むことに特化している

モバイルでの利用増加により、「表示がはやい」ということはますます重要かつ当たり前になっています。Webアプリでも、最適化をすることによって速度の高速化は可能ですが、今回のプロジェクトでは、実データ以外のUIパーツを事前に埋め込めるというネイティブアプリの利点を活かして、高速化にチャレンジしました。

 

また、Webの世界では、非常にオープンな環境であるがゆえにカスタマイズが容易で沢山のパターンのデザインがあったり、多種多様なSDKが混在し、そのすべてをコントロールすることが難しいといったことがあります。特に、PCからの仕様を継承したサービスでは膨大なパターンになりがちです。そこで、今回のプロジェクトでは記事を読むことに特化するように気をつけて設計しました。他のネイティブアプリと同様に、自由度はやや少ないんだけど、重要な機能にフォーカスされているといったモバイル時代に合った方向を目指しました。

 

とにかくはやい

今回のプロダクトでは、見た目がシンプルで記事が読みやすい・スクロールでのページングが滑らかといった特徴がありますが、何よりも一番のユーザーメリットとしてあげられるのが、表示のはやさだと思っています。表示がはやければ、途中で離脱せず、読みたい記事を最後まで読めるようになります。最近話題のAMPInstant Articleでも表示速度の改善を大きな目的としています。現状のWebページが他社に比べ劇的に遅いというわけではありませんが、一度ネイティブ版の表示を体験していただければその違いがわかると思います。

 

こちらが今回のプロジェクトの紹介ムービーです。記事の表示や記事一覧表示、記事の絞り込みなどの操作が素早くできます。

 

 

設計

今回のプロジェクトの最終的な設計は以下のようになりました。

API(記事・広告データ) 
  -> NativeApp(フェッチ、UIコントロール)
    -> ReaderView (WebView, 記事表示)

ネイティブアプリは、APIからのデータ取得と、UIパーツの表示コントロールをします。必要なデータが揃った段階でReaderView(実体はWebView)にデータを渡します。ネイティブアプリとReaderView間はオフラインですので、コスト低くデータを転送できます。(ReaderViewで使うファイル郡( html js css )は事前にネイティブアプリ内に内包しています。)

 

ReaderViewは、ネイティブアプリから受け取った情報をもとに、ブログ記事を表示します。ネイティブからデータを受け取るために、以下の様なメソッドを公開しています。

 

(例)

reader.render({
  title: 'Blog Post',
  text: 'Hi'
}); // render the contents
reader.clear(); // clear the view

初期段階ではWebViewを使わない選択肢も検討しましたが、「ブログ」という財産を活かすため、上記のような設計にしました。それは、アメブロのデータが基本HTMLをベースとしており、WebViewを使わないとブログ記事の表現がしきれない要素があったためです。

 

Web実装

ネイティブアプリに組み込まれるWeb実装(ReaderView内)として、特徴的なトピックスを記載します。

Viewに徹する

ReaderView内の実装では、とにかくViewに徹するようにし、データのフェッチや表示タイミングのコントロール、トランジションはネイティブアプリに任せることにしました。そうすることにより、ネイティブアプリとの役割を明確に分けるようにしています。

React, Flux

一番最初のモックでの実装は、

element.innerHTML = html;

というように、与えられたhtmlを表示するといった極めてシンプルなものでした。

しかしながら、最終的には React Flux での実装に変更しました。ネイティブエンジニアが修正する可能性もおおいにあるためScript中心でviewを構築する React は相性が良いと判断しました。(弊社内では Flux 設計のネイティブアプリも存在し始めているようです)

SVG

ネイティブアプリ内に内包されているWebViewを利用しているので、ある程度ユーザー環境を固定することができます。今回のプロジェクトでは、iOS 8以上、Android OS 4.1以上を対象にしているので、未対応のブラウザを気にすることなくSVGを使うことができます。ReaderViewでは、Web FontやCSS Spriteではなく、SVGをSprite化( symbol )してアイコンを表示しています。

 

なお、今回のタイミングでデザイナーさんと協力してSketch一括管理、Sketchから SVG SVG Sprites Font(TTF, WOFF, EOT) png などに書き出せるようにしており、好きなフォーマットで利用できるようになりました。

 


Sketchで管理された、シンボル一覧

 

tap hightlightをオリジナル実装

できるだけ、WebViewであることを感じさせないために、タップした時のフィードバックをデフォルトのものから変更しました。デフォルトのままだと、"ブラウザ感"が出てしまい、どうしてもネイティブアプリの世界観からずれてしまうためです。具体的には以下のパターンに分けて実装されています。

 

ボタンパターン

通常のブラウザのようにオーバーレイでのフィードバックではなく、ボタン自体の大きさを変えています。こうして、ボタンのデザインを損なうことなくフィードバックを表現しています。

 

 

背景変化パターン

ナビゲーションなど、大きめなスクエアボタンはタップ時に背景色を変更しています。

 

 

テキストリンクパターン

テキストリンクでは、通常のブラウザと同じ表現方法ですが、色をやや薄めにしてデザインに馴染ませています。

 

 

Podで管理

これは非常に余談的ですが、どのバージョンのReader Viewを使っているかネイティブアプリから管理しやすいように CocoaPods (iOS用のライブラリ依存管理ツール)を利用しました。今回のプロジェクトではReaderViewのリリース毎にバージョニング・設定ファイル( AmebloReader.podspec )を更新し、ネイティブアプリのビルド時に指定したバージョンにアップデートしてもらいました(ちなみにAndroidはシェルで管理してました)。

Pod::Spec.new do |s|
s.name         = "AmebloReader"
s.version      = "0.2.3"
s.summary      = "HTML, CSS and JavaScript for Ameba app blog reader"
s.homepage     = "https://ghe/ameba-app/ameba-app-blogreader-webview"
s.license      = { :type => "Custom",
 :text => "Copyright (C) CyberAgent, Inc. All Rights Reserved." }
s.platform     = :ios
s.ios.deployment_target = "8.0"
s.source       = { :git => "git@ghe:ameba-app/ameba-app-blogreader-webview.git",
  :branch => 'master',
  :tag => "#{s.version}" }
s.ios.resource_bundle = { "AmebloReader" => ["dist/blog_ios.html"] }
end

 

デザインスプリント

記事を読むことに特化しているプロダクトにするために、開発メンバー(デザイナー・エンジニア)のスキル・知識を総動員しました。それらを引き出す手法として、今回のプロジェクトでは、デザインスプリントを採用してみました。

 

デザインスプリントはGoogle社が提唱する開発手法で素早いPDCAを可能にしてくれるものです。 この手法のいいところは、意見の強い誰かが言ったこと(利害関係に左右されていたら最悪です)を実装するのではなく、重要な決定にみんなの意見が入り、当事者意識が芽生えるところです。 ものづくりの過程では、開発者自身がいかに自分のものとして考えられるかということが重要です。 そう考えられれば、細かいところも丁寧に気をつけて実装しますし、自ら改良のための提案も進んでしたくなるものです。

 

実際には、デザインスプリントの手法を少しアレンジして実施しました。それでは、その開発フローをのぞいてみましょう。

 

課題決定

このプロジェクトにとって何が大事か、欠かせないものは何か、やってはいけないことは何かを決定します。参加者は思いついたことをそれぞれポストイットに書き出します。ここでは必ず紙に書き出すようにします。発言を求めてしまうと、意見の強い人に左右されてしまったり、いまいち自信がないと発表を控えてしまったりするからです。

投票

その後、それぞれよいと思ったアイデアの紙にシールを貼って投票します。この際に大事なことは、誰が言ったかではなく内容そのものについて評価することです。

 

よいと思ったアイディアには +1 シールを貼っていきます。こうすることで、プロジェクトにとって大事なこと・けしてやらないことなどがメンバー間で共有されます。

評価

投票の多かったものを中心に議論し、今回のテーマについて方向性を絞り込んでおきます。気になるところ・疑問に思うところは、この際に議論し、ある程度みなが納得している状態にします。

遷移図を描く

上記で決まった方向性をもとに、実際に遷移図に落としていきます。この際には、デザイナーだけでなく、エンジニアも一緒に考える方がよいでしょう。各プラットフォーム(OS)の作法に詳しいのは大抵の場合エンジニアですし、最終的に実装するのはエンジニアであることが多いからです。ここである程度一緒に決めておくとあとでデザイナーの元へ確認に行く頻度がかなり減ります。

 

実際に使った遷移図。遷移図は前後の流れも含めて描きます。デザイナーだけでなく、エンジニアも描くのでクオリティはマチマチです。

 

遷移図の評価

遷移図も、コンセプトと同様に議論し評価していきます。エンジニアのみなさん、「これは実装厳しいな...」と思ったらこの段階で遠慮せずに言っておきましょう(あとで徹夜にならないように...)。

実装 (プロトタイプ)

遷移図の評価ができ、案が決まったら実装してみます。実装者は、最初の段階から議論に参加しているのである程度納得した状態で実装できます。腑に落ちた状態かどうかで、実装スピード・クオリティは劇的に変わると思います(わたしはそうです)。

レビュー

実際に作ってみたもののレビューをします。ここでは、必要に応じて開発者だけでなく、ユーザーさんを呼んでのテストも有効です(今回のプロダクトでも数回行い、我々の想像以上に視野が集中しているという発見がありました)。ここで出た改善点を次回のデザインスプリントにいかしていきます。

上記のフローを隔週ベースで一周りするように進めました。実装の段階では、集中して進めるため、開発合宿を行ったりもしました。

 

開発合宿の様子。みんな集中してます。

 

XCodeとAndroid Studio両方を同時に開いているところがこのプロジェクトっぽいところです。

 

お昼は、弁当を注文してみんなで食べます。へいへい(運営担当)の弁当注文スキルもあがりました。

 

広告

広告というと「じゃま...」と感じている方もいるかと思いますが、いち開発者・いちユーザーとして、私自身も「なければないほどよい」と思っています。しかしながら、サービスを継続して提供していくためには広告による収益が大事であることも事実です。また、広告主、メディア、ユーザー全員にとって良かったと思える広告もあるでしょう。そこで、今回のプロジェクトではできるかぎり記事を読む邪魔をせず、効果を上げる以下の様な仕組みを検討しました。

inview率を上げる

通常、広告はSDKでコンテンツの読み込みの後に取得するため、表示が遅れてしまうことがあります。これはデータは読み込まれているのに、ユーザーに届いておらず無駄になっている状態で、誰にとっても喜ばしいことではありません。そこで、今回は記事データと同じタイミングでサーバで広告データを事前取得し、遅れず表示するようにしています。特に記事上部の広告は100%近い inview率 を保証でき価値の高い枠にできます。こうすることで、きちんと広告がユーザーの目に届き、価値があると感じたら押されることになります。

 

広告データは記事と一緒に取得しているので素早く表示され、ガタッと表示領域が伸びたりしない。

 

記事の邪魔をできるかぎりしない

広告の表示が遅く、事前に高さが確保されていない場合、誤ってタップしてしまうことがあります。しかしそれは本質的なタップではありません。それを防ぐため、事前に広告を取得・予め高さを決めて表示するようにしています。また、バナー表示を避け、できる限り記事のデザインと合わせることで記事から"浮いて目立つ"ことのないようにしています。

効果を上げて、枠の数を減らす

広告は数が多いほど効果が出やすい傾向にあるため、ついつい数を増やしてしまいがちです。しかしそれは、本来記事を読みに来ているにもかかわらず、広告だらけで読みにくい・不快だといった本末転倒なことになる可能性もあります。今回のプロジェクトでは上記のような対応をすることで、それぞれの枠の効果を上げることにより、広告の枠を増やし過ぎず、記事とのバランスをとれるように心がけました。

 

KPIs

最後に、このプロジェクトにおけるKPIについて触れて終わりにします。このプロジェクトでは、表示速度の改善・滑らかなページングによる PPU (Pageview Per User) の向上、表示内容最適化による 広告効果(CPM: Cost Per Mille) の向上を主要KPIとして設定しました。

それぞれ

PPU -> 約130%向上
アップ

CPM -> 約120~130%向上
アップ


というようにいまのところよい効果が出ています。

以上、アメブロのネイティブ化についてご紹介しました。iOS, Androidとも、Amebaアプリでご覧になれますので、ぜひ軽快になったブログ表示を体験してみてください。

 

iOSアプリ

 

Androidアプリ

Get it on Google Play

 

いいね!した人  |  リブログ(0)

1pixelさんの読者になろう

ブログの更新情報が受け取れて、アクセスが簡単になります

最近の画像つき記事  もっと見る >>
ページトップへ戻る