Inviter des utilisateurs sur votre application

L'un des moyens les plus efficaces d'inciter de nouveaux utilisateurs à installer votre application consiste à permettre à vos utilisateurs de partager le contenu de votre application avec leurs amis. Avec les liens dynamiques, vous pouvez créer une excellente expérience de partage d'utilisateur à utilisateur : les utilisateurs qui reçoivent des recommandations de contenu de leurs amis peuvent cliquer sur un lien et être redirigés directement vers le contenu partagé dans votre application, même s'ils doivent accéder à l'application Store ou Google Play Store pour installer votre application en premier.

En combinant la rigidité des références d'utilisateurs et la persistance des liens dynamiques, vous pouvez créer des fonctionnalités de partage et de référence d'utilisateur à utilisateur qui attirent de nouveaux utilisateurs en les attirant directement vers le contenu de votre application ou en proposant des promotions qui profitent mutuellement au référent et au référé. .

Avantages clés

  • Les nouveaux utilisateurs qui ouvrent votre application pour la première fois bénéficient d'une expérience de première exécution personnalisée, contextualisée en fonction de ce que leur ami voulait partager avec eux. Par exemple, vous pouvez afficher le contenu qui a été partagé avec eux ou les connecter automatiquement à l'ami qui les a invités.
  • Permet aux utilisateurs de partager facilement du contenu avec leurs amis sur toutes les plateformes, que leurs amis aient ou non installé votre application.

Voici comment commencer !

Mettre en place un nouveau projet Firebase et installer le SDK des liens dynamiques dans votre application.

L'installation du SDK Dynamic Links permet à Firebase de transmettre des données sur Dynamic Link à l'application, y compris après l'installation de l'application par l'utilisateur.

Il est maintenant temps de configurer les liens que les utilisateurs peuvent envoyer à leurs amis. Ne vous inquiétez pas si les amis de vos utilisateurs n'ont pas encore installé l'application ; Dynamic Links peut s'en charger pour vous.

Pour chaque élément de contenu que vous voulez être partageable, créer un lien dynamique .

Lorsque vous créez le Dynamic Link, vous devez fournir une URL HTTP ou HTTPS comme le link paramètre qui sera utilisé pour identifier le contenu que vous partagez. Si vous avez un site Web avec un contenu équivalent, vous devez utiliser les URL de votre site Web. Cela garantira que ces liens s'affichent correctement sur une plate-forme qui ne prend pas en charge les liens dynamiques, comme un navigateur de bureau. Par exemple:

https://example.page.link/?link=https://www.example.com/content?item%3D1234&apn=com.example.android&ibi=com.example.ios&isi=12345

Vous pouvez également ajouter des informations supplémentaires à la charge utile des données en ajoutant des paramètres codés en URL, par exemple, pour indiquer que le lien est destiné à un utilisateur particulier, comme dans une invitation à un jeu.

https://example.page.link/?link=https://www.example.com/invitation?gameid%3D1234%26referrer%3D555&apn=com.example.android&ibi=com.example.ios&isi=12345

Avant de partager ces liens, vous pouvez utiliser le lien dynamique Firebase URL API raccourcisseur pour générer des URL plus conviviale prospectifs. Un bref regard Dynamic Link comme l'exemple suivant:

https://example.page.link/WXYZ

Quel que soit le lien que vous utilisez, lorsque les utilisateurs ouvrent le Dynamic Link sur leur appareil, l'application spécifiée par le apn paramètre (sur Android) ou les ibi et isi paramètres (sur iOS) prendra les utilisateurs du Play Store ou App Store pour installer l'application s'il n'est pas déjà installé. Ensuite, lorsque l'application est installée et ouverte, l'URL spécifiée dans le paramètre 'link' est transmise à l'application.

Tout d'abord, jetez un œil à cet exemple simple d'une application de chat basée sur des salons comme Hangouts qui génère des liens pour inviter des personnes à des salons de chat.

iOS

chat app screenshotchat app screenshot with share sheet

Android

chat app screenshotchat app screenshot with share sheet

Rapide

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
}

Objectif 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;
}

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();
}

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
}

Une fois que vous avez un lien dynamique, vous pouvez ajouter un bouton de partage à votre interface utilisateur qui lancera le flux de partage de plate-forme standard :

