Récompenser les parrainages

L'un des moyens les plus efficaces d'obtenir de nouveaux utilisateurs consiste à parrainer des utilisateurs. Vous pouvez utiliser Dynamic Links avec Realtime Database et Cloud Functions for Firebase pour encourager vos utilisateurs à inviter leurs amis en offrant des récompenses dans l'application pour les parrainages réussis à la fois au référent et au destinataire.

Avantages clés

  • Accélérez la croissance en incitant vos utilisateurs à inviter leurs amis.
  • Les liens d'invitation fonctionnent sur toutes les plateformes.
  • Les nouveaux utilisateurs qui ouvrent votre application pour la première fois bénéficient d'une première expérience que vous personnalisez pour eux. Par exemple, vous pouvez les connecter automatiquement avec l'ami qui les a invités.
  • Retardez éventuellement l'attribution des récompenses jusqu'à ce que les nouveaux utilisateurs aient terminé une tâche d'introduction, telle que la réalisation d'un didacticiel.

Voici comment commencer !

Configurer Firebase et le SDK Dynamic Links

Configurez un nouveau projet Firebase et installez le SDK Dynamic Links dans votre application. ( iOS , Androïd , C++ , Unity ). L'installation du SDK Dynamic Links permet à Firebase de transmettre des données sur le lien dynamique à l'application, y compris après que l'utilisateur a installé l'application. Sans le SDK, il n'y a aucun moyen de connecter un utilisateur de post-installation avec un clic de pré-installation.

Pour créer une invitation, créez d'abord le lien que le destinataire ouvre pour accepter l'invitation. Plus tard, vous inclurez ce lien dans le texte de l'invitation. Lorsqu'un destinataire de l'invitation installe votre application en ouvrant le lien, il peut bénéficier d'une expérience de première exécution personnalisée, notamment en recevant une récompense dans l'application.

Ce lien d'invitation est un lien dynamique avec une valeur de paramètre de link qui indique qu'il provient de votre utilisateur existant.

Il existe de nombreuses façons de formater ces charges utiles de paramètres de link et de les lier à votre application. Un moyen simple consiste à spécifier l'ID de compte utilisateur de l'expéditeur dans un paramètre de requête, comme dans l'exemple suivant :

https://mygame.example.com/?invitedby=SENDER_UID

Ensuite, pour créer des liens dynamiques pouvant être inclus dans une invitation, vous pouvez utiliser l'API Dynamic Link Builder :

Rapide

Remarque : Ce produit Firebase n'est pas disponible sur les cibles macOS, Mac Catalyst, tvOS ou watchOS.
guard let uid = Auth.auth().currentUser?.uid else { return }
let link = URL(string: "https://mygame.example.com/?invitedby=\(uid)")
let referralLink = DynamicLinkComponents(link: link!, domain: "example.page.link")

referralLink.iOSParameters = DynamicLinkIOSParameters(bundleID: "com.example.ios")
referralLink.iOSParameters?.minimumAppVersion = "1.0.1"
referralLink.iOSParameters?.appStoreID = "123456789"

referralLink.androidParameters = DynamicLinkAndroidParameters(packageName: "com.example.android")
referralLink.androidParameters?.minimumVersion = 125

referralLink.shorten { (shortURL, warnings, error) in
  if let error = error {
    print(error.localizedDescription)
    return
  }
  self.invitationUrl = shortURL
}

Java

FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String uid = user.getUid();
String link = "https://mygame.example.com/?invitedby=" + uid;
FirebaseDynamicLinks.getInstance().createDynamicLink()
        .setLink(Uri.parse(link))
        .setDomainUriPrefix("https://example.page.link")
        .setAndroidParameters(
                new DynamicLink.AndroidParameters.Builder("com.example.android")
                        .setMinimumVersion(125)
                        .build())
        .setIosParameters(
                new DynamicLink.IosParameters.Builder("com.example.ios")
                        .setAppStoreId("123456789")
                        .setMinimumVersion("1.0.1")
                        .build())
        .buildShortDynamicLink()
        .addOnSuccessListener(new OnSuccessListener<ShortDynamicLink>() {
            @Override
            public void onSuccess(ShortDynamicLink shortDynamicLink) {
                mInvitationUrl = shortDynamicLink.getShortLink();
                // ...
            }
        });

