Mejores prácticas para la gestión de tokens de registro de FCM

Si utiliza las API de FCM para crear solicitudes de envío mediante programación, es posible que, con el tiempo, esté desperdiciando recursos al enviar mensajes a dispositivos inactivos con tokens de registro obsoletos. Esta situación puede afectar los datos de entrega de mensajes informados en Firebase console o los datos exportados a BigQuery, lo que se manifiesta como una caída dramática (pero no válida) en las tasas de entrega. Esta guía analiza algunas medidas que puede tomar para ayudar a garantizar una segmentación eficiente de los mensajes y unos informes de entrega válidos.

Tokens de registro obsoletos y caducados

Los tokens de registro obsoletos son tokens asociados con dispositivos inactivos que no se han conectado a FCM durante más de un mes. A medida que pasa el tiempo, es cada vez menos probable que el dispositivo vuelva a conectarse a FCM. Es poco probable que se entreguen los envíos de mensajes y la distribución de temas para estos tokens obsoletos.

Hay varias razones por las que un token puede volverse obsoleto. Por ejemplo, el dispositivo al que está asociado el token puede perderse, destruirse o guardarse y olvidarse.

Cuando los tokens obsoletos alcancen los 270 días de inactividad, FCM los considerará tokens caducados . Una vez que un token caduca, FCM lo marca como no válido y rechaza los envíos. Sin embargo, FCM emite un nuevo token para la instancia de la aplicación en el raro caso de que el dispositivo se conecte nuevamente y se abra la aplicación.

Mejores prácticas básicas

Existen algunas prácticas fundamentales que debe seguir en cualquier aplicación que utilice API de FCM para crear solicitudes de envío mediante programación. Las principales mejores prácticas son:

  • Recupere tokens de registro de FCM y guárdelos en su servidor. Una función importante del servidor es realizar un seguimiento del token de cada cliente y mantener una lista actualizada de los tokens activos. Recomendamos encarecidamente implementar una marca de tiempo simbólica en su código y en sus servidores, y actualizar esta marca de tiempo a intervalos regulares.
  • Mantenga la frescura de los tokens y elimine los tokens obsoletos. Además de eliminar los tokens que FCM ya no considera válidos, es posible que desee monitorear otras señales de que los tokens se han vuelto obsoletos y eliminarlos de manera proactiva. Esta guía analiza algunas de sus opciones para lograrlo.

Recuperar y almacenar tokens de registro

En el inicio inicial de su aplicación, el SDK de FCM genera un token de registro para la instancia de la aplicación cliente. Este es el token que debe incluir en las solicitudes de envío dirigidas desde la API o agregarlo a las suscripciones a temas para orientar temas.

Recomendamos encarecidamente que su aplicación recupere este token durante el inicio inicial y lo guarde en su servidor de aplicaciones junto con una marca de tiempo . Esta marca de tiempo debe ser implementada por su código y sus servidores, ya que los SDK de FCM no la proporcionan.

Además, es importante guardar el token en el servidor y actualizar la marca de tiempo cada vez que cambie, como cuando:

  • La aplicación se restaura en un nuevo dispositivo.
  • El usuario desinstala o reinstala la aplicación.
  • El usuario borra los datos de la aplicación.
  • La aplicación vuelve a estar activa después de que FCM haya caducado su token existente

Ejemplo: almacenar tokens y marcas de tiempo en Cloud Firestore

Por ejemplo, puedes usar Cloud Firestore para almacenar tokens en una colección llamada fcmTokens . Cada ID de documento de la colección corresponde a un ID de usuario y el documento almacena el token de registro actual y su marca de tiempo actualizada por última vez. Utilice la función set como se muestra en este ejemplo de 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)
    }

Cada vez que se recupera un token, se almacena en Cloud Firestore llamando 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()
            }
        }

Mantener la frescura de los tokens y eliminar los tokens obsoletos

Determinar si un token está nuevo o obsoleto no siempre es sencillo. Para cubrir todos los casos, debe adoptar un umbral para cuando considere que los tokens están obsoletos. De forma predeterminada, FCM considera que un token está obsoleto si la instancia de su aplicación no se ha conectado durante un mes. Es probable que cualquier token que tenga más de un mes sea un dispositivo inactivo; De lo contrario, un dispositivo activo habría actualizado su token.

Dependiendo de su caso de uso, un mes puede ser demasiado corto o demasiado largo, por lo que depende de usted determinar los criterios que funcionen para usted.

Detectar respuestas de token no válidas desde el backend de FCM

