FCM kayıt jetonu yönetimi için en iyi uygulamalar

Gönderme isteklerini programatik olarak oluşturmak için FCM API'lerini kullanıyorsanız zaman içinde eski kayıt jetonlarına sahip etkin olmayan cihazlara mesaj göndererek kaynakları boşa harcadığınızı fark edebilirsiniz. Bu durum, Firebase konsolunda raporlanan mesaj teslimi verilerini veya BigQuery'ye aktarılan verileri etkileyebilir. Bu durum, teslim oranlarında önemli (ancak gerçekte geçerli olmayan) bir düşüşe yol açabilir. Bu kılavuzda, etkili mesaj hedefleme ve geçerli yayınlama raporlaması sağlamak için alabileceğiniz bazı önlemler ele alınmaktadır.

Eski ve süresi dolmuş kayıt jetonları

Eski kayıt jetonları, bir aydan uzun süredir FCM'ye bağlı olmayan etkin olmayan cihazlarla ilişkili jetonlardır. Zaman geçtikçe cihazın FCM'ye tekrar bağlanma olasılığı da azalır. Bu eski jetonlar için mesaj gönderme ve konu dağılmalarının hiçbir zaman teslim edilmesi pek olası değildir.

Jetonların eskimesinin birkaç nedeni vardır. Örneğin, jetonun ilişkili olduğu cihaz kaybolabilir, tahrip olabilir veya depolama alanına yerleştirilebilir ve unutulabilir.

Eski jetonlar 270 günlük etkin olmama durumuna ulaştığında FCM, bu jetonları süresi dolmuş jetonlar olarak kabul eder. Bir jetonun süresi dolduğunda, FCM jetonu geçersiz olarak işaretler ve bu jetona yapılan gönderimleri reddeder. Bununla birlikte, cihazın tekrar bağlanıp uygulamanın açılması gibi nadir durumlarda FCM, uygulama örneği için yeni bir jeton yayınlar.

Temel en iyi uygulamalar

Programatik olarak gönderme istekleri oluşturmak için FCM API'lerini kullanan tüm uygulamalarda izlemeniz gereken bazı temel uygulamalar vardır. Başlıca en iyi uygulamalar şunlardır:

  • FCM'den kayıt jetonlarını alın ve sunucunuzda depolayın. Sunucunun önemli bir rolü, her istemcinin jetonunu takip etmek ve etkin jetonların güncel bir listesini tutmaktır. Kodunuza ve sunucularınıza bir jeton zaman damgası uygulamanızı ve bu zaman damgasını düzenli aralıklarla güncellemenizi önemle tavsiye ederiz.
  • Jeton güncelliğini koruyun ve eski jetonları kaldırın. FCM'nin artık geçerli olarak kabul etmediği jetonları kaldırmanın yanı sıra, jetonların eskidiğine dair diğer işaretleri izleyip proaktif olarak kaldırmak isteyebilirsiniz. Bu kılavuzda, bunu başarmak için kullanabileceğiniz bazı seçenekler açıklanmaktadır.

Kayıt jetonlarını alma ve depolama

Uygulamanız ilk kez başlatıldığında FCM SDK'sı istemci uygulaması örneği için bir kayıt jetonu oluşturur. Bu, API'den hedeflenen gönderme isteklerine eklemeniz veya konuları hedeflemek için konu aboneliklerine eklemeniz gereken jetondur.

Uygulamanızın ilk başlatma sırasında bu jetonu almasını ve bir zaman damgasıyla birlikte uygulama sunucunuza kaydetmesini önemle tavsiye ederiz. Bu zaman damgası, FCM SDK'ları tarafından size sağlanmadığından kodunuz ve sunucularınız tarafından uygulanmalıdır.

Ayrıca, jetonu sunucuya kaydetmek ve her değişiklikte (örneğin aşağıdaki durumlarda) zaman damgasını güncellemek de önemlidir:

  • Uygulama yeni bir cihaza geri yüklenir.
  • Kullanıcı uygulamayı kaldırır veya yeniden yükler
  • Kullanıcı uygulama verilerini siler
  • FCM mevcut jetonunun süresi dolduktan sonra uygulama tekrar etkin hale gelir.

Örnek: Cloud Firestore'da depolama jetonları ve zaman damgaları

Örneğin, jetonları fcmTokens adlı bir koleksiyonda depolamak için Cloud Firestore'u kullanabilirsiniz. Koleksiyondaki her belge kimliği bir kullanıcı kimliğine karşılık gelir ve belge, mevcut kayıt jetonunu ve son güncelleme zaman damgasını depolar. set işlevini aşağıdaki Kotlin örneğinde gösterildiği gibi kullanın:

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

