Detecting user presence using Firebase firestore, real-time database, and cloud functions in a VueJs application.

4 min read
detecting-user-presence-using-firebase-firestore-real-time-database-and-cloud-functions-in-a-vuejs-application

Detecting user presence using Firebase firestore, real-time database, and cloud functions in a VueJs application.

Checking whether a user is online or not in real-time was a feature I struggled with recently while working on a VueJs project that used firestore as a database. You might be wondering why I couldn’t just write to my user document a boolean online property that is set to true when the user opens the app and set to false when the user closes the app. This was my first taught too but the problem with this approach is there is no way to execute the code that sets online false on the user document as the user leaves the application.

As I started looking for solutions, I found an article in the firebase docs. This article and my solution are a simplified extension of the article in the firebase docs. Please let me know if you see a problem in my solution or an improvement that can be made.

The first step is to set the online status in the real-time database when the user first enters the application. So in the mounted hook of App.vue

mounted () { if(this.loggedIn) { firebase.database().ref(`/status/${payload.userId}`).set({ online: true, lastSeen: firebase.firestore.Timestamp.now() }); firebase.database().ref(`/status/${payload.userId}`).onDisconnect().set({ online: false, lastSeen: firebase.firestore.Timestamp.now() }); } }

In the above snippet, we set online true and we set the last seen property to a firestore timestamp of now. After that, we set up the onDisconnect() method of the real-time database to set the online property to false and the lastSeen property to the time of leaving the app.

This method allows us to detect when the user leaves our app. Now we can set up a cloud function to change the user’s status in the firestore document.

const functions = require("firebase-functions"); const admin = require('firebase-admin'); admin.initializeApp(); const db = admin.firestore(); const rtdb = admin.database(); exports.onUserStatusChanged = functions.database .ref("/status/{userId}") .onUpdate((event, context) => { const uid = context.params.userId; const usersRef = db.collection('Users').doc(uid); rtdb.ref(`/status/${uid}`).on('value', function(snapshot) { usersRef.update({ online: snapshot.val().online, lastSeen: admin.firestore.FieldValue.serverTimestamp() }); return; }); });

In this function, we detect any change in the status branch using the .ref(“/status/{userId}”) reference. When we detect any change we also update the user document in the firestore document.

After this, we can set up a listener in our app to our user document wherever we want to show the user status.

mounted () { firebase.firestore().collection('Users').doc(this.userId).onSnapshot(async () => { const status = await firebase.firestore().collection('Users').doc(this.userId).get() this.userStatus = { online: status.data().online, lastSeen: moment(new Date(status.data().lastSeen.seconds*1000)).format('lll') } }) }

This will detect any change in the user document and update the online status of the user. We can use the userStatus data to show the user's status or for anything else we might need it for.

This solution has worked for me great and wanted to share it with you. If you think the code or its performance can be improved in any way please let me know. See you in the next one 😉.

Comments (0)
No comments yet