Catch up on everything we announced at this year's Firebase Summit. Learn more

Phần thưởng giới thiệu

Một trong những cách hiệu quả nhất để có được người dùng mới là thông qua sự giới thiệu của người dùng. Bạn có thể sử dụng động Liên kết cùng với cơ sở dữ liệu thời gian thựcChức năng Đám mây cho căn cứ hỏa lực để khuyến khích người dùng của bạn để mời bạn bè của họ bằng cách cung cấp những phần thưởng trong ứng dụng cho các giới thiệu thành công cho cả hai giới thiệu và người nhận.

Các lợi ích chính

  • Đẩy nhanh tốc độ phát triển bằng cách khuyến khích người dùng mời bạn bè của họ.
  • Liên kết lời mời hoạt động trên các nền tảng.
  • Người dùng mới mở ứng dụng của bạn lần đầu tiên sẽ có được trải nghiệm lần đầu tiên mà bạn tùy chỉnh cho họ. Ví dụ: bạn có thể tự động kết nối họ với người bạn đã mời họ.
  • Tùy ý trì hoãn việc cấp phần thưởng cho đến khi người dùng mới hoàn thành một số nhiệm vụ giới thiệu, chẳng hạn như hoàn thành hướng dẫn.

Đây là cách bắt đầu!

Thiết lập Firebase và SDK liên kết động

Thiết lập dự án Firebase mới và cài đặt SDK liên kết động vào ứng dụng của bạn. ( IOS , Android , C ++ , Unity ). Việc cài đặt SDK liên kết động cho phép Firebase truyền dữ liệu về Liên kết động tới ứng dụng, kể cả sau khi người dùng cài đặt ứng dụng. Nếu không có SDK, không có cách nào để kết nối người dùng sau cài đặt với một lần nhấp vào cài đặt trước.

Để tạo lời mời, trước tiên hãy tạo liên kết mà người nhận sẽ mở để chấp nhận lời mời. Sau đó, bạn sẽ đưa liên kết này vào văn bản của lời mời. Khi người nhận lời mời cài đặt ứng dụng của bạn bằng cách mở liên kết, họ có thể nhận được trải nghiệm lần đầu tiên được tùy chỉnh, bao gồm cả nhận phần thưởng trong ứng dụng.

Liên kết lời mời này là một liên kết với một động link tham số giá trị cho biết đó là từ người dùng hiện tại của bạn.

Có rất nhiều cách để bạn có thể định dạng các link trọng tải tham số và buộc chúng vào ứng dụng của bạn. Một cách đơn giản là để chỉ định ID tài khoản người dùng của người gửi trong một tham số truy vấn như trong ví dụ sau:

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

Sau đó, để tạo động Liên kết phù hợp để đưa vào một lời mời, bạn có thể sử dụng API Dynamic Link Builder:

Nhanh

Lưu ý: sản phẩm căn cứ hỏa lực này không có sẵn trên hệ điều hành MacOS, Mac Catalyst, tvOS, hoặc mục tiêu 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
    // ...
}

Gửi lời mời

Bây giờ bạn đã tạo liên kết, bạn có thể đưa nó vào lời mời. Lời mời có thể là email, tin nhắn SMS hoặc bất kỳ phương tiện nào khác, tùy thuộc vào điều gì phù hợp nhất với ứng dụng và đối tượng của bạn.

Ví dụ: để gửi một lời mời qua email:

Nhanh

Lưu ý: sản phẩm căn cứ hỏa lực này không có sẵn trên hệ điều hành MacOS, Mac Catalyst, tvOS, hoặc mục tiêu 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)
}

Truy xuất thông tin giới thiệu trong ứng dụng của bạn

Khi người nhận lời mời mở liên kết giới thiệu, họ sẽ được dẫn đến Cửa hàng ứng dụng hoặc Cửa hàng Play để cài đặt ứng dụng của bạn nếu ứng dụng đó chưa được cài đặt. Sau đó, khi họ mở ứng dụng của bạn lần đầu tiên, bạn có thể truy xuất thông tin giới thiệu mà bạn đã đưa vào Liên kết động và sử dụng thông tin đó để áp dụng phần thưởng.

Thông thường, bạn chỉ muốn cấp phần thưởng giới thiệu sau khi người nhận lời mời đăng ký hoặc thậm chí chỉ sau khi người dùng mới hoàn thành một số tác vụ. Cho đến khi các tiêu chí phần thưởng được đáp ứng, bạn cần theo dõi thông tin phần thưởng mà bạn nhận được từ Liên kết động.

Một cách để theo dõi thông tin này là đăng nhập ẩn danh người dùng và lưu trữ dữ liệu trong bản ghi Cơ sở dữ liệu thời gian thực của tài khoản ẩn danh. Khi người nhận đăng ký và tài khoản ẩn danh được chuyển đổi thành tài khoản vĩnh viễn, tài khoản mới sẽ có cùng UID với tài khoản ẩn danh và kết quả là sẽ có quyền truy cập vào thông tin phần thưởng.

Ví dụ: để lưu UID của người giới thiệu sau khi người nhận mở ứng dụng của bạn:

