Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

อ้างอิงรางวัล

จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ

วิธีที่มีประสิทธิภาพที่สุดในการรับผู้ใช้ใหม่คือผ่านการอ้างอิงผู้ใช้ คุณสามารถใช้ Dynamic Links ร่วมกับ Realtime Database และ Cloud Functions สำหรับ Firebase เพื่อสนับสนุนให้ผู้ใช้เชิญเพื่อนของพวกเขาโดยเสนอรางวัลในแอปสำหรับการอ้างอิงที่ประสบความสำเร็จแก่ทั้งผู้อ้างอิงและผู้รับ

ประโยชน์หลัก

  • เร่งการเติบโตโดยมอบสิ่งจูงใจให้ผู้ใช้เชิญเพื่อน
  • ลิงก์คำเชิญทำงานข้ามแพลตฟอร์ม
  • ผู้ใช้ใหม่ที่เปิดแอปของคุณเป็นครั้งแรกจะได้รับประสบการณ์ใช้งานครั้งแรกที่คุณปรับแต่งให้เหมาะกับพวกเขา ตัวอย่างเช่น คุณสามารถเชื่อมต่อกับเพื่อนที่เชิญพวกเขาโดยอัตโนมัติ
  • เลือกเลื่อนเวลาการให้รางวัลจนกว่าผู้ใช้ใหม่จะเสร็จสิ้นภารกิจแนะนำบางอย่าง เช่น การทำบทช่วยสอนให้เสร็จสิ้น

นี่คือวิธีเริ่มต้น!

ตั้งค่า Firebase และ Dynamic Links SDK

ตั้งค่าโปรเจ็กต์ Firebase ใหม่และติดตั้ง Dynamic Links SDK ในแอปของคุณ ( iOS , Android , C++ , เอกภาพ ) การติดตั้ง SDK ลิงก์แบบไดนามิกช่วยให้ Firebase ส่งต่อข้อมูลเกี่ยวกับลิงก์แบบไดนามิกไปยังแอปได้ รวมถึงหลังจากที่ผู้ใช้ติดตั้งแอป หากไม่มี SDK จะไม่มีวิธีเชื่อมต่อผู้ใช้หลังการติดตั้งด้วยการคลิกล่วงหน้า

ในการสร้างคำเชิญ ขั้นแรกให้สร้างลิงก์ที่ผู้รับเปิดขึ้นเพื่อตอบรับคำเชิญ หลังจากนั้น คุณจะใส่ลิงก์นี้ในข้อความเชิญ เมื่อผู้รับคำเชิญติดตั้งแอปของคุณโดยเปิดลิงก์ พวกเขาจะได้รับประสบการณ์ใช้งานครั้งแรกที่ปรับแต่งได้ รวมถึงการรับรางวัลในแอป

ลิงก์คำเชิญนี้เป็นลิงก์แบบไดนามิกที่มีค่าพารามิเตอร์ link ซึ่งระบุว่ามาจากผู้ใช้ปัจจุบันของคุณ

มีหลายวิธีที่คุณสามารถจัดรูปแบบเพย์โหลดพารามิเตอร์ link เหล่านี้และเชื่อมโยงเข้ากับแอปของคุณ วิธีง่ายๆ วิธีหนึ่งคือการระบุ ID บัญชีผู้ใช้ของผู้ส่งในพารามิเตอร์การสืบค้นดังในตัวอย่างต่อไปนี้:

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

จากนั้น เพื่อ สร้างลิงก์แบบไดนามิก ที่เหมาะสมสำหรับรวมในการเชิญ คุณสามารถใช้ Dynamic Link Builder API:

Swift

หมายเหตุ: ผลิตภัณฑ์ Firebase นี้ไม่มีใน macOS, Mac Catalyst, tvOS หรือ 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
    // ...
}

ส่งคำเชิญ

เมื่อคุณสร้างลิงก์แล้ว คุณสามารถรวมลิงก์ไว้ในคำเชิญได้ คำเชิญอาจเป็นอีเมล ข้อความ SMS หรือสื่ออื่นๆ ขึ้นอยู่กับสิ่งที่เหมาะสมที่สุดสำหรับแอปและผู้ชมของคุณ

ตัวอย่างเช่น ในการส่งคำเชิญทางอีเมล:

Swift

หมายเหตุ: ผลิตภัณฑ์ Firebase นี้ไม่มีใน macOS, Mac Catalyst, tvOS หรือ 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)
}

ดึงข้อมูลอ้างอิงในแอพของคุณ

เมื่อผู้รับคำเชิญเปิดลิงก์อ้างอิง พวกเขาจะถูกนำไปที่ App Store หรือ Play Store เพื่อติดตั้งแอปของคุณ หากยังไม่ได้ติดตั้ง จากนั้น เมื่อพวกเขาเปิดแอปของคุณเป็นครั้งแรก คุณสามารถดึงข้อมูลการอ้างอิงที่คุณรวมไว้ในลิงก์แบบไดนามิกและใช้เพื่อรับรางวัลได้

โดยปกติ คุณต้องการให้รางวัลผู้อ้างอิงเฉพาะหลังจากที่ผู้รับคำเชิญลงทะเบียน หรือแม้แต่หลังจากที่ผู้ใช้ใหม่ทำงานบางอย่างเสร็จสิ้น จนกว่าจะตรงตามเกณฑ์การให้รางวัล คุณต้องติดตามข้อมูลรางวัลที่คุณได้รับจากลิงก์แบบไดนามิก