Alınan jetonlar, sendTokenToServer çağrısı yapılarak Cloud Firestore'da depolanır:

    /**
     * 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()
            }
        }

Jeton güncelliğini koruyun ve eski jetonları kaldırın

Bir jetonun yeni mi yoksa eski mi olduğunu belirlemek her zaman kolay değildir. Tüm durumları kapsamak için jetonların eski olduğunu düşündüğünüzde uygulanacak bir eşik belirlemeniz gerekir. Varsayılan olarak FCM, uygulama örneği bir ay boyunca bağlanmamış olan bir jetonu eski olarak kabul eder. Bir aydan eski olan herhangi bir jeton etkin olmayan bir cihaz olabilir; aksi halde, etkin bir cihaz jetonu yenilerdi.

Kullanım alanınıza bağlı olarak bir ay çok kısa veya çok uzun olabilir. Bu nedenle size uygun olan kriterleri belirlemek size kalmıştır.

FCM arka ucundan geçersiz jeton yanıtlarını tespit etme

FCM'den geçersiz jeton yanıtlarını tespit ettiğinizden emin olun ve geçersiz olduğu bilinen veya süresi dolan tüm kayıt jetonlarını sisteminizden silerek yanıt verin. HTTP v1 API ile bu hata mesajları, gönderme isteğinizin geçersiz veya süresi dolmuş jetonları hedeflediğini gösterebilir:

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

Mesaj yükünün geçerli olduğundan eminseniz ve hedeflenen jeton için bu yanıtlardan herhangi birini alırsanız bu jeton kaydını silebilirsiniz çünkü bu jeton bir daha geçerli olmayacağından bu jetonun kaydını silebilirsiniz. Örneğin, geçersiz jetonları Cloud Firestore'dan silmek için aşağıdaki gibi bir işlevi dağıtıp çalıştırabilirsiniz:

    // 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, yalnızca bir jetonun 270 gün sonra süresi dolduysa veya bir istemcinin kaydı açıkça iptal edilirse geçersiz jeton yanıtı döndürecektir. Eski kayıt durumunu kendi tanımlarınıza göre daha doğru bir şekilde izlemeniz gerekiyorsa proaktif olarak eski kayıt jetonlarını kaldırabilirsiniz.

Jetonları düzenli olarak güncelleme

Sunucunuzdaki tüm kayıt jetonlarını düzenli aralıklarla almanızı ve güncellemenizi öneririz. Bunun için şunları yapmanız gerekir:

  • Uygun API çağrısını kullanarak mevcut jetonu almak için istemci uygulamanıza uygulama mantığı ekleyin (ör. Apple platformları için token(completion): veya Android için getToken()) ve ardından mevcut jetonu depolama için uygulama sunucunuza (zaman damgasıyla birlikte) gönderin. Bu, tüm istemcileri veya jetonları kapsayacak şekilde yapılandırılmış aylık bir iş olabilir.
  • Jetonun değişip değişmediğinden bağımsız olarak, jetonun zaman damgasını düzenli aralıklarla güncellemek için sunucu mantığı ekleyin.

WorkManager kullanarak jeton güncellemeye yönelik Android mantığına dair bir örnek için Firebase blogundaki Manage Cloud Messaging Tokens (Cloud Mesajlaşma Jetonlarını Yönetme) bölümüne göz atın.

Hangi zamanlama kalıbını takip ederseniz edin, jetonları düzenli aralıklarla güncellediğinizden emin olun. Ayda bir defa yapılacak güncelleme sıklığı, pil etkisi ile etkin olmayan kayıt jetonlarını algılama arasında iyi bir denge sağlar. Bu yenileme işlemini yaparak, etkin olmayan cihazların tekrar etkin hale geldiğinde kaydı yenilemelerini de sağlayabilirsiniz. Haftalıktan daha sık yenilemenin bir faydası yoktur.

Eski kayıt jetonlarını kaldırma

Bir cihaza mesaj göndermeden önce, cihazın kayıt jetonunun zaman damgasının eskilik aralığınız içinde olduğundan emin olun. Örneğin, zaman damgasının const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; gibi tanımlanmış bir eskilik dönemi süresi içinde olduğundan emin olmak için günlük kontrol gerçekleştirmek ve ardından eski jetonları kaldırmak için Cloud Functions for Firebase'i uygulayabilirsiniz:

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

Konuların eski jeton e-posta listesinden çıkma

Konuları kullanıyorsanız abone oldukları konulara ait eski jetonların kaydını iptal etmek de isteyebilirsiniz. Bu işlem iki adımdan oluşur:

  1. Uygulamanız, konulara ayda bir kez ve kayıt jetonu değiştiğinde yeniden abone olmalıdır. Bu, uygulama tekrar etkin hale geldiğinde aboneliklerin otomatik olarak yeniden göründüğü kendi kendini iyileştiren bir çözüm oluşturur.
  2. Bir uygulama örneği bir ay boyunca boşta kalırsa (veya kendi eski zaman aralığınızda) jetonun konularını FCM arka ucundan silmek için Firebase Admin SDK'sını kullanarak ilgili uygulamayı konu aboneliğinden çıkarmanız gerekir.

Bu iki adımın avantajı, devre dışı bırakılacak eski jeton sayısı daha az olduğundan yayılmalarınızın daha hızlı gerçekleşmesidir. Ayrıca eski uygulama örnekleriniz, tekrar etkin hale geldiklerinde otomatik olarak yeniden abone olur.

Yayının başarısını ölçme

Mesaj teslimiyle ilgili en doğru fikri edinmek için mesajları yalnızca etkin olarak kullanılan uygulama örneklerine göndermeniz önerilir. Bu, özellikle yüksek sayıda aboneye sahip konulara düzenli olarak mesaj gönderiyorsanız önemlidir. Bu abonelerin bir kısmı gerçekten etkin değilse bu durumun, yayınlama istatistikleriniz üzerindeki etkisi zaman içinde belirgin hale gelebilir.

Mesajları bir jetona hedeflemeden önce şunları göz önünde bulundurun:

  • Google Analytics, BigQuery'de yakalanan veriler veya diğer izleme sinyalleri, jetonun etkin olduğunu belirtiyor mu?
  • Önceki teslimat denemeleri belirli bir süre boyunca tutarlı olarak başarısız oldu mu?
  • Kayıt jetonu geçen ay sunucularınızda güncellendi mi?
  • Android cihazlarda FCM Data API, droppedDeviceInactive nedeniyle oluşan mesaj teslim hatalarının yüksek bir yüzdesini raporluyor mu?

Teslim hakkında daha fazla bilgi için İleti teslimini anlama sayfasına göz atın.