Kotlin+KTX

val user = Firebase.auth.currentUser!!
val uid = user.uid
val invitationLink = "https://mygame.example.com/?invitedby=$uid"
Firebase.dynamicLinks.shortLinkAsync {
    link = Uri.parse(invitationLink)
    domainUriPrefix = "https://example.page.link"
    androidParameters("com.example.android") {
        minimumVersion = 125
    }
    iosParameters("com.example.ios") {
        appStoreId = "123456789"
        minimumVersion = "1.0.1"
    }
}.addOnSuccessListener { shortDynamicLink ->
    mInvitationUrl = shortDynamicLink.shortLink
    // ...
}

Envoyez les convocations

Maintenant que vous avez créé le lien, vous pouvez l'inclure dans une invitation. L'invitation peut être un e-mail, un SMS ou tout autre support, en fonction de ce qui est le plus approprié pour votre application et votre public.

Par exemple, pour envoyer une invitation par e-mail :

Rapide

Remarque : Ce produit Firebase n'est pas disponible sur les cibles macOS, Mac Catalyst, tvOS ou watchOS.
guard let referrerName = Auth.auth().currentUser?.displayName else { return }
let subject = "\(referrerName) wants you to play MyExampleGame!"
let invitationLink = invitationUrl?.absoluteString
let msg = "<p>Let's play MyExampleGame together! Use my <a href=\"\(invitationLink)\">referrer link</a>!</p>"

if !MFMailComposeViewController.canSendMail() {
  // Device can't send email
  return
}
let mailer = MFMailComposeViewController()
mailer.mailComposeDelegate = self
mailer.setSubject(subject)
mailer.setMessageBody(msg, isHTML: true)
myView.present(mailer, animated: true, completion: nil)

Java

String referrerName = FirebaseAuth.getInstance().getCurrentUser().getDisplayName();
String subject = String.format("%s wants you to play MyExampleGame!", referrerName);
String invitationLink = mInvitationUrl.toString();
String msg = "Let's play MyExampleGame together! Use my referrer link: "
        + invitationLink;
String msgHtml = String.format("<p>Let's play MyExampleGame together! Use my "
        + "<a href=\"%s\">referrer link</a>!</p>", invitationLink);

Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:")); // only email apps should handle this
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, msg);
intent.putExtra(Intent.EXTRA_HTML_TEXT, msgHtml);
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
}

Kotlin+KTX

val referrerName = Firebase.auth.currentUser?.displayName
val subject = String.format("%s wants you to play MyExampleGame!", referrerName)
val invitationLink = mInvitationUrl.toString()
val msg = "Let's play MyExampleGame together! Use my referrer link: $invitationLink"
val msgHtml = String.format("<p>Let's play MyExampleGame together! Use my " +
        "<a href=\"%s\">referrer link</a>!</p>", invitationLink)

val intent = Intent(Intent.ACTION_SENDTO).apply {
    data = Uri.parse("mailto:") // only email apps should handle this
    putExtra(Intent.EXTRA_SUBJECT, subject)
    putExtra(Intent.EXTRA_TEXT, msg)
    putExtra(Intent.EXTRA_HTML_TEXT, msgHtml)
}
intent.resolveActivity(packageManager)?.let {
    startActivity(intent)
}

Récupérer les informations de parrainage dans votre application

Lorsque le destinataire de l'invitation ouvre le lien de parrainage, il est dirigé vers l'App Store ou le Play Store pour installer votre application si elle n'est pas déjà installée. Ensuite, lorsqu'ils ouvrent votre application pour la première fois, vous pouvez récupérer les informations de parrainage que vous avez incluses dans le lien dynamique et les utiliser pour appliquer la récompense.

