أفضل الممارسات لإدارة الرموز المميّزة للتسجيل في خدمة "المراسلة عبر السحابة الإلكترونية من Firebase"

إذا كنت تستخدم واجهات برمجة تطبيقات FCM لإنشاء طلبات إرسال آليًا، قد تلاحظ بمرور الوقت أنّك تهدر الموارد من خلال إرسال رسائل إلى أجهزة غير نشطة تستخدم رموز تسجيل قديمة. يمكن أن يؤثر هذا الموقف في بيانات تسليم الرسائل التي يتم الإبلاغ عنها في وحدة تحكّم Firebase أو البيانات التي يتم تصديرها إلى BigQuery، ويظهر ذلك على شكل انخفاض كبير (ولكن ليس صالحًا في الواقع) في معدّلات التسليم. يتناول هذا الدليل بعض الإجراءات التي يمكنك اتّخاذها للمساعدة في ضمان استهداف رسائل فعّال وإعداد تقارير تسليم صالحة.

الرموز المميّزة للتسجيل القديمة والمنتهية الصلاحية

الرموز المميّزة القديمة للتسجيل هي رموز مرتبطة بالأجهزة غير النشطة التي لم يتم ربطها بحساب FCM لأكثر من شهر. ومع مرور الوقت، يصبح من المرجّح أن يتصل الجهاز بـ FCM مرة أخرى. من غير المرجّح أن يتم إرسال الرسائل ونشر المواضيع باستخدام هذه الرموز القديمة.

هناك عدة أسباب قد تؤدي إلى انتهاء صلاحية الرمز المميّز. على سبيل المثال، قد يتم فقدان الجهاز المرتبط بالرمز المميّز أو إتلافه أو وضعه في مكان تخزين وعدم تذكره.

عندما تصل الرموز المميّزة القديمة إلى 270 يومًا من عدم النشاط، سيعتبرها FCM رموزًا مميّزة منتهية الصلاحية. بعد انتهاء صلاحية الرمز المميّز، يضع FCM علامة عليه بأنّه غير صالح ويرفض إرسال الرسائل إليه. ومع ذلك، تُصدر FCM رمز أمان جديدًا لمثيل التطبيق في الحالة النادرة التي يتصل فيها الجهاز مرة أخرى ويتم فتح التطبيق.

أفضل الممارسات الأساسية

هناك بعض الممارسات الأساسية التي يجب اتّباعها في أي تطبيق يستخدم FCM واجهات برمجة التطبيقات لإنشاء طلبات الإرسال آليًا. في ما يلي أفضل الممارسات الرئيسية:

  • استرداد الرموز المميّزة للتسجيل من FCM وتخزينها على الخادم من الأدوار المهمة للخادم تتبُّع رمز التمويه لكل مستخدم والاحتفاظ بقائمة محدّثة بالرموز النشطة. ننصحك بشدة باستخدام طابع زمني للرمز المميّز في الرمز البرمجي والخوادم، وتعديل هذا الطابع الزمني على فترات زمنية منتظمة.
  • الحفاظ على حداثة الرموز المميّزة وإزالة الرموز المميّزة القديمة: بالإضافة إلى إزالة الرموز المميّزة التي لم تعُد FCM تعتبرها صالحة، ننصحك بمراقبة علامات أخرى تدل على أنّ الرموز المميّزة قديمة وإزالتها بشكل استباقي. ويتناول هذا الدليل بعض الخيارات المتاحة لك لتحقيق ذلك.

استرداد الرموز المميزة للتسجيل وتخزينها

عند بدء تشغيل تطبيقك لأول مرة، تنشئ حزمة SDK لنظام التشغيل FCM رمز تسجيل لنسخة تطبيق العميل. هذا هو الرمز المميّز الذي يجب تضمينه في طلبات الإرسال المستهدفة من واجهة برمجة التطبيقات، أو إضافته إلى الاشتراكات في المواضيع لاستهداف topics.

ننصح بشدة بأن يستردّ تطبيقك هذا الرمز المميّز عند بدء التشغيل الأولي ويحفظه في خادم التطبيق مع الطابع الزمني. يجب أن يتم تنفيذ الطابع الزمني من خلال الرمز البرمجي والخوادم، لأنّه لا يتم توفيره من خلال حِزم تطوير البرامج (SDK) لنظام التشغيل FCM.

من المهم أيضًا حفظ الرمز المميّز على الخادم وتعديل الطابع الزمني عند تغييره، مثل:

  • استعادة التطبيق على جهاز جديد
  • إلغاء تثبيت التطبيق أو إعادة تثبيته
  • محو المستخدم لبيانات التطبيق
  • يصبح التطبيق نشطًا مرة أخرى بعد انتهاء صلاحية الرمز المميّز الحالي لدى FCM

مثال: تخزين الرموز المميّزة والطابع الزمني في Cloud Firestore

