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 contribuire a garantire un targeting dei messaggi efficiente e report di recapito validi.

Token di registrazione obsoleti e scaduti

I token di registrazione non validi sono token associati a dispositivi inattivi che non si sono collegati a FCM da più di 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 le suddivisioni in più argomenti per questi token non validi vengano mai eseguiti.

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 non validi raggiungono i 270 giorni di inattività, FCM li considererà token scaduti. Una volta scaduto, FCM lo contrassegna come non valido e rifiuta le relative invii. 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 codice e nei server e di aggiornarlo 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 mirate dall'API o aggiungere alle iscrizioni agli argomenti per il targeting degli argomenti.

Consigliamo vivamente alla tua app di recuperare questo token all'avvio iniziale e di salvarlo sul server dell'app insieme a un timestamp. Questo timestamp deve essere implementato dal tuo codice e dai tuoi server, in quanto non viene fornito dagli SDK di FCM.

Inoltre, è importante salvare il token sul 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 la scadenza del token esistente il giorno FCM

Esempio: memorizza token e timestamp in Cloud Firestore

Ad esempio, puoi utilizzare Cloud Firestore per archiviare i token in una raccolta chiamata fcmTokens. Ogni ID documento nella raccolta corrisponde a un ID utente e il documento memorizza il token di registrazione corrente e il relativo 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 è aggiornato o meno 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 non valido se la sua istanza di app non si è connessa da un mese. È probabile che qualsiasi token precedente a un mese appartenga a un dispositivo inattivo. Un dispositivo attivo avrebbe invece aggiornato il 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 con token non validi dal backend FCM

Assicurati di rilevare le risposte con token non validi da FCM e rispondi eliminando dal tuo sistema tutti i token di registrazione noti come non validi o scaduti. Con l'API HTTP v1, questi messaggi di errore possono 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 del messaggio sia valido e ricevi una di queste risposte per un token scelto come target, puoi eliminare in sicurezza il record di questo token, poiché non sarà 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 del token non valida solo se un token è scaduto dopo 270 giorni o se un client è stato esplicitamente annullato. Se hai bisogno di monitorare con maggiore precisione la mancata attivazione in base alle tue definizioni, puoi rimuovere in modo proattivo i token di registrazione non attivi.

Aggiornare regolarmente i token

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 trattarsi di un job mensile configurato per coprire tutti i clienti o i token.
  • Aggiungi la logica del server per aggiornare il timestamp del token a intervalli regolari, indipendentemente dal fatto che il token sia cambiato o meno.

Per un esempio di logica Android per l'aggiornamento dei token utilizzando WorkManager, consulta Gestire i token Cloud Messaging sul 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. Con questo aggiornamento, inoltre, assicurati che la registrazione di qualsiasi dispositivo che diventa inattivo venga aggiornata quando diventa di nuovo attivo. Non è vantaggioso eseguire l'aggiornamento più spesso di una volta alla settimana.

Rimuovere i token di registrazione non validi

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

Annullare l'iscrizione dei token non validi agli argomenti

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

  1. L'app deve iscriversi di nuovo agli argomenti una volta al mese e ogni volta che cambia il token di registrazione. 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 il periodo di tempo che hai definito come finestra di inattività), devi annullare la sottoscrizione agli argomenti utilizzando l'SDK Firebase Admin per eliminare la mappatura del token agli argomenti dal backend FCM.

Il vantaggio di questi due passaggi è che le suddivisioni avverranno più velocemente poiché esistono meno token non validi a cui eseguire la suddivisione e le istanze di app non valide si riabboneranno automaticamente una volta che saranno di nuovo attive.

Misurare il successo della pubblicazione

Per avere un quadro più preciso dell'invio dei messaggi, è meglio inviare i messaggi solo alle istanze dell'app in uso. Questo è particolarmente importante se invii regolarmente messaggi a argomenti con un numero elevato di iscritti. Se una parte di questi iscritti è 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 tentativi di invio precedenti non sono riusciti in modo coerente per un periodo di tempo?
  • Il token di registrazione è stato aggiornato sui tuoi server nell'ultimo mese?
  • Per i dispositivi Android, l'API FCM Data registra un'alta percentuale di errori di recapito dei messaggi a causa di droppedDeviceInactive?

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