Uno dei modi più efficaci per ottenere nuovi utenti è attraverso i referral degli utenti. Puoi utilizzare i collegamenti dinamici insieme al database in tempo reale e alle funzioni cloud per Firebase per incoraggiare i tuoi utenti a invitare i loro amici offrendo premi in-app per i referral riusciti sia al referrer che al destinatario.
Vantaggi chiave
- Accelera la crescita fornendo un incentivo ai tuoi utenti affinché invitino i propri amici.
- I link di invito funzionano su tutte le piattaforme.
- I nuovi utenti che aprono la tua app per la prima volta ottengono un'esperienza di prima esecuzione personalizzabile per loro. Ad esempio, puoi connetterli automaticamente con l'amico che li ha invitati.
- Facoltativamente, ritarda la concessione dei premi fino a quando i nuovi utenti non completano alcune attività introduttive, come il completamento di un tutorial.
Ecco come iniziare!
Configura Firebase e l'SDK di Dynamic Links
Configura un nuovo progetto Firebase e installa l'SDK di Dynamic Links nella tua app. ( iOS , Android , C++ , Unity ). L'installazione dell'SDK di Dynamic Links consente a Firebase di trasmettere i dati relativi a Dynamic Link all'app, anche dopo che l'utente ha installato l'app. Senza l'SDK, non c'è modo di connettere un utente post-installazione con un clic pre-installazione.
Crea link di invito
Per creare un invito, creare innanzitutto il collegamento che il destinatario apre per accettare l'invito. Successivamente, includerai questo collegamento nel testo dell'invito. Quando un destinatario dell'invito installa la tua app aprendo il collegamento, può ottenere un'esperienza di prima esecuzione personalizzata, inclusa la ricezione di un premio in-app.
Questo collegamento di invito è un collegamento dinamico con un valore di parametro di link
che indica che proviene dall'utente esistente.
Esistono molti modi per formattare questi payload dei parametri di link
e collegarli alla tua app. Un modo semplice consiste nello specificare l'ID dell'account utente del mittente in un parametro di query come nell'esempio seguente:
https://mygame.example.com/?invitedby=SENDER_UID
Quindi, per creare collegamenti dinamici adatti all'inclusione in un invito, puoi utilizzare l'API Dynamic Link Builder:
Rapido
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
}
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 // ... }
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(); // ... } });
Invia gli inviti
Ora che hai creato il link, puoi includerlo in un invito. L'invito può essere un'e-mail, un messaggio SMS o qualsiasi altro mezzo, a seconda di ciò che è più appropriato per la tua app e il tuo pubblico.
Ad esempio, per inviare un invito via e-mail:
Rapido
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)
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) }
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); }
Recupera le informazioni sui referral nella tua app
Quando il destinatario dell'invito apre il link di riferimento, verrà indirizzato all'App Store o al Play Store per installare la tua app se non è già installata. Quindi, quando aprono la tua app per la prima volta, puoi recuperare le informazioni di riferimento che hai incluso nel collegamento dinamico e utilizzarle per applicare il premio.
Di solito, si desidera concedere premi di riferimento solo dopo che il destinatario dell'invito si è registrato o anche solo dopo che il nuovo utente ha completato alcune attività. Fino a quando non vengono soddisfatti i criteri di ricompensa, è necessario tenere traccia delle informazioni sulla ricompensa ottenute dal collegamento dinamico.
Un modo per tenere traccia di queste informazioni è l'accesso dell'utente in modo anonimo e l'archiviazione dei dati nel record del database in tempo reale dell'account anonimo. Quando il destinatario si iscrive e l'account anonimo viene convertito in un account permanente, il nuovo account avrà lo stesso UID dell'account anonimo e, di conseguenza, avrà accesso alle informazioni sulla ricompensa.
Ad esempio, per salvare l'UID del referrer dopo che il destinatario ha aperto la tua app:
Rapido
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.
}
}
}
}
}
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) } }
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); } }); }
Quindi, quando il destinatario dell'invito decide di creare un account, puoi trasferire le informazioni di riferimento dall'account anonimo al nuovo account del destinatario dell'invito.
Innanzitutto, ottieni un oggetto AuthCredential
utilizzando il metodo di accesso che l'invitato desidera utilizzare. Ad esempio, per accedere con un indirizzo e-mail e una password:
Rapido
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
Kotlin+KTX
val credential = EmailAuthProvider.getCredential(email, password)
Java
AuthCredential credential = EmailAuthProvider.getCredential(email, password);
Quindi, collega questa credenziale all'account anonimo:
Rapido
if let user = Auth.auth().currentUser {
user.link(with: credential) { (user, error) in
// Complete any post sign-up tasks here.
}
}
Kotlin+KTX
Firebase.auth.currentUser!! .linkWithCredential(credential) .addOnSuccessListener { // 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. } });
Il nuovo account permanente ha accesso a tutti i dati del premio che hai aggiunto all'account anonimo.
Assegna premi al referrer e al destinatario
Ora che hai recuperato e salvato i dati dell'invito dal Dynamic Link, puoi concedere i premi per il referral al referrer e al destinatario ogni volta che i criteri che vuoi richiedere sono stati soddisfatti.
Sebbene tu possa scrivere nel database in tempo reale dalla tua app client, spesso vorrai consentire solo l'accesso in lettura a dati come la valuta in-app dalle tue app ed eseguire operazioni di scrittura solo dal tuo back-end. Questo back-end potrebbe essere qualsiasi sistema in grado di eseguire l'SDK Firebase Admin, ma spesso è più semplice utilizzare Cloud Functions per eseguire queste attività.
Ad esempio, supponi di avere un gioco e di voler concedere una ricompensa in valuta di gioco al destinatario dopo che il destinatario si è registrato e al referrer dopo che il destinatario ha raggiunto il livello 5.
Per concedere il premio per la registrazione, implementa una funzione che controlla la creazione di una specifica chiave di Realtime Database e concede il premio quando lo è. Per esempio:
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;
});
}
});
});
Quindi, quando un nuovo utente si registra, attiva questa funzione creando la chiave del database in tempo reale. Ad esempio, attiva la funzione nel listener di successo di linkWithCredential
, che hai creato nel passaggio precedente:
Rapido
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())
}
}
}
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) }
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); } });
Per concedere una ricompensa al referrer quando il destinatario raggiunge il livello 5, implementa una funzione che controlla le modifiche al campo del level
nei tuoi record utente. Se un utente è passato dal livello 4 al livello 5 e l'utente ha registrato un referrer, assegna il premio:
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;
});
}
});
}
});
Sia il referrer che il tuo nuovo utente hanno ora ricevuto i loro premi.