Best practice per la gestione dei token di registrazione FCM

Se utilizzi le API FCM per creare richieste di invio in modo programmatico, potresti scoprire che, nel tempo, stai sprecando risorse inviando messaggi a dispositivi inattivi con token di registrazione non aggiornati. Questa situazione può influire sui dati di recapito dei messaggi registrati nella Console Firebase o sui dati esportati in BigQuery, presentandosi come un calo significativo (ma non effettivamente valido) dei tassi di recapito. Questa guida illustra alcune misure che puoi adottare per garantire un targeting dei messaggi efficiente e report sulla pubblicazione validi.

Token di registrazione inattivi e scaduti

I token di registrazione inattivi sono token associati a dispositivi inattivi che non sono stati connessi a FCM da oltre un mese. Con il passare del tempo, è sempre meno probabile che il dispositivo si connetta di nuovo a FCM. È improbabile che gli invii di messaggi e i fanout degli argomenti per questi token inattivi vengano mai recapitati.

Esistono diversi motivi per cui un token può diventare inattivo. Ad esempio, il dispositivo a cui è associato il token potrebbe essere smarrito, distrutto o messo in un ripostiglio e dimenticato.

Quando i token inattivi raggiungono 270 giorni di inattività, FCM li considera token scaduti. Quando un token scade, FCM lo contrassegna come non valido e rifiuta l'invio. Tuttavia, FCM emette un nuovo token per l'istanza dell'app nel raro caso in cui il dispositivo si connetta di nuovo e l'app venga aperta.

Best practice di base

Esistono alcune best practice fondamentali da seguire in qualsiasi app che utilizzi le API FCM per creare richieste di invio in modo programmatico. Le principali best practice sono:

  • Recupero i token di registrazione da FCM e li memorizza sul tuo server. Un ruolo importante del server è tenere traccia del token di ogni cliente e mantenere un elenco aggiornato dei token attivi. Ti consigliamo vivamente di implementare un timestamp del token nel tuo codice e nei tuoi server e di aggiornare il timestamp a intervalli regolari.
  • Mantieni aggiornati i token e rimuovi quelli non validi. Oltre a rimuovere i token che FCM non considera più validi, ti consigliamo di monitorare altri indicatori che indicano che i token non sono più aggiornati e rimuoverli in modo proattivo. Questa guida illustra alcune delle opzioni a tua disposizione per raggiungere questo obiettivo.

Recuperare e memorizzare i token di registrazione

All'avvio iniziale dell'app, l'SDK FCM genera un token di registrazione per l'istanza dell'app client. Questo è il token che devi includere nelle richieste di invio target dell'API o aggiungere alle sottoscrizioni agli argomenti per il targeting degli argomenti.

Ti consigliamo vivamente di fare in modo che l'app recuperi questo token all'avvio iniziale e lo salvi sul server dell'app insieme a un timestamp. Questo timestamp deve essere implementato dal codice e dai server, poiché non viene fornito dagli SDK FCM.

Inoltre, è importante salvare il token nel server e aggiornare il timestamp ogni volta che cambia, ad esempio quando:

  • L'app viene ripristinata su un nuovo dispositivo
  • L'utente disinstalla o reinstalla l'app.
  • L'utente cancella i dati dell'app
  • L'app diventa di nuovo attiva dopo che il token esistente di FCM è scaduto

Esempio: memorizza token e timestamp in Cloud Firestore

Ad esempio, potresti utilizzare Cloud Firestore per archiviare i token in una raccolta denominata fcmTokens. Ogni ID documento nella raccolta corrisponde a un ID utente e il documento archivia il token di registrazione attuale e il timestamp dell'ultimo aggiornamento. Utilizza la funzione set come mostrato in questo esempio di 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)
    }

Ogni volta che viene recuperato un token, viene memorizzato in Cloud Firestore chiamando 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()
            }
        }

Mantenere aggiornati i token e rimuoverli se non sono più validi

Determinare se un token è nuovo o inattivo non è sempre facile. Per coprire tutti i casi, devi adottare una soglia per determinare quando considerare i token obsoleti. Per impostazione predefinita, FCM considera un token inattivo se la relativa istanza dell'app non si connette da un mese. È probabile che i token più vecchi di un mese sia un dispositivo inattivo; in caso contrario, un dispositivo attivo avrebbe aggiornato il proprio token.

A seconda del caso d'uso, un mese potrebbe essere troppo breve o troppo lungo, quindi sta a te determinare i criteri più adatti alle tue esigenze.

Rileva le risposte di token non valide dal backend FCM

