欢迎参加我们将于 2022 年 10 月 18 日举办的 Firebase 峰会(线上线下同时进行),了解 Firebase 如何帮助您加快应用开发速度、满怀信心地发布应用并在之后需要时轻松地扩大应用规模。立即报名

Segnalazioni di ricompensa

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 propri amici offrendo premi in-app per referral riusciti sia al referrer che al destinatario.

Vantaggi chiave

  • Accelera la crescita fornendo un incentivo ai tuoi utenti per invitare i loro 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 che puoi personalizzare 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 Dynamic Links SDK

Configura un nuovo progetto Firebase e installa Dynamic Links SDK nella tua app. ( iOS , Android , C++ , Unity ). L'installazione di Dynamic Links SDK consente a Firebase di trasmettere i dati su Dynamic Link all'app, anche dopo che l'utente ha installato l'app. Senza l'SDK, non è possibile connettere un utente post-installazione con un clic di pre-installazione.

Per creare un invito, crea prima il collegamento che il destinatario apre per accettare l'invito. Successivamente, includerai questo link nel testo dell'invito. Quando un destinatario dell'invito installa la tua app aprendo il link, 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 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:

Veloce

Nota: questo prodotto Firebase non è disponibile su target macOS, Mac Catalyst, tvOS o 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
    // ...
}

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 e-mail:

Veloce

Nota: questo prodotto Firebase non è disponibile su target macOS, Mac Catalyst, tvOS o 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)
}

Recupera le informazioni di riferimento 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 in Dynamic Link e utilizzarle per applicare il premio.

Di solito, vuoi concedere premi referral solo dopo che il destinatario dell'invito si è registrato, o anche solo dopo che il nuovo utente ha completato alcune attività. Fino a quando i criteri di ricompensa non vengono soddisfatti, devi tenere traccia delle informazioni sulla ricompensa che hai ricevuto da Dynamic Link.

Un modo per tenere traccia di queste informazioni è accedere all'utente in modo anonimo e archiviare i dati nel record del database in tempo reale dell'account anonimo. Quando il destinatario si registra 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 l'app:

Veloce

Nota: questo prodotto Firebase non è disponibile su target macOS, Mac Catalyst, tvOS o 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)
            }
}

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 usando il metodo di accesso che l'invitato desidera utilizzare. Ad esempio, per accedere con un indirizzo e-mail e una password:

Veloce

Nota: questo prodotto Firebase non è disponibile su target macOS, Mac Catalyst, tvOS o watchOS.
let credential = EmailAuthProvider.credential(withEmail: email, password: password)

Java

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

Kotlin+KTX

val credential = EmailAuthProvider.getCredential(email, password)

Quindi, collega questa credenziale all'account anonimo:

Veloce

Nota: questo prodotto Firebase non è disponibile su target macOS, Mac Catalyst, tvOS o 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.
        }

Il nuovo account permanente ha accesso a tutti i dati sulla ricompensa che hai aggiunto all'account anonimo.

Concedi premi al referrer e al destinatario

Ora che hai recuperato e salvato i dati dell'invito da Dynamic Link, puoi concedere i premi di riferimento al referrer e al destinatario ogni volta che i criteri che desideri 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 Firebase Admin SDK, ma spesso è più semplice utilizzare Cloud Functions per eseguire queste attività.

Ad esempio, supponiamo che tu abbia un gioco e desideri 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, distribuire una funzione che controlla la creazione di una chiave di database in tempo reale specifica 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:

Veloce

Nota: questo prodotto Firebase non è disponibile su target macOS, Mac Catalyst, tvOS o 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)
        }

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 record utente. Se un utente è passato dal livello 4 al livello 5 e l'utente ha registrato un referrer, concedi 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.