Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Obtenga nuevos usuarios recompensando las referencias de los usuarios

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Una de las formas más efectivas de obtener nuevos usuarios es a través de referencias de usuarios. Puede usar Dynamic Links junto con Realtime Database y Cloud Functions para Firebase para alentar a sus usuarios a invitar a sus amigos al ofrecer recompensas en la aplicación por referencias exitosas tanto para el remitente como para el destinatario.

Beneficios clave

  • Acelere el crecimiento proporcionando un incentivo para que sus usuarios inviten a sus amigos.
  • Los enlaces de invitación funcionan en todas las plataformas.
  • Los nuevos usuarios que abren su aplicación por primera vez obtienen una experiencia de primera ejecución que usted personaliza para ellos. Por ejemplo, puede conectarlos automáticamente con el amigo que los invitó.
  • Opcionalmente, retrase la concesión de recompensas hasta que los nuevos usuarios completen alguna tarea introductoria, como completar un tutorial.

¡Aquí le mostramos cómo empezar!

Configurar Firebase y el SDK de Dynamic Links

Configure un nuevo proyecto de Firebase e instale el SDK de Dynamic Links en su aplicación. ( iOS , Android , C++ , Unidad ). La instalación del SDK de Dynamic Links permite que Firebase transmita datos sobre Dynamic Link a la aplicación, incluso después de que el usuario instala la aplicación. Sin el SDK, no hay forma de conectar a un usuario posterior a la instalación con un clic previo a la instalación.

Para crear una invitación, primero cree el enlace que el destinatario abre para aceptar la invitación. Posteriormente, incluirás este enlace en el texto de la invitación. Cuando un destinatario de la invitación instala su aplicación abriendo el enlace, puede obtener una experiencia de primera ejecución personalizada, incluida la recepción de una recompensa en la aplicación.

Este enlace de invitación es un enlace dinámico con un valor de parámetro de link que indica que es de su usuario existente.

Hay muchas maneras de formatear estas cargas útiles de parámetros de link y vincularlas a su aplicación. Una forma sencilla es especificar el ID de la cuenta de usuario del remitente en un parámetro de consulta como en el siguiente ejemplo:

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

Luego, para crear Dynamic Links adecuados para su inclusión en una invitación, puede usar la API Dynamic Link Builder:

Rápido

Nota: Este producto de Firebase no está disponible en objetivos 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
    // ...
}

Envía las invitaciones

Ahora que ha creado el enlace, puede incluirlo en una invitación. La invitación puede ser un correo electrónico, un mensaje SMS o cualquier otro medio, según lo que sea más apropiado para su aplicación y audiencia.

Por ejemplo, para enviar una invitación por correo electrónico:

Rápido

Nota: Este producto de Firebase no está disponible en objetivos 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)
}

Recuperar información de referencia en su aplicación

Cuando el destinatario de la invitación abra el enlace de referencia, será dirigido a App Store o Play Store para instalar su aplicación si aún no está instalada. Luego, cuando abran su aplicación por primera vez, puede recuperar la información de referencia que incluyó en Dynamic Link y usarla para aplicar la recompensa.

Por lo general, desea otorgar recompensas de referencia solo después de que el destinatario de la invitación se registre, o incluso solo después de que el nuevo usuario complete alguna tarea. Hasta que se cumplan los criterios de recompensa, debe realizar un seguimiento de la información de recompensa que obtuvo de Dynamic Link.

Una forma de realizar un seguimiento de esta información es iniciar la sesión del usuario de forma anónima y almacenar los datos en el registro de la base de datos en tiempo real de la cuenta anónima. Cuando el destinatario se registre y la cuenta anónima se convierta en una cuenta permanente, la nueva cuenta tendrá el mismo UID que la cuenta anónima y, como resultado, tendrá acceso a la información de la recompensa.

Por ejemplo, para guardar el UID del remitente después de que el destinatario abra su aplicación:

Rápido

Nota: Este producto de Firebase no está disponible en objetivos 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)
            }
}

Luego, cuando el destinatario de la invitación decida crear una cuenta, puede transferir la información de referencia de la cuenta anónima a la nueva cuenta del destinatario de la invitación.

Primero, obtenga un objeto AuthCredential usando el método de inicio de sesión que el invitado quiere usar. Por ejemplo, para iniciar sesión con una dirección de correo electrónico y una contraseña:

Rápido

Nota: Este producto de Firebase no está disponible en objetivos 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)

Luego, vincule esta credencial a la cuenta anónima:

Rápido

Nota: Este producto de Firebase no está disponible en objetivos 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.
        }

La nueva cuenta permanente tiene acceso a todos los datos de recompensa que agregó a la cuenta anónima.

Otorgar recompensas al referente y al destinatario

Ahora que recuperó y guardó los datos de la invitación de Dynamic Link, puede otorgar las recompensas de referencia al remitente y al destinatario siempre que se cumplan los criterios que desea exigir.

Aunque puede escribir en la base de datos en tiempo real desde su aplicación cliente, a menudo querrá permitir solo el acceso de lectura a datos como la moneda en la aplicación desde sus aplicaciones y realizar operaciones de escritura solo desde su backend. Este backend podría ser cualquier sistema capaz de ejecutar el SDK de administrador de Firebase, pero a menudo es más fácil usar Cloud Functions para realizar estas tareas.

Por ejemplo, suponga que tiene un juego y desea otorgar una recompensa de moneda del juego al destinatario después de que el destinatario se registre, y al referente después de que el destinatario alcance el nivel 5.

Para otorgar la recompensa por registrarse, implemente una función que vigile la creación de una clave específica de Realtime Database y otorgue la recompensa cuando se cree. Por ejemplo:

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

Luego, cuando un nuevo usuario se registre, active esta función creando la clave de Realtime Database. Por ejemplo, active la función en el detector de éxito de linkWithCredential , que creó en el paso anterior:

Rápido

Nota: Este producto de Firebase no está disponible en objetivos 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)
        }

Para otorgar una recompensa al remitente cuando el destinatario alcance el nivel 5, implemente una función que vigile los cambios en el campo de level en sus registros de usuario. Si un usuario pasó del nivel 4 al nivel 5, y el usuario tiene un referente registrado, otorgue la recompensa:

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

Tanto el remitente como su nuevo usuario ahora han recibido sus recompensas.