Assicurati di rilevare risposte non valide relative ai token da parte di FCM e rispondi eliminando dal sistema i token di registrazione noti come non validi o scaduti. Con l'API HTTP v1, questi messaggi di errore potrebbero indicare che la richiesta di invio ha come target token non validi o scaduti:

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

Se hai la certezza che il payload dei messaggi sia valido e ricevi una di queste risposte per un token scelto come target, puoi eliminare il record di questo token, poiché non sarà mai più valido. Ad esempio, per eliminare i token non validi da Cloud Firestore, puoi eseguire il deployment e l'esecuzione di una funzione come la seguente:

    // 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 restituirà una risposta relativa al token non valida solo se il token è scaduto dopo 270 giorni o se un client ha annullato la registrazione in modo esplicito. Se hai bisogno di monitorare in modo più accurato l'inattività in base alle tue definizioni, puoi rimuovere i token di registrazione inattivi in modo proattivo.

Aggiorna i token regolarmente

Ti consigliamo di recuperare e aggiornare periodicamente tutti i token di registrazione sul tuo server. Per farlo, devi:

  • Aggiungi la logica dell'app nell'app client per recuperare il token corrente utilizzando la chiamata API appropriata (ad esempio token(completion): per le piattaforme Apple o getToken() per Android) e poi invia il token corrente al server dell'app per l'archiviazione (con un timestamp). Potrebbe essere un job mensile configurato per coprire tutti i client o i token.
  • Aggiungi la logica del server per aggiornare il timestamp del token a intervalli regolari, indipendentemente dal fatto che il token sia stato modificato o meno.

Per un esempio della logica Android per l'aggiornamento dei token utilizzando WorkManager, vedi Gestione dei token di Cloud Messaging nel blog di Firebase.

Qualunque sia il pattern di tempo che segui, assicurati di aggiornare periodicamente i token. Una frequenza di aggiornamento mensile offre un buon equilibrio tra l'impatto sulla batteria e il rilevamento dei token di registrazione inattivi. Eseguendo questo aggiornamento, ti assicurerai inoltre che i dispositivi inattivi aggiornino la relativa registrazione quando saranno di nuovo attivi. Non è vantaggioso eseguire l'aggiornamento più spesso di una volta alla settimana.

Rimuovi i token di registrazione inattivi

Prima di inviare messaggi a un dispositivo, assicurati che il timestamp del token di registrazione del dispositivo rientri nel periodo di tempo della finestra di inattività. Ad esempio, potresti implementare Cloud Functions for Firebase per eseguire un controllo giornaliero per assicurarti che il timestamp rientri in un periodo di tempo definito, ad esempio const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;, e poi rimuovere i token non validi:

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

Annulla l'iscrizione dei token obsoleti agli argomenti

Se utilizzi gli argomenti, ti consigliamo di annullare la registrazione dei token non validi dagli argomenti a cui sono iscritti. Ciò prevede due passaggi:

  1. L'app deve abbonarsi di nuovo agli argomenti una volta al mese e ogni volta che il token di registrazione cambia. Si tratta di una soluzione di riparazione automatica in cui gli abbonamenti vengono visualizzati di nuovo automaticamente quando un'app diventa di nuovo attiva.
  2. Se un'istanza dell'app è inattiva per un mese (o per la tua finestra di inattività), devi annullare l'iscrizione agli argomenti utilizzando l'SDK Admin Firebase per eliminare il token alla mappatura degli argomenti dal backend FCM.

Il vantaggio di questi due passaggi è che i fanout saranno più veloci perché ci sono meno token inattivi per il fan-out e le istanze di app inattive si riabboneranno automaticamente una volta riattivate.

Misura il successo delle consegne

Per avere un quadro più preciso della consegna dei messaggi, è preferibile inviare i messaggi solo a istanze di app utilizzate attivamente. Ciò è particolarmente importante se invii regolarmente messaggi ad argomenti con un numero elevato di sottoscrittori. Se una parte di questi sottoscrittori è effettivamente inattiva, l'impatto sulle statistiche di recapito può essere significativo nel tempo.

Prima di scegliere come target dei messaggi un token, valuta quanto segue:

  • Google Analytics, i dati acquisiti in BigQuery o altri indicatori di monitoraggio indicano che il token è attivo?
  • I precedenti tentativi di consegna non sono andati a buon fine regolarmente in un determinato periodo di tempo?
  • Il token di registrazione è stato aggiornato sui tuoi server nell'ultimo mese?
  • Per i dispositivi Android, l'API FCM Data segnala un'elevata percentuale di errori di recapito dei messaggi dovuti a droppedDeviceInactive?

Per ulteriori informazioni sull'invio, consulta Informazioni sull'invio dei messaggi.