クラウドワークスのiOSアプリ会員登録を改善した話

この記事は[CrowdWorks Advent Calendar 2017](https://qiita.com/advent-calendar/2017/crowdworks)の10日目の記事です。

## はじめに

クラウドワークスでiOSアプリエンジニアをやっています@tkoshidaです。

クラウドワークスではお仕事を受注するクラウドワーカー向けのiOSアプリ[CrowdWorks for Worker](https://itunes.apple.com/jp/app/id1013797155)をApp Storeで公開しています。
社内では最近そのiOS/AndroidアプリがWeb側のサービスと比較して継続率が高かったりすることなどから、アプリに注力するようになってきています。

今回はこれまで課題が多かったアプリ会員登録まわりの、iOSアプリにおける改善の取り組みについてご紹介できればと思います。

## これまでのアプリでの会員登録の流れとその課題

これまでのアプリでの会員登録は次のような流れでした。

![Artboard.png](https://qiita-image-store.s3.amazonaws.com/0/39009/ac156332-65a3-b616-627c-6ebc6cc2b129.png)

このように、アプリインストール後に会員登録しようとメールアドレスを登録すると確認メールを受信し、メール内の確認用URLを開くと最終的にはスマホサイトで会員登録する流れとなっていました。このときの主な課題点としては、次のようなものでした。

### (課題1) アプリからの会員登録はすべてブラウザでスマホサイトに流していた

ユーザーがスマホサイトで会員登録が終わってもアプリに戻る動線がなく、アプリからの離脱に繋がっていました。

### (課題2) スマホサイトで会員登録したときの認証情報がアプリに引き継がれない

スマホサイトで会員登録を完了しても、アプリを利用するにはアプリのログイン画面で再度ID/Passwordを入力してログインしなおさなければならなく離脱につながっていました。

### (課題3) 会員登録フォームの入力項目数が多い

下記のようにフォーム入力項目数は多く、ユーザーがスマホで入力するにはスクロールしながら入力するため大変で離脱に繋がっていました。

<img width="512" alt="スクリーンショット 2017-12-07 13.15.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/39009/d2da66f1-3ed1-38a5-22b9-2e43360c245d.png">


### (課題4) 会員登録フォームの入力が不親切

たとえば全ての情報を入力した後でないとvalidationエラーが表示されないため、途中で入力ミスに気づきにくかったりします。

### (課題5) そもそもアプリにSNS会員登録の動線がなかった

クラウドワークスではメールアドレスによる会員登録以外に、Facebook, Yahoo, GoogleのSNSアカウントでの会員登録が可能でしたが、アプリ内にはメールアドレスによる登録の動線しか存在しませんでした。

## アプリでの会員登録の課題を改善する

上記のように、ユーザーがアプリから会員登録をするにあたりいくつもの課題があったため、アプリからの新規会員をうまく増やせているとは言えない状況でした。

そこでこの状況を改善するため、以下のような対策を行いました。

### (対策1) メール内のメールアドレス確認用リンクをFirebase dynamic linksのURLに変更

メール内のメールアドレス確認用リンクは通常のクラウドワークスサイトへのリンクであったため、リンクを開くとアプリではなくブラウザでスマホサイトが開いてしまっていました。

これをアプリからの会員登録の場合には、[Firebase dynamic links](https://firebase.google.com/docs/dynamic-links/?hl=ja)でアプリへのディープリンクURLにすることにより、タップしたときにアプリがインストールされていればアプリの会員登録フォームに遷移し、
インストールされていなければブラウザの会員登録フォームに遷移させることができます。
これによりアプリに戻る動線ができたので、アプリからの離脱が減らせるようになりました。

ただし、URLがFirebase dynamic linksのドメインになってしまうため、URLは直接見えないようにボタンの見た目にする対応もあわせておこないました。

変更前 | 変更後
--- | ---
![名称未設定_size.png](https://qiita-image-store.s3.amazonaws.com/0/39009/2bcccc23-fb93-1ced-00fb-174d763e6721.png) | ![名称未設定2.png](https://qiita-image-store.s3.amazonaws.com/0/39009/c13a3877-72b4-51c1-2a20-115d08f64b6e.png)

### (対策2) ネイティブで会員登録フォームを実装しWeb API（新規）をリクエストするようにする

実はWebView（サーバーからHTMLページを返してそれを表示）で実装しても良いのではないか、という話はありました。
会員登録フォームのアプリ上の体験をよくしていくには何度かドラスティックに画面構成も変えうることもあるだろうし、その場合にはWebViewで作っておいた方がアップデートの工数は少ないだろうと。

しかし課題であったフォーム入力における体験の悪さからの離脱を改善するために、ネイティブによる操作性の良さを取り入れたかったりなどの理由により総合的にネイティブでの実装となりました。

アプリ上でフォーム入力して会員登録まで実行ができるため、登録完了後はログイン済みの状態でアプリの利用を開始することが可能となります。

### (対策3) アプリ上で自動入力なども対応することによりストレスの少ないフォーム入力ができるようにする

会員登録フォームの中で入力の面倒なところとして、住所入力があります。
Webサイト側も対応済みですが、郵便番号から住所の自動入力をするようにしています。
またアプリ独自の対応として、名前のふりがな入力も自動入力するようにしています。

郵便番号変換 | ふりがな自動入力
--- | ---
![ゆうびん.gif](https://qiita-image-store.s3.amazonaws.com/0/39009/b60528b1-d7d0-179d-4558-2734345bc53c.gif) | ![ふりがな.gif](https://qiita-image-store.s3.amazonaws.com/0/39009/c06f295c-46e8-6be6-d3f0-bf0372b0a958.gif)

ふりがなの自動入力には、iOSにはローマ字からひらがなを取得するのに `CFStringTransform` という関数が提供されているのでこれを使うことにより実現しています。

```swift
static func hurigana(text: String) -> String {
    let inputText = text as NSString
    let outputText = NSMutableString()
    var range = CFRangeMake(0, inputText.length)
    let locale = CFLocaleCopyCurrent()
    let tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, inputText as CFString, range, kCFStringTokenizerUnitWordBoundary, locale)
    var tokenType = CFStringTokenizerGoToTokenAtIndex(tokenizer, 0)
    
    while tokenType.rawValue != 0 {
        range = CFStringTokenizerGetCurrentTokenRange(tokenizer)
        if let latin = CFStringTokenizerCopyCurrentTokenAttribute(tokenizer, kCFStringTokenizerAttributeLatinTranscription) as? NSString {
            let hurigana = latin.mutableCopy() as! NSMutableString
            CFStringTransform(hurigana, nil, kCFStringTransformLatinHiragana, false)
            outputText.append(hurigana as String)
        } else {
            if let substring = CFStringCreateWithSubstring(kCFAllocatorDefault, inputText as CFString, range) {
                outputText.append(substring as String)
            }
        }
        tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)
    }
    
    return outputText as String
}
```

ちなみにTextFieldのプレースホルダーは、Androidの[Material DesignのTextField](https://material.io/guidelines/components/text-fields.html)のように入力時には上によけて入力文字に消されないようにしていつでも見える状態にし、ユーザーにわかりやすいフォームにする対応も実装してたりします。

### (対策4) フォーム画面は一画面にはせず情報のまとまりでページを分ける

フォーム項目数の多さでユーザーが圧倒されないよう、情報のまとまりでページを分け細かいステップにします。
それにより入力に対するvalidationのフィードバックをページごとにすぐに受けられたり、ページが進むペースが小刻みになることにより心地よいリズムの体験にします。

### (対策5) 会員登録Web APIのロボット対策としてGoogleのInvisible reCAPTCHAを使うようにする

Web APIで会員登録ができるようになるため、ロボット対策としてGoogleの[Invisible reCAPTCHA](https://developers.google.com/recaptcha/docs/invisible)を使うことにより不正に会員登録をされないように対策も行なうことにしました。

しかしiOS向けにはGoogleからreCAPTCHA用のライブラリがまだ提供されていない（Android向けには存在）ため、GitHubで[ReCaptcha](https://github.com/fjcaetano/ReCaptcha)というライブラリを見つけたのでこれを使いました。
WebViewをラップすることでWebのreCAPTCHAをiOSでも利用可能にしたライブラリのようです。

Invisible reCAPTCHAなので大抵の人は車の画像選択などは表示されないので、存在を気にすることなく会員登録が出来るのではないでしょうか。

### (対策6) 会員登録Web APIでフォームをバージョン判定するようにする

会員登録のフォーム入力項目は仕様変更などにより今後増減することが想定されます。
フォーム仕様が変わるとユーザーがインストールしたアプリとはフォームに不一致が発生して会員登録に失敗してしいます。
そこで会員登録フォームにバージョン付けしてやることにより、ユーザーのアプリの会員登録フォームが古いバージョンかを判定することができるようになります。
会員登録フォーム表示の際にWeb APIにてフォームバージョンをチェックすれば、アプリがアップデートが必要かを判定することができ、実際に必要とあらばアップデートを促すような処理を実装することとしました。

### (対策7) SNS（Facebook/Google/Yahoo）による会員登録も対応

これはもともと機能が抜けていたので、ちゃんと対応しようということで対応となりましたw

SNSからの会員登録の場合は、SNSに登録される情報も一部使って会員登録のフォームを埋めることができるため、会員登録は比較的楽に行えるようになります。

## 改善した結果

上記の通り、改善した結果次のような会員登録の流れになります。

![Artboard Copy 2.png](https://qiita-image-store.s3.amazonaws.com/0/39009/0425d425-db75-28f0-20ca-c8b160c13fa7.png)


改善前には会員登録フォームでスマホサイトに流れていたのが、アプリに戻ってこられるようになりました。
また会員登録フォームは入力しやすいものとなり、SNSからの会員登録もできるようになりました。

さて改善した結果の効果についてですが、以下のグラフがアプリ経由会員登録数の推移となります。
他施策の効果なども入って若干わかりづらいですが、アプリのリリースによる効果もあってアプリ経由の会員登録は増えてきています。
※アプリの会員登録改善のリリースは、SNSによる会員登録と、メールアドレスからの会員登録の2段階のリリースに分かれています。

![名称未設定.png](https://qiita-image-store.s3.amazonaws.com/0/39009/126a4dcc-b891-deba-b129-2b89de563b2e.png)


## おわりに

会員登録については、他にも以下のような議論がありました。

* 会員登録の時点で今のフォーム内容は全部必要なんだっけ？（サービス利用中の必要になったタイミングに変更するなど）といった入力フォーム項目の見直しの議論
* SNSでの会員登録にLINEを追加したい

ただ、現状では仕様の調整や実装などに多くのコストがかかることが見込まれますので、これらの検討や改善は別途引き続きやっていければと思います。

それでは、引き続き[CrowdWorks Advent Calendar 2017](https://qiita.com/advent-calendar/2017/crowdworks)をよろしくお願いします！