目的
FirebaseDynamicLinksを使って、開発したiOSアプリのメール認証→(ユーザー)登録において離脱率を減らすこと
※ 私が開発している Dieter というアプリではメール認証時の離脱率が深刻な問題となっていました。数値でいうと約30%のユーザーが離脱しています。iOSアプリ上でメールアドレス/パスワードを入力したユーザーのうち約30%がメール認証を行なっていない(or 行なっても,iOSアプリに戻りログインできていない)と言う状態です。
ユーザー登録フロー の変更点
ユーザー情報入力→ユーザー登録→確認画面
に Firebase Dynamic Links を導入し、メール認証+アプリへの自動遷移 によるユーザー登録を可能とします。
Firebase Dynamic Links って何?
アプリを自動的に開いてくれるURLです。(別途設定すれば)アプリが未インストールの場合はAppStoreに遷移します。また、iOS/Android等 様々なプラットフォームで動作します。
Firebaseが提供している技術です。
(Firebase Dynamic Links - Firebaseリファレンス から詳細な説明を抜粋)
Firebase Dynamic Links について
Dynamic Links により、ユーザーがリンクを開いたプラットフォームで得られる最高のエクスペリエンスを提供できるようになります。iOS または Android でダイナミックリンクを開くと、ネイティブアプリのリンク先のコンテンツに直接移動します。デスクトップ ブラウザでダイナミック リンクを開くと、ウェブサイト上の同じコンテンツに移動します。
さらに、ダイナミック リンクはアプリのインストールが必要な場面でも利用できます。たとえば、ダイナミック リンクを開いたユーザーの iOS デバイスまたは Android デバイスにアプリがインストールされていない場合にインストールを促し、インストール完了後にアプリを起動してリンクを開くといったこともできます。
Firebase Dynamic Links の注意点
-
2023年5月ごろから、Firebase Dynamic Links を用いた実装が非推奨となっている
- 公式によると「詳細については、2023 年第 3 四半期に発表する予定」とのこと。私は、今後新しい遷移の技術が発表され、その技術に Firebase Dynamic Links が置き換わっていくと予想しています。
-
Firebase無料プラン(Spark)の場合、メール認証制限(5件/1日)がある
-
公式が公開している無料枠の制限を見てみると 5件/1日 という制限が設けられていました。
-
余談ですが、私はこれを機に 有料枠(Blaze) にアップグレードしました。制限ある中でサービスの運用するのはきついと判断したので ...
-
他にURLからアプリへ遷移可能な技術はないのか?
代表的なものが2つあります!
Custom URL Scheme
URLからアプリ画面へのみ(つまりアプリインストールの有無に応じたWEBサイトへの遷移はできない)遷移可能な技術。遷移先アプリを未インストールの場合エラー発生。
遷移先として設定しているアプリ固有のスキームを設定しURLを設定する。
(例: myapp://page1
, myapp://user/123
)
※ この場合 スキーム=myapp
myapp:// に続く文字列(page1, user/123)に応じてアプリ側で処理を書きます。
この際、アプリ側の処理を効率的に行うため Crossroad (CookPadのOSS) が存在しています。CustomURLScheme,Crossroadについて詳細が知りたい方は以下のCookPadテックブログを参考にしてみてください。
Universal Link
Safariを経由せずに(インストール済みの)アプリへ遷移可能。← Custom URL Scheme と同様
アプリ未インストール時に任意のWEBサイトへ遷移可能。
iOS端末専用の遷移方法である。
つまり、Custom URL Scheme で実現できていなかった アプリインストールの有無に応じた遷移
が可能となったのです。
しかし、Apple専用のプロトコルであるため Androidで共通して使えない
ことや、サーバー上に別途でファイル(※1)を作成しないといけない=手間がかかる
、といったデメリットが存在していました。
※1 : apple-app-site-association
⭐️ これら Universal Link のデメリットを解決したものが、Firebase Dynamic Links です。
(再) Firebase Dynamic Links とは?
アプリを自動的に開いてくれるURLです。(別途設定すれば)アプリが未インストールの場合はAppStoreに遷移します。また、iOS/Android等 様々なプラットフォームで動作します。
【実装】Firebase Dynamic Links によるメール認証
[1/5] Firebase Dynamic Links を設定
1: エンゲージメント > Dynamic Links を押す
2: ドメインの設定
: 任意のドメインを設定 (例: example.page.link)
3: 新しいダイナミックリンクを押す
-
短縮URLの設定
: 任意の文字列を設定 (例: open) -
ダイナミックリンクの設定
(※2)- ディープリンクのURL設定: 基本は対象アプリがあるAppStoreのURL。
- アプリ未インストール時の遷移先URL
- ダイナミックリンク名: 任意 (例: AppStore)
- ディープリンクのURL設定: 基本は対象アプリがあるAppStoreのURL。
-
Apple 用のリンク動作の定義
: ディープリンクを Apple アプリで開く > 対象のFirebaseプロジェクトを選択(※3)- アプリがインストールされていない場合のユーザーの移動先: アプリのAppStoreページ
-
Android 用のリンク動作の定義
: ブラウザでディープリンクの URL を開く -
キャンペーントラッキング、ソーシャルタグ、詳細オプション(省略可)
: 任意で設定
※2 : ブラウザを対象とした遷移先, モバイルの遷移先は次で設定可能
※3 : Firebaseプロジェクトに Apple Store ID
と チームID
を追加する必要あり
4: 承認済みドメイン に apps.apple.com を追加
Authentication
> Setting
> 承認済みドメイン
に、apps.apple.com
を追加します。
追加する理由は、(メール送信用の設定を実装で)AppStoreのアプリを指定可能にするためです。
[2/5] XCodeプロジェクトの設定
URL Types の設定
1: TARGETS
> Info
> URL Types
> +
※ Identifier: 任意
※ URL Schemes: アプリごと設定される Bundle ID。(確認 : TARGETS
> General
> Identify
> Bundle Identigy
)
Associated Domains の設定
1: TARGET
> Signing & Capabilities
> +Capability
> Associated Domains
2: Domains
に 「applink: Firebase上 Dynamic Links を設定 > 2:ドメインの設定
で設定したドメイン」 を追加 (例: applink:example.page.link)
[3/5] メールを送りメール認証が可能であることを確認する
1:メール送信用の設定を実装
アプリ起動時(SceneDelegate.swift
)にメール送信のプログラムが動くようにしています。
今回はメールが届くかどうかを確認することが目的だったの...
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// 〜〜〜
// //MARK: practice Dynamic Links
let actionUrl = "https://apps.apple.com/jp/app/timelab/id6446396011?l=en&platform=iphone" // 対象アプリのURL
let actionCodeSettings = ActionCodeSettings()
actionCodeSettings.url = URL(string: actionUrl)
// The sign-in operation has to always be completed in the app.
actionCodeSettings.handleCodeInApp = true
actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)
let email = "hogehoge@example.com" // テスト用のメール, @iCloud.com にメールが届かなかった... @gmail.comには正常に届く。
// メール送信
Auth.auth().sendSignInLink(toEmail: email, actionCodeSettings: actionCodeSettings) { error in
if let error = error {
print("sendSignInLInk Error")
print(error)
return
}
UserDefaults.standard.set(email, forKey: "email")
print("success sendSignInLink")
}
// 〜〜〜
}
}
メール受信を確認!
未インストール | インストール済み |
---|---|
[4/5] URLから遷移したことを検知する
Firebase Dynamic Links のURLを押しiOSアプリへ遷移 → 遷移を検知 する必要があります。
遷移を検知するプログラムを SceneDelegate.swift にて実装をしていきます。
FirebaseDynamicLinksのチュートリアル や 様々な記事 で AppDelegate.swift による実装方法が挙げられています。
しかし、iOS13以降およびXcode11以降で生成されるプロジェクトにはSceneDelegate.swiftが追加され、AppDelegate.swiftではなくSceneDelegate.swiftに実装を行う必要があります。(DeNAさんテックブログより)
以下のプログラムは、アプリのタスクが終了しているかどうか
に応じた2通りの実装を示しています。
import UIKit
import Firebase
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// 〜
// アプリのタスクが終了している状態から Firebase Dynamic Links を用いてアプリを起動した時
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let userActivity = connectionOptions.userActivities.first(where: { $0.webpageURL != nil }) {
guard let url = userActivity.webpageURL else { return }
if let user = Auth.auth().currentUser { return } // ユーザーがログイン状態でないことを担保する
DynamicLinks.dynamicLinks().handleUniversalLink(url) { [weak self] dynamicLink, err in
if err != nil { return } else {
guard let url = dynamicLink?.url else { return }
guard (dynamicLink?.matchType == .unique || dynamicLink?.matchType == .default) else { return }
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) ,let queryItems = components.queryItems else { return }
// Firebase Dynamic Links を用いた処理を書く
print(url)
}
}
}
}
// アプリのタスクが終了"していない"状態から Firebase Dynamic Links を用いてアプリを起動した時
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
guard let url = userActivity.webpageURL else { return }
DynamicLinks.dynamicLinks().handleUniversalLink(url) { dynamicLink, err in
if err != nil { return } else {
guard let url = dynamicLink?.url else { return }
guard (dynamicLink?.matchType == .unique || dynamicLink?.matchType == .default) else { return }
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) ,let queryItems = components.queryItems else { return }
// Firebase Dynamic Links を用いた処理を書く
print(url)
}
}
}
// 〜
}
print(url)
の出力結果
https://----------.firebaseapp.com/__/auth/action?apiKey=------------------&mode=signIn&oobCode=-------------------&continueUrl=https://〜〜〜.page.link/〜〜〜&lang=en
※ continueUrl=https://〜〜〜.page.link/〜〜〜
が今後重要となります
[5/5] 画面遷移後 ユーザー登録を行う
Firebase Dynamic Links を押す
> 画面遷移
を行った後、(画面が開かれた瞬間(viewDidLoad))にユーザー登録を行います。
ユーザー登録に使用する メールアドレス や パスワード
は、アカウント作成画面で入力したデータを使用します。この時入力したデータは端末内に保存しておき、ユーザー登録時に端末内から呼び出す という流れでデータを使用していきます。
画面遷移後のユーザー登録に関するプログラムは、各プロダクトによって実装方針が変わるものだと思うため、今回割愛します。
以上で「Firebase Dynamic Links を使って ユーザー登録における 離脱率を減らそうって話」は終わりです。より良い開発ライフをお過ごしください!
参考サイト