En règle générale, vous souhaitez accorder des récompenses de parrainage uniquement après l'inscription du destinataire de l'invitation, ou même uniquement après que le nouvel utilisateur a terminé une tâche. Jusqu'à ce que les critères de récompense soient remplis, vous devez garder une trace des informations de récompense que vous avez obtenues à partir du lien dynamique.

Une façon de garder une trace de ces informations consiste à connecter l'utilisateur de manière anonyme et à stocker les données dans l'enregistrement de la base de données en temps réel du compte anonyme. Lorsque le destinataire s'inscrit et que le compte anonyme est converti en compte permanent, le nouveau compte aura le même UID que le compte anonyme et, par conséquent, aura accès aux informations de récompense.

Par exemple, pour enregistrer l'UID du référent une fois que le destinataire a ouvert votre application :

Rapide

Remarque : Ce produit Firebase n'est pas disponible sur les cibles macOS, Mac Catalyst, tvOS ou watchOS.
struct MyApplication: App {

  var body: some Scene {
    WindowGroup {
      VStack {
        Text("Example text")
      }
      .onOpenURL { url in
        if DynamicLinks.dynamicLinks()?.shouldHandleDynamicLink(fromCustomSchemeURL: url) ?? false {
        let dynamicLink = DynamicLinks.dynamicLinks()?.dynamicLink(fromCustomSchemeURL: url)
        handleDynamicLink(dynamicLink)
      }
      // Handle incoming URL with other methods as necessary
      // ...
      }
    }
  }
}

func handleDynamicLink(_ dynamicLink: DynamicLink?) {
  guard let dynamicLink = dynamicLink else { return false }
  guard let deepLink = dynamicLink.url else { return false }
  let queryItems = URLComponents(url: deepLink, resolvingAgainstBaseURL: true)?.queryItems
  let invitedBy = queryItems?.filter({(item) in item.name == "invitedby"}).first?.value
  let user = Auth.auth().currentUser
  // If the user isn't signed in and the app was opened via an invitation
  // link, sign in the user anonymously and record the referrer UID in the
  // user's RTDB record.
  if user == nil && invitedBy != nil {
    Auth.auth().signInAnonymously() { (user, error) in
      if let user = user {
        let userRecord = Database.database().reference().child("users").child(user.uid)
        userRecord.child("referred_by").setValue(invitedBy)
        if dynamicLink.matchConfidence == .weak {
          // If the Dynamic Link has a weak match confidence, it is possible
          // that the current device isn't the same device on which the invitation
          // link was originally opened. The way you handle this situation
          // depends on your app, but in general, you should avoid exposing
          // personal information, such as the referrer's email address, to
          // the user.
        }
      }
    }
  }
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // ...

    FirebaseDynamicLinks.getInstance()
            .getDynamicLink(getIntent())
            .addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
                @Override
                public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
                    // Get deep link from result (may be null if no link is found)
                    Uri deepLink = null;
                    if (pendingDynamicLinkData != null) {
                        deepLink = pendingDynamicLinkData.getLink();
                    }
                    //
                    // If the user isn't signed in and the pending Dynamic Link is
                    // an invitation, sign in the user anonymously, and record the
                    // referrer's UID.
                    //
                    FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
                    if (user == null
                            && deepLink != null
                            && deepLink.getBooleanQueryParameter("invitedby", false)) {
                        String referrerUid = deepLink.getQueryParameter("invitedby");
                        createAnonymousAccountWithReferrerInfo(referrerUid);
                    }
                }
            });
}

private void createAnonymousAccountWithReferrerInfo(final String referrerUid) {
    FirebaseAuth.getInstance()
            .signInAnonymously()
            .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
                @Override
                public void onSuccess(AuthResult authResult) {
                    // Keep track of the referrer in the RTDB. Database calls
                    // will depend on the structure of your app's RTDB.
                    FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
                    DatabaseReference userRecord =
                            FirebaseDatabase.getInstance().getReference()
                                    .child("users")
                                    .child(user.getUid());
                    userRecord.child("referred_by").setValue(referrerUid);
                }
            });
}

