新規ユーザーにアプリをインストールしてもらう最も効果的な方法の 1 つは、ユーザーがアプリのコンテンツを友達と共有できるようにすることです。 Dynamic Links を使用すると、ユーザー間の優れた共有エクスペリエンスを作成できます。友人からコンテンツのおすすめを受け取ったユーザーは、リンクをクリックして、アプリにアクセスしなければならない場合でも、アプリ内の共有コンテンツに直接移動できます。ストアまたは Google Play ストアにアクセスして、最初にアプリをインストールします。
ユーザー紹介の持続性と Dynamic Links の持続性を組み合わせることで、ユーザー間の共有機能と紹介機能を作成して、新しいユーザーをアプリのコンテンツに直接誘導したり、紹介者と被紹介者に相互に利益をもたらすプロモーションを提供したりすることで、新しいユーザーを呼び込むことができます。 .
主な利点
- アプリを初めて開いた新規ユーザーは、友人が共有したい内容に基づいてコンテキスト化された、カスタマイズされた初回実行エクスペリエンスを取得します。たとえば、共有されたコンテンツを表示したり、招待した友達と自動的に接続したりできます。
- 友達があなたのアプリをインストールしているかどうかに関係なく、ユーザーがプラットフォーム間で友達と簡単にコンテンツを共有できるようにします。
始める方法は次のとおりです。
Firebase と Dynamic Links SDK を設定する
新しい Firebase プロジェクトを設定し、Dynamic Links SDK をアプリにインストールします。
Dynamic Links SDK をインストールすると、ユーザーがアプリをインストールした後など、Firebase は Dynamic Link に関するデータをアプリに渡すことができます。
動的リンクを作成する
次に、ユーザーが友人に送信できるリンクを設定します。ユーザーの友達がまだアプリをインストールしていなくても心配はいりません。 Dynamic Links がそれを処理します。
共有可能にしたいコンテンツの要素ごとに、ダイナミック リンクを作成します。
ダイナミック リンクを作成するときは、共有しているコンテンツを識別するために使用されるlink
パラメーターとして HTTP または HTTPS URL を指定する必要があります。同等のコンテンツを含む Web サイトがある場合は、Web サイトの URL を使用する必要があります。これにより、これらのリンクは、デスクトップ ブラウザーなど、Dynamic Links をサポートしていないプラットフォームで正しくレンダリングされます。例:
https://example.page.link/?link=https://www.example.com/content?item%3D1234&apn=com.example.android&ibi=com.example.ios&isi=12345
URL エンコードされたパラメーターを追加することで、データ ペイロードに追加情報を追加することもできます。たとえば、ゲームへの招待など、特定のユーザー向けのリンクであることを示すことができます。
https://example.page.link/?link=https://www.example.com/invitation?gameid%3D1234%26referrer%3D555&apn=com.example.android&ibi=com.example.ios&isi=12345
これらのリンクを共有する前に、 Firebase Dynamic Links URL Shorter APIを使用して、見やすい URL を生成することをお勧めします。短いダイナミック リンクは次の例のようになります:
https://example.page.link/WXYZ
どちらのリンクを使用しても、ユーザーがデバイスでダイナミック リンクを開くと、 apn
パラメーター (Android の場合) またはibi
およびisi
パラメーター (iOS の場合) で指定されたアプリは、ユーザーを Play ストアまたは App Store に誘導してアプリをインストールします。まだインストールされていない場合。次に、アプリをインストールして開くと、'link' パラメーターで指定された URL がアプリに渡されます。
ダイナミック リンクを送信する「共有」ボタンを追加する
まず、チャット ルームに人々を招待するためのリンクを生成する、ハングアウトのようなルーム ベースのチャット アプリの簡単な例を見てみましょう。
iOS


アンドロイド