على سبيل المثال، يمكنك استخدام Cloud Firestore لتخزين الرموز المميّزة في مجموعة تُسمى fcmTokens. يتوافق كل معرّف مستند في المجموعة مع معرّف مستخدم، ويخزّن المستند رمز تسجيل حالي و الطابع الزمني لآخر تعديل. استخدِم الدالة set كما هو موضّح في مثال Kotlin التالي:

    /**
     * Persist token to third-party servers.
     *
     * Modify this method to associate the user's FCM registration token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private fun sendTokenToServer(token: String?) {
        // If you're running your own server, call API to send token and today's date for the user

        // Example shown below with Firestore
        // Add token and timestamp to Firestore for this user
        val deviceToken = hashMapOf(
            "token" to token,
            "timestamp" to FieldValue.serverTimestamp(),
        )
        // Get user ID from Firebase Auth or your own server
        Firebase.firestore.collection("fcmTokens").document("myuserid")
            .set(deviceToken)
    }

عند استرداد رمز مميّز، يتم تخزينه في Cloud Firestore من خلال استدعاء sendTokenToServer:

    /**
     * Called if the FCM registration token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the
     * FCM registration token is initially generated so this is where you would retrieve the token.
     */
    override fun onNewToken(token: String) {
        Log.d(TAG, "Refreshed token: $token")

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // FCM registration token to your app server.
        sendTokenToServer(token)
    }
        var token = Firebase.messaging.token.await()

        // Check whether the retrieved token matches the one on your server for this user's device
        val preferences = this.getPreferences(Context.MODE_PRIVATE)
        val tokenStored = preferences.getString("deviceToken", "")
        lifecycleScope.launch {
            if (tokenStored == "" || tokenStored != token)
            {
                // If you have your own server, call API to send the above token and Date() for this user's device

                // Example shown below with Firestore
                // Add token and timestamp to Firestore for this user
                val deviceToken = hashMapOf(
                    "token" to token,
                    "timestamp" to FieldValue.serverTimestamp(),
                )

                // Get user ID from Firebase Auth or your own server
                Firebase.firestore.collection("fcmTokens").document("myuserid")
                    .set(deviceToken).await()
            }
        }

الحفاظ على حداثة الرموز المميّزة وإزالة الرموز المميّزة القديمة

إنّ تحديد ما إذا كان الرمز المميّز جديدًا أو قديمًا ليس أمرًا مباشرًا في بعض الأحيان. لتغطية جميع الحالات، يجب تحديد حدّ أدنى لوقت اعتبار الرموز المميّزة قديمة. تُعتبر العلامة المميّزة قديمة تلقائيًا في FCM إذا لم يتم ربط مثيل التطبيق بها لمدة شهر. من المحتمل أن يكون أي رمز مميّز أقدم من شهر واحد متعلقًا بجهاز غير نشط، لأنّه في حال كان الجهاز نشطًا، كان من المفترض أن يُحدِّث رمزه المميّز.

استنادًا إلى حالة الاستخدام، قد يكون شهر واحد قصيرًا جدًا أو طويلاً جدًا، لذا يعود تحديد المعايير المناسبة إليك.

رصد الردود غير الصالحة للرموز المميّزة من الخلفية في FCM

تأكَّد من رصد الردود غير الصالحة للرموز المميّزة من FCM والاستجابة لها من خلال حذف أي رموز تسجيل معروف أنّها غير صالحة أو انتهت صلاحيتها من نظامك. باستخدام واجهة برمجة التطبيقات HTTP v1، قد تشير رسائل الخطأ هذه إلى أنّه استهدَف طلب الإرسال علامات مميزة غير صالحة أو منتهية الصلاحية:

  • UNREGISTERED (HTTP 404)
  • INVALID_ARGUMENT (HTTP 400)

إذا كنت متأكدًا من أنّ الحمولة البرمجية للرسالة صالحة وتلقّيت أيًا من هذين الردّين على رمز مستهدف، يمكنك بأمان حذف سجلّ هذا الرمز المستهدف، لأنّه لن يكون صالحًا مرة أخرى. على سبيل المثال، لحذف الرموز المميّزة غير الصالحة من Cloud Firestore، يمكنك نشر وتنفيذ دالة مثل ما يلي:

    // Registration token comes from the client FCM SDKs
    const registrationToken = 'YOUR_REGISTRATION_TOKEN';

    const message = {
    data: {
        // Information you want to send inside of notification
    },
    token: registrationToken
    };

    // Send message to device with provided registration token
    getMessaging().send(message)
    .then((response) => {
        // Response is a message ID string.
    })
    .catch((error) => {
        // Delete token for user if error code is UNREGISTERED or INVALID_ARGUMENT.
        if (errorCode == "messaging/registration-token-not-registered") {
            // If you're running your own server, call API to delete the
            token for the user

            // Example shown below with Firestore
            // Get user ID from Firebase Auth or your own server
            Firebase.firestore.collection("fcmTokens").document(user.uid).delete()
        }
    });

لن يعرض FCM استجابة رمز مميّز غير صالح إلا إذا انتهت صلاحية الرمز المميّز بعد 270 يومًا أو إذا ألغى العميل التسجيل صراحةً. إذا كنت بحاجة إلى تتبع المهلة بدقة أكبر وفقًا لتعريفاتك الخاصة، يمكنك إزالة الرموز المميّزة القديمة للتسجيل بشكل استباقي.