Nhanh

Lưu ý: sản phẩm căn cứ hỏa lực này không có sẵn trên hệ điều hành MacOS, Mac Catalyst, tvOS, hoặc mục tiêu watchos.
func application(_ app: UIApplication, open url: URL, options:
    [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
  if let isDynamicLink = DynamicLinks.dynamicLinks()?.shouldHandleDynamicLink(fromCustomSchemeURL: url),
      isDynamicLink {
    let dynamicLink = DynamicLinks.dynamicLinks()?.dynamicLink(fromCustomSchemeURL: url)
    return handleDynamicLink(dynamicLink)
  }
  // Handle incoming URL with other methods as necessary
  // ...
  return false
}

@available(iOS 8.0, *)
func application(_ application: UIApplication,
    continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
  guard let dynamicLinks = DynamicLinks.dynamicLinks() else { return false }
  let handled = dynamicLinks.handleUniversalLink(userActivity.webpageURL!) { (dynamicLink, error) in
    if (dynamicLink != nil) && !(error != nil) {
      self.handleDynamicLink(dynamicLink)
    }
  }
  if !handled {
    // Handle incoming URL with other methods as necessary
    // ...
  }
  return handled
}

func handleDynamicLink(_ dynamicLink: DynamicLink?) -> Bool {
  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.
        }
      }
    }
  }
  return true
}

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

Sau đó, khi người nhận lời mời quyết định tạo tài khoản, bạn có thể chuyển thông tin giới thiệu từ tài khoản ẩn danh sang tài khoản mới của người nhận lời mời.

Thứ nhất, nhận được một AuthCredential đối tượng sử dụng đăng nhập trong phương pháp mời muốn sử dụng. Ví dụ: để đăng nhập bằng địa chỉ email và mật khẩu:

Nhanh

Lưu ý: sản phẩm căn cứ hỏa lực này không có sẵn trên hệ điều hành MacOS, Mac Catalyst, tvOS, hoặc mục tiêu watchos.
let credential = EmailAuthProvider.credential(withEmail: email, password: password)

Java

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

Kotlin + KTX

val credential = EmailAuthProvider.getCredential(email, password)

Sau đó, liên kết thông tin đăng nhập này với tài khoản ẩn danh:

Nhanh

Lưu ý: sản phẩm căn cứ hỏa lực này không có sẵn trên hệ điều hành MacOS, Mac Catalyst, tvOS, hoặc mục tiêu 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.
        }

Tài khoản mới, vĩnh viễn, có quyền truy cập vào tất cả dữ liệu phần thưởng mà bạn đã thêm vào tài khoản ẩn danh.

Cấp phần thưởng cho người giới thiệu và người nhận

Bây giờ bạn đã truy xuất và lưu dữ liệu lời mời từ Liên kết động, bạn có thể cấp phần thưởng giới thiệu cho người giới thiệu và người nhận bất cứ khi nào các tiêu chí bạn muốn yêu cầu đã được đáp ứng.

Mặc dù bạn có thể ghi vào Cơ sở dữ liệu thời gian thực từ ứng dụng khách của mình, nhưng bạn thường chỉ muốn cho phép quyền truy cập đọc vào dữ liệu như tiền tệ trong ứng dụng từ ứng dụng của mình và chỉ thực hiện các thao tác ghi từ chương trình phụ trợ của bạn. Phần phụ trợ này có thể là bất kỳ hệ thống nào có khả năng chạy SDK quản trị Firebase, nhưng việc sử dụng Chức năng đám mây để thực hiện các tác vụ này thường dễ dàng nhất.

Ví dụ: giả sử bạn có một trò chơi và bạn muốn cấp phần thưởng bằng đơn vị tiền tệ trong trò chơi cho người nhận sau khi người nhận đăng ký và cho người giới thiệu sau khi người nhận đạt cấp độ 5.

Để cấp phần thưởng cho việc đăng ký, hãy triển khai một chức năng theo dõi khóa Cơ sở dữ liệu thời gian thực cụ thể được tạo và cấp phần thưởng khi đúng như vậy. Ví dụ:

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

Sau đó, khi người dùng mới đăng ký, hãy kích hoạt chức năng này bằng cách tạo khóa Cơ sở dữ liệu thời gian thực. Ví dụ, kích hoạt các chức năng trong linkWithCredential thành người biết lắng nghe 's, mà bạn đã tạo ở bước trước:

Nhanh

Lưu ý: sản phẩm căn cứ hỏa lực này không có sẵn trên hệ điều hành MacOS, Mac Catalyst, tvOS, hoặc mục tiêu 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)
        }

Cấp một phần thưởng cho người giới thiệu khi đạt nhận cấp 5, triển khai một chức năng mà giám sát mọi thay đổi đối với level lĩnh vực trong hồ sơ người dùng của bạn. Nếu người dùng đã đi từ cấp 4 đến cấp 5 và người dùng có liên kết giới thiệu được ghi lại, hãy cấp phần thưởng:

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

Cả người giới thiệu và người dùng mới của bạn hiện đã nhận được phần thưởng của họ.