วิธีหนึ่งในการติดตามข้อมูลนี้คือลงชื่อเข้าใช้ผู้ใช้โดยไม่ระบุชื่อและจัดเก็บข้อมูลในบันทึกฐานข้อมูลเรียลไทม์ของบัญชีที่ไม่ระบุตัวตน เมื่อผู้รับลงทะเบียนและบัญชีที่ไม่ระบุตัวตนถูกแปลงเป็นบัญชีถาวร บัญชีใหม่จะมี UID เดียวกันกับบัญชีที่ไม่ระบุตัวตน ส่งผลให้สามารถเข้าถึงข้อมูลรางวัลได้

ตัวอย่างเช่น หากต้องการบันทึก UID ของผู้อ้างอิงหลังจากที่ผู้รับเปิดแอปของคุณ:

Swift

หมายเหตุ: ผลิตภัณฑ์ Firebase นี้ไม่มีใน macOS, Mac Catalyst, tvOS หรือ 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)
            }
}

จากนั้น เมื่อผู้รับคำเชิญตัดสินใจสร้างบัญชี คุณสามารถโอนข้อมูลอ้างอิงจากบัญชีที่ไม่ระบุตัวตนไปยังบัญชีใหม่ของผู้รับคำเชิญได้

ขั้นแรก รับอ็อบเจ็กต์ AuthCredential โดยใช้วิธีลงชื่อเข้าใช้ที่ผู้ได้รับเชิญต้องการใช้ ตัวอย่างเช่น ในการลงชื่อเข้าใช้ด้วยที่อยู่อีเมลและรหัสผ่าน:

Swift

หมายเหตุ: ผลิตภัณฑ์ Firebase นี้ไม่มีใน macOS, Mac Catalyst, tvOS หรือ watchOS
let credential = EmailAuthProvider.credential(withEmail: email, password: password)

Java

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

Kotlin+KTX

val credential = EmailAuthProvider.getCredential(email, password)

จากนั้นเชื่อมโยงข้อมูลประจำตัวนี้กับบัญชีที่ไม่ระบุตัวตน:

Swift

หมายเหตุ: ผลิตภัณฑ์ Firebase นี้ไม่มีใน macOS, Mac Catalyst, tvOS หรือ 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.
        }

บัญชีใหม่แบบถาวรสามารถเข้าถึงข้อมูลรางวัลทั้งหมดที่คุณเพิ่มลงในบัญชีที่ไม่ระบุตัวตน

ให้รางวัลแก่ผู้อ้างอิงและผู้รับ

เมื่อคุณดึงและบันทึกข้อมูลคำเชิญจากลิงก์แบบไดนามิกแล้ว คุณสามารถมอบรางวัลผู้อ้างอิงให้กับผู้อ้างอิงและผู้รับเมื่อใดก็ตามที่ตรงตามเกณฑ์ที่คุณต้องการ

แม้ว่าคุณจะสามารถเขียนไปยังฐานข้อมูลเรียลไทม์จากแอปไคลเอ็นต์ของคุณได้ แต่คุณมักจะต้องการอนุญาตเฉพาะการเข้าถึงแบบอ่านข้อมูล เช่น สกุลเงินในแอปจากแอปของคุณ และดำเนินการเขียนจากแบ็กเอนด์ของคุณเท่านั้น แบ็กเอนด์นี้อาจเป็นระบบใดๆ ก็ตามที่เรียกใช้ Firebase Admin SDK ได้ แต่มักจะง่ายที่สุดที่จะใช้ Cloud Functions เพื่อทำงานเหล่านี้

ตัวอย่างเช่น สมมติว่าคุณมีเกมและคุณต้องการให้รางวัลเป็นสกุลเงินในเกมแก่ผู้รับหลังจากผู้รับลงทะเบียน และผู้อ้างอิงหลังจากผู้รับถึงระดับ 5

ในการมอบรางวัลสำหรับการลงทะเบียน ให้ปรับใช้ฟังก์ชันที่คอยดูคีย์ฐานข้อมูลเรียลไทม์ที่จะสร้าง และให้รางวัลเมื่อถึงเวลานั้น ตัวอย่างเช่น:

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

จากนั้น เมื่อผู้ใช้ใหม่ลงทะเบียน ให้เรียกใช้ฟังก์ชันนี้โดยสร้างคีย์ฐานข้อมูลเรียลไทม์ ตัวอย่างเช่น ทริกเกอร์ฟังก์ชันในตัวฟังความสำเร็จของ linkWithCredential ซึ่งคุณสร้างในขั้นตอนก่อนหน้า:

Swift

หมายเหตุ: ผลิตภัณฑ์ Firebase นี้ไม่มีใน macOS, Mac Catalyst, tvOS หรือ 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)
        }

หากต้องการให้รางวัลแก่ผู้อ้างอิงเมื่อผู้รับถึงระดับ 5 ให้ปรับใช้ฟังก์ชันที่คอยดูการเปลี่ยนแปลงในช่อง level ในบันทึกผู้ใช้ของคุณ หากผู้ใช้เปลี่ยนจากระดับ 4 เป็นระดับ 5 และมีผู้อ้างอิงบันทึก ให้รางวัล:

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

ทั้งผู้อ้างอิงและผู้ใช้ใหม่ของคุณได้รับรางวัลแล้ว