Rapide

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)
}

Objectif 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];
}

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"));
}

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"))
}

Dans cet exemple, l'interface utilisateur de partage par défaut présente automatiquement une liste d'applications pour partager le lien, c'est donc quelque chose que vous pouvez configurer dans votre propre application avec seulement quelques lignes de code.

Plutôt que de laisser l'utilisateur sélectionner des contacts et rédiger le message dans votre application, ces actions sont déléguées à l'application qu'il choisit dans la boîte de dialogue de partage. De plus, la délégation du partage à d'autres applications signifie que vous n'avez pas à demander à l'utilisateur les autorisations de contacts et permet aux utilisateurs de choisir parmi une liste de contacts étendue au sein de leur application choisie. Afin de faciliter un meilleur partage social, vous pouvez ajouter des métadonnées aperçu des médias sociaux à votre lien dynamique qui sera affiché en même temps que le lien dans les canaux sociaux majeurs.

Parfois, cependant, il ne suffit pas d'envoyer un simple lien sans texte pour une référence convaincante. En accompagnant le lien d'un message court et, si possible, d'une présentation plus riche, les utilisateurs peuvent comprendre la proposition de valeur du filleul lorsqu'il le reçoit :

iOS

rewarded referral screenshotrewarded referral screenshot with share sheet

Android

rewarded referral screenshotrewarded referral screenshot with share sheet

Bien que cela soit plus complexe que le dernier exemple, l'approche sera plus ou moins la même. Sur cet écran, il y a un grand graphique avec la proposition de valeur de l'invitation et des boutons pour le partage sur les principaux canaux sociaux. Il y a une certaine redondance dans ce flux d'interface utilisateur : certains canaux de partage sont présentés individuellement pour permettre une personnalisation des messages plus spécifique aux canaux, comme l'ajout d'une ligne d'objet aux invitations par e-mail. Dans ce menu d'invitation, nous :

  • Présentez des boutons de partage d'e-mail, de SMS et de lien de copie, et personnalisez leurs messages de manière appropriée. L'e-mail inclura un sujet et peut inclure un corps plus long avec des sauts de ligne, des images et des espaces ; le texte doit inclure un corps plus court avec des sauts de ligne, mais peu d'espaces et aucune image ; et la copie de lien devrait simplement copier le lien et rien d'autre.
  • Utilisez l'interface utilisateur de partage du système pour tout le reste, y compris un court message d'invitation pour accompagner le lien.
  • Lien profond via un schéma d'URL ou un lien universel vers une autre application qui a une logique spéciale pour gérer les invitations de votre application. Cela ne fonctionnera pas en dehors d'un partenariat entre votre organisation et l'autre application, et n'est probablement pas une option pour les petites organisations. Cela dit, certaines applications peuvent documenter publiquement leur comportement de lien universel/profond. Nous allons implémenter une version factice de ceci dans notre exemple.

Tout d'abord, définissez un type de contenu d'invitation, qui encapsule uniquement les informations dans une invitation et ne contient aucune fonctionnalité. De cette façon, vous pouvez commencer par les types de données et réfléchir à votre code en fonction de la manière dont il assemble ces données.

Rapide

/// 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

}

Objectif 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

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) {
        // ...
    }

}

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
)

La seule donnée requise ici est l'URL, sans laquelle vous ne pouvez pas inviter d'utilisateurs dans votre application. Les autres éléments de données sont clairement structurés pour l'envoi d'e-mails, ce qui les rend un peu gênants dans certains autres cas : lors de l'envoi d'une invitation par texte, le texte de présentation accompagnant le lien peut se lire de la même manière qu'un objet d'e-mail, mais lors du partage sur les réseaux sociaux le texte accompagnant le lien pourrait ressembler davantage au corps d'un e-mail. Vous devrez expérimenter vous - même pour trouver le meilleur équilibre pour votre application, et si vous ne savez pas, vous pouvez toujours utiliser un service comme Config à distance pour vous permettre de modifier les valeurs de texte après le lancement de l' application.

Rapide

/// 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()

}

Objectif 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

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) {
        // ...
    }

}

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) {
        // ...
    }
}