迅速
func generateContentLink() -> URL { let baseURL = URL(string: "https://your-custom-name.page.link")! let domain = "https://your-app.page.link" let linkBuilder = DynamicLinkComponents(link: baseURL, domainURIPrefix: domain) linkBuilder?.iOSParameters = DynamicLinkIOSParameters(bundleID: "com.your.bundleID") linkBuilder?.androidParameters = DynamicLinkAndroidParameters(packageName: "com.your.packageName") // Fall back to the base url if we can't generate a dynamic link. return linkBuilder?.link ?? baseURL }
Objective-C
- (NSURL *)generateContentLink { NSURL *baseURL = [NSURL URLWithString:@"https://your-custom-name.page.link"]; NSString *domain = @"https://your-app.page.link"; FIRDynamicLinkComponents *builder = [[FIRDynamicLinkComponents alloc] initWithLink:baseURL domainURIPrefix:domain]; builder.iOSParameters = [FIRDynamicLinkIOSParameters parametersWithBundleID:@"com.your.bundleID"]; builder.androidParameters = [FIRDynamicLinkAndroidParameters parametersWithPackageName:@"com.your.packageName"]; // Fall back to the base url if we can't generate a dynamic link. return builder.link ?: baseURL; }
Kotlin+KTX
fun generateContentLink(): Uri { val baseUrl = Uri.parse("https://your-custom-name.page.link") val domain = "https://your-app.page.link" val link = FirebaseDynamicLinks.getInstance() .createDynamicLink() .setLink(baseUrl) .setDomainUriPrefix(domain) .setIosParameters(DynamicLink.IosParameters.Builder("com.your.bundleid").build()) .setAndroidParameters(DynamicLink.AndroidParameters.Builder("com.your.packageName").build()) .buildDynamicLink() return link.uri }
Java
public static Uri generateContentLink() { Uri baseUrl = Uri.parse("https://your-custom-name.page.link"); String domain = "https://your-app.page.link"; DynamicLink link = FirebaseDynamicLinks.getInstance() .createDynamicLink() .setLink(baseUrl) .setDomainUriPrefix(domain) .setIosParameters(new DynamicLink.IosParameters.Builder("com.your.bundleid").build()) .setAndroidParameters(new DynamicLink.AndroidParameters.Builder("com.your.packageName").build()) .buildDynamicLink(); return link.getUri(); }
動的リンクを作成したら、標準のプラットフォーム共有フローを起動する共有ボタンを UI に追加できます。
迅速
lazy private var shareController: UIActivityViewController = { let activities: [Any] = [ "Learn how to share content via Firebase", URL(string: "https://firebase.google.com")! ] let controller = UIActivityViewController(activityItems: activities, applicationActivities: nil) return controller }() @IBAction func shareButtonPressed(_ sender: Any) { let inviteController = UIStoryboard(name: "Main", bundle: nil) .instantiateViewController(withIdentifier: "InviteViewController") self.navigationController?.pushViewController(inviteController, animated: true) }
Objective-C
- (UIActivityViewController *)shareController { if (_shareController == nil) { NSArray *activities = @[ @"Learn how to share content via Firebase", [NSURL URLWithString:@"https://firebase.google.com"] ]; UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:activities applicationActivities:nil]; _shareController = controller; } return _shareController; } - (IBAction)shareLinkButtonPressed:(UIView *)sender { if (![sender isKindOfClass:[UIView class]]) { return; } self.shareController.popoverPresentationController.sourceView = sender; [self presentViewController:self.shareController animated:YES completion:nil]; }
Kotlin+KTX
private fun onShareClicked() { val link = DynamicLinksUtil.generateContentLink() val intent = Intent(Intent.ACTION_SEND) intent.type = "text/plain" intent.putExtra(Intent.EXTRA_TEXT, link.toString()) startActivity(Intent.createChooser(intent, "Share Link")) }
Java
private void onShareClicked() { Uri link = DynamicLinksUtil.generateContentLink(); Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, link.toString()); startActivity(Intent.createChooser(intent, "Share Link")); }
この例では、デフォルトの共有 UI がリンクを共有するためのアプリのリストを自動的に表示するため、数行のコードで独自のアプリに設定できます。
ユーザーが連絡先を選択してアプリでメッセージを作成するのではなく、これらのアクションは、共有ダイアログから選択したアプリに委任されます。さらに、共有を他のアプリに委任すると、ユーザーに連絡先のアクセス許可を求める必要がなくなり、ユーザーは選択したアプリ内の拡張された連絡先リストから選択できるようになります。ソーシャル共有をより容易にするために、ソーシャル メディア プレビュー メタデータをダイナミック リンクに追加できます。このメタデータは、主要なソーシャル チャネルのリンクと共に表示されます。
ただし、テキストのない裸のリンクを送信するだけでは、説得力のある紹介には不十分な場合があります。リンクに短いメッセージを付け、可能であればより充実したプレゼンテーションを付けることで、ユーザーは紹介を受けたときにその価値提案を理解できます。
iOS