Kotlin+KTX

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // ...

    Firebase.dynamicLinks
            .getDynamicLink(intent)
            .addOnSuccessListener(this) { pendingDynamicLinkData ->
                // Get deep link from result (may be null if no link is found)
                var deepLink: Uri? = null
                if (pendingDynamicLinkData != null) {
                    deepLink = pendingDynamicLinkData.link
                }
                //
                // If the user isn't signed in and the pending Dynamic Link is
                // an invitation, sign in the user anonymously, and record the
                // referrer's UID.
                //
                val user = Firebase.auth.currentUser
                if (user == null &&
                        deepLink != null &&
                        deepLink.getBooleanQueryParameter("invitedby", false)) {
                    val referrerUid = deepLink.getQueryParameter("invitedby")
                    createAnonymousAccountWithReferrerInfo(referrerUid)
                }
            }
}

private fun createAnonymousAccountWithReferrerInfo(referrerUid: String?) {
    Firebase.auth
            .signInAnonymously()
            .addOnSuccessListener {
                // Keep track of the referrer in the RTDB. Database calls
                // will depend on the structure of your app's RTDB.
                val user = Firebase.auth.currentUser
                val userRecord = Firebase.database.reference
                        .child("users")
                        .child(user!!.uid)
                userRecord.child("referred_by").setValue(referrerUid)
            }
}

Ensuite, lorsque le destinataire de l'invitation décide de créer un compte, vous pouvez transférer les informations de parrainage du compte anonyme vers le nouveau compte du destinataire de l'invitation.

Commencez par obtenir un objet AuthCredential à l'aide de la méthode de connexion que l'invité souhaite utiliser. Par exemple, pour vous connecter avec une adresse e-mail et un mot de passe :

Rapide

Remarque : Ce produit Firebase n'est pas disponible sur les cibles macOS, Mac Catalyst, tvOS ou watchOS.
let credential = EmailAuthProvider.credential(withEmail: email, password: password)

Java

AuthCredential credential = EmailAuthProvider.getCredential(email, password);

Kotlin+KTX

val credential = EmailAuthProvider.getCredential(email, password)

Ensuite, liez cet identifiant au compte anonyme :

Rapide

Remarque : Ce produit Firebase n'est pas disponible sur les cibles macOS, Mac Catalyst, tvOS ou watchOS.
if let user = Auth.auth().currentUser {
  user.link(with: credential) { (user, error) in
    // Complete any post sign-up tasks here.
  }
}

Java

FirebaseAuth.getInstance().getCurrentUser()
        .linkWithCredential(credential)
        .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
            @Override
            public void onSuccess(AuthResult authResult) {
                // Complete any post sign-up tasks here.
            }
        });

Kotlin+KTX

Firebase.auth.currentUser!!
        .linkWithCredential(credential)
        .addOnSuccessListener {
            // Complete any post sign-up tasks here.
        }

Le nouveau compte permanent a accès à toutes les données de récompense que vous avez ajoutées au compte anonyme.

Accorder des récompenses au parrain et au destinataire

Maintenant que vous avez récupéré et enregistré les données d'invitation à partir du lien dynamique, vous pouvez accorder les récompenses de parrainage au parrain et au destinataire chaque fois que les critères que vous souhaitez exiger sont remplis.

Bien que vous puissiez écrire dans la base de données en temps réel à partir de votre application cliente, vous souhaiterez souvent autoriser uniquement l'accès en lecture aux données telles que la monnaie intégrée à l'application à partir de vos applications et effectuer des opérations d'écriture uniquement à partir de votre backend. Ce backend peut être n'importe quel système capable d'exécuter le SDK Firebase Admin, mais il est souvent plus facile d'utiliser Cloud Functions pour effectuer ces tâches.

Par exemple, supposons que vous ayez un jeu et que vous souhaitiez accorder une récompense en monnaie du jeu au destinataire après son inscription, et au parrain une fois que le destinataire a atteint le niveau 5.