Il ne reste plus qu'à le brancher sur un composant d'interface utilisateur de votre choix. Pour la mise en œuvre de ce flux inviter, voir les échantillons sur GitHub pour iOS et Android .

Ce sont toutes des méthodes pour permettre à vos utilisateurs d'envoyer des invitations à leurs amis, ce qui est la solution d'invitation la plus légère. De nombreuses applications populaires envoient également des invitations en envoyant des e-mails via leur propre backend, ce qui nécessite l'intégration d'un service d'envoi d'e-mails, mais offre un certain nombre d'avantages qui ne sont pas disponibles autrement avec seulement quelques inconvénients mineurs.

Avantages:

  • Active les e-mails avec un balisage complexe qui ne peut pas être modifié par votre utilisateur avant l'envoi.
  • Permet un suivi/des analyses plus granulaires (c'est-à-dire envoyer les réussites et les échecs sur votre backend).

Les inconvénients:

  • Les e-mails sont plus susceptibles d'être signalés comme spam
  • Nécessite une intégration avec un service de livraison de courrier électronique
  • Nécessite des autorisations de contacts dans l'application

En règle générale, l'envoi d'invitations via votre propre service de livraison de courrier électronique offre une expérience d'invitation plus cohérente et potentiellement plus riche au détriment de la polyvalence.

Ouvrez le contenu lié dans votre application

Enfin, vous devez recevoir le lien transmis à votre application afin de pouvoir afficher le contenu lié au destinataire. C'est facile à l'aide du SDK Dynamic Links :

iOS

Sur iOS, vous recevez le Dynamic Link en mettant en œuvre l' application:continueUserActivity:restorationHandler: méthode. Dans le gestionnaire de restauration, vous pouvez obtenir le Dynamic Link en appelant handleUniversalLink:completion: . Si un Dynamic Link a été transmis à votre application, vous pouvez l' obtenir à partir de l' url propriété du FIRDynamicLink . Par exemple:

Objectif c

[[FIRDynamicLinks dynamicLinks]
    handleUniversalLink:userActivity.webpageURL
             completion:^(FIRDynamicLink * _Nullable dynamicLink,
                          NSError * _Nullable error) {
      NSString *link = dynamicLink.url;
      BOOL strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong;
      // ...
    }];

Rapide

FIRDynamicLinks.dynamicLinks()?.handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
    let link = dynamicLink.url
    let strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong
    // ...
}

De plus, vous devez appeler dynamicLinkFromCustomSchemeURL: dans l' application:openURL:options: méthode pour recevoir dynamique Liens passés à votre application comme URL de régime personnalisé. Par exemple:

Objectif c

FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
if (dynamicLink) {
  NSString *link = dynamicLink.url;
  BOOL strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong;
  // ...
  return YES;
}

Rapide

let dynamicLink = FIRDynamicLinks.dynamicLinks()?.dynamicLinkFromCustomSchemeURL(url)
if let dynamicLink = dynamicLink {
  let link = dynamicLink.url
  let strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong
  // ...
  return true
}

Maintenant que vous avez la valeur du link paramètre, vous pouvez afficher le contenu lié au destinataire, ou traiter les données spécifiées par le paramètre d'une autre manière. Bibliothèque de routage URL Une telle que JLRoutes peut aider dans cette tâche.

Si vous recevez un lien destiné à un destinataire spécifique, assurez -vous que la confiance du match Dynamic Link est strong avant d' exécuter une logique spécifique à l' utilisateur.

Android

Sur Android, vous utilisez le getDynamicLink() méthode pour obtenir des données à partir du Dynamic Link:

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
                    // ...
                }
            }
        });

Kotlin+KTX

Firebase.dynamicLinks
        .getDynamicLink(intent)
        .addOnCompleteListener { task ->
            if (!task.isSuccessful) {
                // Handle error
                // ...
            }

            val invite = FirebaseAppInvite.getInvitation(task.result)
            if (invite != null) {
                // Handle invite
                // ...
            }
        }

Maintenant que vous avez la valeur du link paramètre, vous pouvez afficher le contenu lié au destinataire, ou traiter les données spécifiées par le paramètre d'une autre manière. Une bibliothèque de routage d'URL peut vous aider dans cette tâche.