アンドロイド


これは前の例よりも複雑ですが、アプローチはほぼ同じです。この画面には、招待の価値提案と、主要なソーシャル チャネルに共有するためのボタンを含む大きなグラフィックがあります。この UI フローには冗長性があります。一部の共有チャネルは個別に表示され、電子メールの招待に件名を追加するなど、チャネル固有のメッセージのカスタマイズを可能にします。この招待メニューでは、次のことを行います。
- メール、テキスト メッセージ、コピー リンクの共有ボタンを表示し、それらのメッセージを適切にカスタマイズします。電子メールには件名が含まれ、改行、画像、および空白を含む長い本文を含めることができます。テキストには、改行を含む短い本文を含める必要がありますが、空白はほとんどなく、画像は含めないでください。リンクのコピーは、リンクをコピーするだけで、他には何もコピーしません。
- リンクに付随する短い招待メッセージなど、その他すべてにシステム共有 UI を使用します。
- アプリの招待を処理するための特別なロジックを持つ別のアプリへの URL スキームまたはユニバーサル リンクを介したディープ リンク。これは、組織と他のアプリとの間のパートナーシップの外では機能せず、小規模な組織の場合は選択肢にならない可能性があります。とはいえ、一部のアプリは、ユニバーサル/ディープリンクの動作を公開している場合があります。サンプルでは、これのダミー バージョンを実装します。
最初に、招待の情報のみをカプセル化し、機能を含まない招待コンテンツ タイプを定義します。このようにして、データ型から始めて、そのデータをどのように組み合わせるかという観点からコードを考えることができます。
迅速
/// The content within an invite, with optional fields to accommodate all presenters. /// This type could be modified to also include an image, for sending invites over email. struct InviteContent { /// The subject of the message. Not used for invites without subjects, like text message invites. var subject: String? /// The body of the message. Indispensable content should go here. var body: String? /// The URL containing the invite. In link-copy cases, only this field will be used. var link: URL }
Objective-C
/// The content within an invite, with optional fields to accommodate all presenters. /// This type could be modified to also include an image, for sending invites over email. @interface InviteContent : NSObject <NSCopying> /// The subject of the message. Not used for invites without subjects, like text message invites. @property (nonatomic, readonly, nullable) NSString *subject; /// The body of the message. Indispensable content should go here. @property (nonatomic, readonly, nullable) NSString *body; /// The URL containing the invite. In link-copy cases, only this field will be used. @property (nonatomic, readonly) NSURL *link; - (instancetype)initWithSubject:(nullable NSString *)subject body:(nullable NSString *)body link:(NSURL *)link NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @end
Kotlin+KTX
/** * The content of an invitation, with optional fields to accommodate all presenters. * This type could be modified to also include an image, for sending invites over email. */ data class InviteContent( /** The subject of the message. Not used for invites without subjects, like SMS. */ val subject: String?, /** The body of the message. Indispensable content should go here. */ val body: String?, /** The URL containing the link to invite. In link-copy cases, only this field will be used. */ val link: Uri )
Java
/** * The content of an invitation, with optional fields to accommodate all presenters. * This type could be modified to also include an image, for sending invites over email. */ public class InviteContent { /** * The subject of the message. Not used for invites without subjects, like SMS. **/ @Nullable public final String subject; /** * The body of the message. Indispensable content should go here. **/ @Nullable public final String body; /** * The URL containing the link to invite. In link-copy cases, only this field will be used. **/ @NonNull public final Uri link; public InviteContent(@Nullable String subject, @Nullable String body, @NonNull Uri link) { // ... } }
ここで必要なデータは URL だけです。これがないと、ユーザーをアプリに招待することはできません。他のデータは、電子メールを送信するために明確に構造化されているため、他の場合には少し厄介です.テキストで招待状を送信する場合、リンクに付随する宣伝文句は電子メールの件名と同じように読めるかもしれませんが、ソーシャルメディアに共有する場合.テキストに付随するリンクは、電子メールの本文に似ている場合があります。アプリの最適なバランスを見つけるには、これを自分で試す必要があります。不明な場合は、いつでもRemote Configなどのサービスを使用して、アプリの起動後にテキスト値を変更できるようにすることができます。
迅速
/// A type responsible for presenting an invite given using a specific method /// given the content of the invite. protocol InvitePresenter { /// The name of the presenter. User-visible. var name: String { get } /// An icon representing the invite method. User-visible. var icon: UIImage? { get } /// Whether or not the presenter's method is available. iOS devices that aren't phones /// may not be able to send texts, for example. var isAvailable: Bool { get } /// The content of the invite. Some of the content type's fields may be unused. var content: InviteContent { get } /// Designated initializer. init(content: InviteContent, presentingController: UIViewController) /// This method should cause the presenter to present the invite and then handle any actions /// required to complete the invite flow. func sendInvite() }
Objective-C
/// A type responsible for presenting an invite given using a specific method /// given the content of the invite. @protocol InvitePresenter <NSObject> /// The name of the presenter. User-visible. @property (nonatomic, readonly) NSString *name; /// An icon representing the invite method. User-visible. @property (nonatomic, readonly, nullable) UIImage *icon; /// Whether or not the presenter's method is available. iOS devices that aren't phones /// may not be able to send texts, for example. @property (nonatomic, readonly) BOOL isAvailable; /// The content of the invite. Some of the content type's fields may be unused. @property (nonatomic, readonly) InviteContent *content; /// Designated initializer. - (instancetype)initWithContent:(InviteContent *)content presentingViewController:(UIViewController *)controller; /// This method should cause the presenter to present the invite and then handle any actions /// required to complete the invite flow. - (void)sendInvite; @end
Kotlin+KTX
/** * Presents the invite using a specific method, such as email or social. */ open class InvitePresenter( /** The user-visible name of the invite method, like 'Email' or 'SMS' */ val name: String, /** An icon representing the invite method. */ @param:DrawableRes @field:DrawableRes val icon: Int, /** Whether or not the method is available on this device. For example, SMS is phone only. */ val isAvailable: Boolean, /** The Content of the invitation */ val content: InviteContent ) { /** * Send the invitation using the specified method. */ open fun sendInvite(context: Context) { // ... } }
Java
/** * Presents the invite using a specific method, such as email or social. */ public class InvitePresenter { /** * The user-visible name of the invite method, like 'Email' or 'SMS' **/ public final String name; /** * An icon representing the invite method. **/ @DrawableRes public final int icon; /** * Whether or not the method is available on this device. For example, SMS is phone only. **/ public final boolean isAvailable; /** * The Content of the invitation **/ public final InviteContent content; public InvitePresenter(String name, @DrawableRes int icon, boolean isAvailable, InviteContent content) { // ... } /** * Send the invitation using the specified method. */ public void sendInvite(Context context) { // ... } }
あとは、これを選択した UI コンポーネントにプラグインするだけです。この招待フローの完全な実装については、iOSおよびAndroid 用の GitHub のサンプルを参照してください。
これらはすべて、ユーザーが友人に招待状を送信できるようにするための方法であり、最も軽量な招待状ソリューションです。多くの人気のあるアプリは、独自のバックエンドを介して電子メールを送信することによっても招待状を配信します。これには、メール送信サービスを統合する必要がありますが、他の方法では利用できない多くの利点があり、いくつかの小さな欠点があるだけです.
長所:
- ユーザーが送信前に変更できない複雑なマークアップを含む電子メールを有効にします。
- より詳細な追跡/分析を有効にします (つまり、バックエンドで成功と失敗を送信します)。
短所:
- スパムとしてフラグが立てられる可能性が高いメール
- メール配信サービスとの統合が必要
- アプリ内の連絡先権限が必要です
一般に、独自の電子メール配信サービスを介して招待状を送信すると、汎用性は犠牲になりますが、より一貫性のある、より充実した招待体験が得られます。
アプリでリンクされたコンテンツを開く
最後に、リンクされたコンテンツを受信者に表示できるように、アプリに渡されたリンクを受け取る必要があります。これは、Dynamic Links SDK を使用すると簡単です。
iOS
iOS では、 application:continueUserActivity:restorationHandler:
メソッドを実装してダイナミック リンクを受け取ります。復元ハンドラーでは、 handleUniversalLink:completion:
を呼び出すことでダイナミック リンクを取得できます。ダイナミック リンクがアプリに渡された場合、 FIRDynamicLink
のurl
プロパティから取得できます。例えば:
Objective-C
[[FIRDynamicLinks dynamicLinks]
handleUniversalLink:userActivity.webpageURL
completion:^(FIRDynamicLink * _Nullable dynamicLink,
NSError * _Nullable error) {
NSString *link = dynamicLink.url;
BOOL strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong;
// ...
}];
迅速
FIRDynamicLinks.dynamicLinks()?.handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
let link = dynamicLink.url
let strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong
// ...
}
さらに、 application:openURL:options:
メソッドでdynamicLinkFromCustomSchemeURL:
を呼び出して、カスタム スキーム URL としてアプリに渡されるダイナミック リンクを受け取る必要があります。例えば:
Objective-C
FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
if (dynamicLink) {
NSString *link = dynamicLink.url;
BOOL strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong;
// ...
return YES;
}
迅速
let dynamicLink = FIRDynamicLinks.dynamicLinks()?.dynamicLinkFromCustomSchemeURL(url)
if let dynamicLink = dynamicLink {
let link = dynamicLink.url
let strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong
// ...
return true
}
link
パラメーターの値を取得したので、リンクされたコンテンツを受信者に表示したり、パラメーターで指定されたデータを別の方法で処理したりできます。 JLRoutesなどの URL ルーティング ライブラリは、このタスクに役立ちます。
特定の受信者向けのリンクを受信している場合は、ユーザー固有のロジックを実行する前に、ダイナミック リンクの一致の信頼性がstrong
ことを確認してください。
アンドロイド
Android では、 getDynamicLink()
メソッドを使用してダイナミック リンクからデータを取得します。
Kotlin+KTX
Firebase.dynamicLinks .getDynamicLink(intent) .addOnCompleteListener { task -> if (!task.isSuccessful) { // Handle error // ... } val invite = FirebaseAppInvite.getInvitation(task.result) if (invite != null) { // Handle invite // ... } }
Java
FirebaseDynamicLinks.getInstance() .getDynamicLink(getIntent()) .addOnCompleteListener(new OnCompleteListener<PendingDynamicLinkData>() { @Override public void onComplete(@NonNull Task<PendingDynamicLinkData> task) { if (!task.isSuccessful()) { // Handle error // ... } FirebaseAppInvite invite = FirebaseAppInvite.getInvitation(task.getResult()); if (invite != null) { // Handle invite // ... } } });
link
パラメーターの値を取得したので、リンクされたコンテンツを受信者に表示したり、パラメーターで指定されたデータを別の方法で処理したりできます。 URL ルーティング ライブラリは、このタスクに役立ちます。