Best practice per la gestione dei token di registrazione FCM

Se utilizzi le API FCM per creare richieste di invio a livello di codice, potresti scoprire che, nel tempo, stai sprecando risorse inviando messaggi a dispositivi inattivi con token di registrazione obsoleti. Questa situazione può influire sui dati di consegna dei messaggi riportati nella console Firebase o sui dati esportati in BigQuery, manifestandosi come un calo drammatico (ma non effettivamente valido) dei tassi di consegna. In questa guida vengono illustrate alcune misure che è possibile adottare per garantire un targeting efficiente dei messaggi e rapporti di consegna validi.

Migliori pratiche di base

Esistono alcune pratiche fondamentali da seguire in qualsiasi app che utilizza le API FCM per creare richieste di invio a livello di codice. Le principali buone pratiche sono:

  • Memorizza i token di registrazione sul tuo server. Un ruolo importante per il server è tenere traccia del token di ciascun client 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 questo timestamp a intervalli regolari.
  • Rimuovere i token archiviati che diventano obsoleti . Oltre a rimuovere i token nei casi ovvi di risposte non valide, probabilmente dovrai monitorare altri segnali che indicano che il token non è aggiornato. Questa guida illustra alcune delle opzioni per raggiungere questo obiettivo.

Recupera e archivia i token di registrazione

All'avvio iniziale della tua 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 sottoscrizioni agli argomenti per la destinazione degli argomenti.

Come indicato nelle nostre guide alla configurazione del client, la tua app dovrebbe recuperare questo token all'avvio iniziale e salvarlo sul server dell'app insieme a un timestamp . Questo timestamp deve essere implementato dal tuo codice e dai tuoi server, poiché non ti 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/reinstalla l'app
  • L'utente cancella i dati dell'app.

Esempio: archivia 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 memorizza il token di registrazione corrente 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 un token viene recuperato, viene archiviato 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()
            }
        }

Rileva risposte token non valide dal backend FCM

Assicurati di rilevare le risposte dei token non validi da FCM e rispondi eliminando dal tuo sistema tutti i token di registrazione noti per essere non validi. Con l'API HTTP v1, questi messaggi di errore potrebbero indicare che la tua richiesta di invio aveva come target token obsoleti o non validi:

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

Da notare che, poiché INVALID_ARGUMENT viene lanciato anche in caso di problemi nel payload del messaggio, segnala un token non valido solo se il payload è completamente valido. Per ulteriori informazioni, vedere Codici di errore .

Se sei sicuro che il payload del messaggio sia valido e ricevi una di queste risposte per un token mirato, è sicuro eliminare il record di questo token, poiché non sarà mai più valido. Ad esempio, per eliminare token non validi da Cloud Firestore, potresti distribuire ed eseguire 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()
        }
    });

Garantire la freschezza del token di registrazione

Determinare se un token è nuovo o obsoleto non è sempre semplice. Per coprire tutti i casi, dovresti adottare una soglia per quando consideri i token obsoleti; la nostra raccomandazione è di due mesi. È probabile che qualsiasi token più vecchio di due mesi sia un dispositivo inattivo; altrimenti un dispositivo attivo avrebbe aggiornato il proprio token.

Aggiorna i token regolarmente

Ti consigliamo di recuperare e aggiornare periodicamente tutti i token di registrazione sul tuo server. Ciò richiede di:

  • Aggiungi la logica dell'app nell'app client per recuperare il token corrente utilizzando la chiamata API appropriata (come token(completion): per piattaforme Apple o getToken() per Android) e quindi invia il token corrente al server dell'app per l'archiviazione (con timestamp ). Potrebbe trattarsi di un lavoro mensile configurato per coprire tutti i client/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 Gestione dei token di messaggistica cloud sul blog Firebase.

Qualunque sia il modello temporale che segui, assicurati di aggiornare periodicamente i token. Una frequenza di aggiornamento di una volta ogni due mesi raggiunge probabilmente un buon equilibrio tra l'impatto sulla batteria e il rilevamento di token di registrazione inattivi. Eseguendo questo aggiornamento, ti assicuri anche che qualsiasi dispositivo che diventa inattivo aggiornerà la sua registrazione quando tornerà attivo. Non vi è alcun vantaggio nell'eseguire l'aggiornamento con una frequenza superiore a quella settimanale.

Rimuovere i token di registrazione obsoleti

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

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 ai token obsoleti dagli argomenti

Un'altra considerazione è la gestione delle sottoscrizioni agli argomenti per rimuovere i token di registrazione obsoleti. Prevede due passaggi:

  1. La tua app dovrebbe iscriversi nuovamente agli argomenti una volta al mese e/o ogni volta che cambia il token di registrazione. Ciò costituisce una soluzione di autoriparazione, in cui gli abbonamenti riappaiono automaticamente quando un'app diventa di nuovo attiva.
  2. Se un'istanza dell'app rimane inattiva per 2 mesi (o per il tuo periodo di inattività), dovresti annullarne l'iscrizione agli argomenti utilizzando Firebase Admin SDK per eliminare la mappatura token/argomento dal backend FCM.

Il vantaggio di questi due passaggi è che i fanout verranno eseguiti più rapidamente poiché ci sono meno token obsoleti su cui eseguire il fanout e le istanze dell'app obsolete verranno automaticamente sottoscritte nuovamente una volta che saranno nuovamente attive.

Misurare il successo della consegna

In genere, consigliamo di indirizzare i messaggi in base alle azioni osservate o acquisite dalle istanze dell'app utilizzate attivamente. Ciò è particolarmente importante se invii regolarmente messaggi ad argomenti con un gran numero di iscritti; se una parte di questi iscritti è effettivamente inattiva, l'impatto sulle statistiche di consegna può essere significativo nel tempo.

Prima di indirizzare i messaggi a un token, considera:

  • Google Analytics, i dati acquisiti in BigQuery o altri segnali di monitoraggio indicano che il token è attivo?
  • I precedenti tentativi di consegna sono falliti costantemente per un periodo di tempo?
  • Il token di registrazione è stato aggiornato sui tuoi server negli ultimi due mesi?
  • Per i dispositivi Android, l' API FCM Data segnala un'elevata percentuale di errori di recapito dei messaggi dovuti a droppedDeviceInactive ?

Per ulteriori informazioni sulla consegna, vedere Informazioni sulla consegna dei messaggi .