Pour accorder la récompense pour l'inscription, déployez une fonction qui surveille la création d'une clé de base de données en temps réel spécifique et accorde la récompense lorsqu'elle l'est. Par example:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.grantSignupReward = functions.database.ref('/users/{uid}/last_signin_at')
    .onCreate(event => {
      var uid = event.params.uid;
      admin.database().ref(`users/${uid}/referred_by`)
        .once('value').then(function(data) {
          var referred_by_somebody = data.val();
          if (referred_by_somebody) {
            var moneyRef = admin.database()
                .ref(`/users/${uid}/inventory/pieces_of_eight`);
            moneyRef.transaction(function (current_value) {
              return (current_value || 0) + 50;
            });
          }
        });
    });

Ensuite, lorsqu'un nouvel utilisateur s'inscrit, déclenchez cette fonction en créant la clé Realtime Database. Par exemple, déclenchez la fonction dans l'écouteur de réussite de linkWithCredential , que vous avez créé à l'étape précédente :

Rapide

Remarque : Ce produit Firebase n'est pas disponible sur les cibles macOS, Mac Catalyst, tvOS ou watchOS.
if let user = Auth.auth().currentUser {
  user.link(with: credential) { (user, error) in
    // Complete any post sign-up tasks here.

    // Trigger the sign-up reward function by creating the "last_signin_at" field.
    // (If this is a value you want to track, you would also update this field in
    // the success listeners of your Firebase Authentication signIn calls.)
    if let user = user {
      let userRecord = Database.database().reference().child("users").child(user.uid)
      userRecord.child("last_signin_at").setValue(ServerValue.timestamp())
    }
  }
}

Java

FirebaseAuth.getInstance().getCurrentUser()
        .linkWithCredential(credential)
        .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
            @Override
            public void onSuccess(AuthResult authResult) {
                // Complete any post sign-up tasks here.

                // Trigger the sign-up reward function by creating the
                // "last_signin_at" field. (If this is a value you want to track,
                // you would also update this field in the success listeners of
                // your Firebase Authentication signIn calls.)
                FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
                DatabaseReference userRecord =
                        FirebaseDatabase.getInstance().getReference()
                                .child("users")
                                .child(user.getUid());
                userRecord.child("last_signin_at").setValue(ServerValue.TIMESTAMP);
            }
        });

Kotlin+KTX

Firebase.auth.currentUser!!
        .linkWithCredential(credential)
        .addOnSuccessListener {
            // Complete any post sign-up tasks here.

            // Trigger the sign-up reward function by creating the
            // "last_signin_at" field. (If this is a value you want to track,
            // you would also update this field in the success listeners of
            // your Firebase Authentication signIn calls.)
            val user = Firebase.auth.currentUser!!
            val userRecord = Firebase.database.reference
                    .child("users")
                    .child(user.uid)
            userRecord.child("last_signin_at").setValue(ServerValue.TIMESTAMP)
        }

Pour accorder une récompense au référent lorsque le destinataire atteint le niveau 5, déployez une fonction qui surveille les modifications apportées au champ de level dans vos enregistrements utilisateur. Si un utilisateur est passé du niveau 4 au niveau 5 et que l'utilisateur a un référent enregistré, accordez la récompense :

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.rewardReferrals = functions.database.ref('/users/{uid}/level')
    .onUpdate(event => {
      var level = event.data.val();
      var prev_level = event.data.previous.val();
      if (prev_level == 4 && level == 5) {
        var referrerRef = event.data.ref.parent.child('referred_by');
        return referrerRef.once('value').then(function(data) {
          var referrerUid = data.val();
          if (referrerUid) {
            var moneyRef = admin.database()
                .ref(`/users/${referrerUid}/inventory/pieces_of_eight`);
            return moneyRef.transaction(function (current_value) {
              return (current_value || 0) + 50;
            });
          }
        });
      }
    });

Le parrain et votre nouvel utilisateur ont maintenant reçu leurs récompenses.