تعديل الرموز المميّزة بانتظام

ننصحك باسترداد جميع الرموز المميّزة للتسجيل وتعديلها بشكل دوري على خادمك. يتطلّب ذلك منك تنفيذ ما يلي:

  • أضِف منطق التطبيق في تطبيق العميل لاسترداد الرمز المميّز الحالي باستخدام طلب البيانات المناسب لواجهة برمجة التطبيقات (مثل token(completion): لأنظمة التشغيل Apple أو getToken() لنظام التشغيل Android)، ثم أرسِل الرمز المميّز الحالي إلى خادم التطبيق لتخزينه (مع طابع زمني). يمكن أن تكون هذه مهمة شهرية تم ضبطها لتغطية كل العملاء أو الرموز المميّزة.
  • أضِف منطق الخادم لتعديل الطابع الزمني للرمز المميّز على فترات منتظمة، بغض النظر عمّا إذا كان الرمز المميّز قد تغيّر أم لا.

للحصول على مثال على منطق Android لتعديل الرموز المميّزة باستخدام WorkManager، اطّلِع على إدارة الرموز المميّزة لميزة "المراسلة عبر السحابة الإلكترونية" في مدوّنة Firebase.

بغض النظر عن نمط التوقيت الذي تتّبعه، احرص على تعديل الرموز المميّزة بشكل دوري. إنّ معدّل تكرار التحديث مرة واحدة في الشهر يحقق توازنًا جيدًا بين تأثير البطارية ورصد الرموز المميّزة غير النشطة للتسجيل. من خلال إجراء هذا التحديث، تضمن أيضًا أنّ أي جهاز يصبح غير نشط سيتم تحديث تسجيله عندما يصبح نشطًا مرة أخرى. لا فائدة من إجراء عملية إعادة التحميل بشكلٍ متكرّر أكثر من مرة في الأسبوع.

إزالة الرموز المميّزة القديمة للتسجيل

قبل إرسال الرسائل إلى جهاز، تأكَّد من أنّ الطابع الزمني لمرموز تسجيل الجهاز يقع ضمن فترة صلاحيته. على سبيل المثال، يمكنك تنفيذ Cloud Functions for Firebase لإجراء عملية تحقّق يومية للتأكّد من أنّ الطابع الزمني يقع ضمن فترة زمنية محدّدة للصلاحية، مثل const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;، ثم إزالة الرموز المميّزة القديمة:

exports.pruneTokens = functions.pubsub.schedule('every 24 hours').onRun(async (context) => {
  // Get all documents where the timestamp exceeds is not within the past month
  const staleTokensResult = await admin.firestore().collection('fcmTokens')
      .where("timestamp", "<", Date.now() - EXPIRATION_TIME)
      .get();
  // Delete devices with stale tokens
  staleTokensResult.forEach(function(doc) { doc.ref.delete(); });
});

إلغاء اشتراك الرموز غير الصالحة من المواضيع

إذا كنت تستخدم المواضيع، قد تحتاج أيضًا إلى إلغاء تسجيل الرموز المميّزة القديمة من المواضيع التي اشتركت فيها. يتضمن ذلك خطوتَين:

  1. يجب أن يعيد تطبيقك الاشتراك في المواضيع مرة واحدة في الشهر وكلما تغيّر رمز تسجيل التطبيق. ويشكّل ذلك حلًا ذاتي الاسترداد، حيث تظهر الاشتراكات تلقائيًا عندما يصبح التطبيق نشطًا مرة أخرى.
  2. إذا كانت إحدى نُسخ التطبيق غير نشِطة لمدة شهر واحد (أو فترة عدم التحديث التي تحدّدها بنفسك)، عليك إلغاء اشتراكها في المواضيع باستخدام حزمة تطوير البرامج (SDK) لإدارة Firebase لمحاولة حذف تعيين الرمز المميّز إلى الموضوع من الخلفية في FCM.

تتمثل فائدة هاتين الخطوتَين في أنّ عمليات التوسيع ستتم بشكل أسرع لأنّه يتوفر عدد أقل من الرموز المميّزة القديمة التي يمكن توسيع نطاقها، وستتم إعادة اشتراك نُسخ التطبيق القديمة تلقائيًا بعد أن تصبح نشطة مرة أخرى.

قياس نجاح عملية الإرسال

للحصول على الصورة الأكثر دقة لتسليم الرسائل، من الأفضل إرسال الرسائل إلى نُسخ التطبيق المستخدَمة بشكل نشط فقط. ويُعدّ ذلك مهمًا بشكل خاص إذا كنت تُرسِل باستمرار رسائل إلى مواضيع تضمّ أعدادًا كبيرة من المشتركين. وإذا كان جزء من هؤلاء المشتركين غير نشط، يمكن أن يكون التأثير على إحصاءات التسليم ملحوظًا بمرور الوقت.

قبل استهداف الرسائل برمز مميّز، يُرجى مراعاة ما يلي:

لمزيد من المعلومات عن التسليم، يُرجى الاطّلاع على مقالة فهم عملية تسليم الرسائل.