Asegúrese de detectar respuestas de tokens no válidos de FCM y responda eliminando de su sistema cualquier token de registro que se sepa que no es válido o que ha caducado. Con la API HTTP v1, estos mensajes de error pueden indicar que su solicitud de envío tenía como objetivo tokens no válidos o caducados:

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

Si está seguro de que la carga útil del mensaje es válida y recibe cualquiera de estas respuestas para un token específico, es seguro eliminar su registro de este token, ya que nunca volverá a ser válido. Por ejemplo, para eliminar tokens no válidos de Cloud Firestore, puedes implementar y ejecutar una función como la siguiente:

    // 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 solo devolverá una respuesta de token no válida si un token expiró después de 270 días o si un cliente se dio de baja explícitamente. Si necesita realizar un seguimiento más preciso del estado obsoleto según sus propias definiciones, puede eliminar de forma proactiva los tokens de registro obsoletos .

Actualizar tokens periódicamente

Le recomendamos que recupere y actualice periódicamente todos los tokens de registro en su servidor. Esto requiere que:

  • Agregue lógica de aplicación en su aplicación cliente para recuperar el token actual usando la llamada API adecuada (como token(completion): para plataformas Apple o getToken() para Android) y luego envíe el token actual a su servidor de aplicaciones para su almacenamiento (con un marca de tiempo). Este podría ser un trabajo mensual configurado para cubrir a todos los clientes o tokens.
  • Agregue lógica de servidor para actualizar la marca de tiempo del token a intervalos regulares, independientemente de si el token ha cambiado o no.

Para ver un ejemplo de lógica de Android para actualizar tokens mediante WorkManager , consulte Administración de tokens de mensajería en la nube en el blog de Firebase.

Cualquiera que sea el patrón de tiempo que sigas, asegúrate de actualizar los tokens periódicamente. Una frecuencia de actualización de una vez al mes logra un buen equilibrio entre el impacto de la batería y la detección de tokens de registro inactivos. Al realizar esta actualización, también se asegura de que cualquier dispositivo que quede inactivo actualizará su registro cuando vuelva a estar activo. No hay ningún beneficio en realizar la actualización con más frecuencia que semanalmente.

Eliminar tokens de registro obsoletos

Antes de enviar mensajes a un dispositivo, asegúrese de que la marca de tiempo del token de registro del dispositivo esté dentro del período de obsolescencia. Por ejemplo, podría implementar Cloud Functions para Firebase para ejecutar una verificación diaria para garantizar que la marca de tiempo esté dentro de un período de ventana de obsolescencia definido, como const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; y luego eliminar tokens obsoletos:

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

Darse de baja de tokens obsoletos de temas

Si utiliza temas, es posible que también desee cancelar el registro de tokens obsoletos de los temas a los que están suscritos. Esto implica dos pasos:

  1. Su aplicación debe volver a suscribirse a temas una vez al mes y cada vez que cambie el token de registro. Esto forma una solución de autorreparación, donde las suscripciones reaparecen automáticamente cuando una aplicación vuelve a estar activa.
  2. Si una instancia de aplicación está inactiva durante un mes (o su propia ventana de obsolescencia), debe cancelar su suscripción a los temas usando el SDK de administrador de Firebase para eliminar la asignación de token a tema desde el backend de FCM.

El beneficio de estos dos pasos es que sus distribuciones se producirán más rápido, ya que hay menos tokens obsoletos para distribuir, y las instancias de su aplicación obsoleta se volverán a suscribir automáticamente una vez que estén activas nuevamente.

Medir el éxito de la entrega

Para obtener una imagen más precisa de la entrega de mensajes, es mejor enviar mensajes únicamente a instancias de aplicaciones utilizadas activamente. Esto es especialmente importante si envía mensajes regularmente a temas con una gran cantidad de suscriptores; Si una parte de esos suscriptores están realmente inactivos, el impacto en sus estadísticas de entrega puede ser significativo con el tiempo.

Antes de dirigir mensajes a un token, considere:

  • ¿Google Analytics, los datos capturados en BigQuery u otras señales de seguimiento indican que el token está activo?
  • ¿Los intentos de entrega anteriores han fallado constantemente durante un período de tiempo?
  • ¿Se actualizó el token de registro en sus servidores durante el último mes?
  • Para dispositivos Android, ¿la API de datos de FCM informa un alto porcentaje de fallas en la entrega de mensajes debido a droppedDeviceInactive ?

Para obtener más información sobre la entrega, consulte Comprender la entrega de mensajes .