January 20, 2020

Add Push Notifications to your jQuery chat app

Wajahat Karim

In a previous tutorial, I wrote about how to code a ridiculously good-looking jQuery chat room. Rather than build an overly-simple chat app, I challenged us to include advanced features like message history. In this tutorial, we’ll take things one step further by introducing chat push notifications.

Above, the app shows notifications when the window is in the foreground. I wanted to include foreground notifications for demo purposes. We will also leverage a service worker to render background notifications, even when the page isn’t open.

Because this tutorial picks up where the last one ends, it’s up to you if you’d like to follow on from the beginning or clone the repository and continue from there.

Getting started

I created a starter template based on the previous tutorial and uploaded it to this repository. Go ahead and download it to your local machine as shown here:

git clone https://github.com/cometchat-pro-tutorials/jquery-push-starter.git

Once you are done, open the project in your editor of choice. This project contains a couple of files, image assets, and directories that hold the logic to make the app function as a basic jQuery chat application. Here is a quick overview of the relevant files and directories:

  • index.html: This is the main file for the application. It is sometimes referred to as the entry point. It contains the simple HTML elements for the chat application and also the links to the SDK that will be used to power the application.
  • css/style.css: stylesheet to add more custom styles, which includes colors and other user interface enhancement for the application
  • assets: It holds the images for the chat app
  • js: This directory houses two script files chatService.js and scripts.js. These files contain the required logic to authenticate users on CometChat, participate in a chat session and also retrieve older messages amongst other things.

Now that you have a starter template and have a full understanding of the existing folder structure, you can now proceed to make use of CometChat JavaScript SDK to make the application work, but first, you need to create an account.

Creating CometChat account

If you followed the previous tutorial, you’ll know all about CometChat. Otherwise, here is a quick introduction.

CometChat is a chat platform, which makes it trivial to add voice, video, and text chat to your applications. In our case, we code the front-end then connect to CometChat to send and receive messages in real-time, store message history, and more. We’ll also be leveraging the CometChat push notifications extension to connect with Firebase Cloud Messaging.

To connect to CometChat, you’ll need to create a free account then an app. This will take a few seconds. Once it’s done, click the Explore button to view your newly-created application. Copy and save both your app ID and full access key from the API Keys menu:

Add CometChat credential globally
Back in the code, navigate to ./js/scripts.js file and add your CometChat credentials as a global variable as shown here:

// js/scripts

$(document).ready(function() {

// Global variables
window.COMETCHAT_APP_ID = 'YOUR_COMMETCHAT_APP_ID';
window.COMETCHAT_API_KEY = 'YOUR_COMMETCHAT_API_KEY';
...

});

This will make it so easy to reference and make use of these variables within your application. Replace the YOUR_COMMETCHAT_APP_ID and YOUR_COMMETCHAT_API_KEY placeholder with the appropriate credentials as obtained from your CometChat dashboard.

To be sure that the downloaded starter template works like a group chat application, for now, go ahead and run the index.html file in a browser. Open from two different tabs and log in on each tab using the following test users; superhero1, superhero2, superhero3 from CometChat:

If your app worked as shown above, then you are on track and ready to include the push notifications feature. Otherwise, kindly check your code again and ensure that your CometChat credentials are filled appropriately.

Setting up Firebase project

Firebase is a platform that provides lots of services for both web and mobile applications and facilitates the quick development of apps without managing infrastructure. To enable push notifications for our chat application, we will use a service called Firebase Cloud Messaging (FCM), which will enable us to send messages to any device using HTTP requests.

To begin, you need to have a Firebase account and add a new project within it. Click here to create a new Firebase account, if you don’t have one already. Next, from your Firebase console, create a new project by clicking on the Create a project button:

Firebase console

You will be prompted to enter your project name. Once you are done, click on the </> symbol to add a new web app to your project:

Firebase app page

Enter a name for your app and register it. You will see a page similar to the one shown below afterward:

Firebase config

Copy and save the Firebase config snippet somewhere, as we will need this later.

If you have an existing Firebase project for an application that you wish to integrate CometChat, you can easily select the project and download the config file instead of creating another.

Enabling CometChat push notifications extension

Now that we have created a Firebase project and a web app within it, you need to go back to your CometChat dashboard and enable the push notification extension for the app that you added on CometChat earlier. Click on Extensions from the left side menu:

CometChat dashboard

Then from the list of all extensions, click on the Add Extension button on the Push Notification row:

CometChat enable push notification extension

Add FCM Server key
To complete the process of enabling the Push notification extension on CometChat, a Firebase Cloud Messaging server key is required. Head back to your Firebase console and click on Project Settings. Then select the Cloud Messaging tab to obtain it as shown here:

Firebase settings page

Copy the FCM Server Key and from the CometChat dashboard, click on Actions → Settings for the installed extension:

CometChat installed extensions

Paste the Server key in the dialog box and give your notification a title:

Push notification page

Now, that you have created a Firebase project, created a web app, enable the push notifications extension on CometChat and added the FCM server key, your CometChat application is almost set to start communicating properly with Firebase. To complete the process, we will initialize and configure Firebase messaging within the chat application in the next section.

Add and configure Firebase messaging in your application

Here, you will configure push notifications by creating a new file named pushNotification.js within the js folder. Now open this newly created file and use the following content for it:

// /js/pushNotification.js

const pushNotificationService = function() {
let firebaseUid = '';
return {
initializeFirebase: function() {
if (firebase.messaging.isSupported()) {
const firebaseConfig = {
apiKey: "YOUR_FIREBASE_APIKEY",
authDomain: "YOUR_FIREBASE_DOMAIN",
databaseURL: "FIREBASE_DATABASE_URL",
projectId: "FIREBASE_PROJECT_ID",
storageBucket: "STORAGE_BUCKET",
messagingSenderId: "FIREBASE_MESSAGE_SENDER_ID",
appId: "FIREBASE_APP_ID",
};

firebase.initializeApp(firebaseConfig);

const messaging = firebase.messaging();
messaging
.requestPermission()
.then(() => {
console.log("Have Permission");
return messaging.getToken();
})
.then(token => {
var userType = 'group';
var UID = "supergroup";
var appId = COMETCHAT_APP_ID;

var topic = appId + '_' + userType + '_' + UID;

var url = `https://ext-push-notifications.cometchat.com/fcmtokens/${token}/topics/${topic}`;

fetch(url, {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/json',
}),
body: JSON.stringify({appId: appId}),
})
.then(response => {
if (response.status < 200 || response.status >= 400) {
console.log(
'Error subscribing to topic: ' +
response.status +
' - ' +
response.text()
);
}
})
.catch(error => {
console.error(error);
});
})
.catch(error => {
if (error.code === 'messaging/permission-blocked') {
console.log('Please Unblock Notification Request Manually');
} else {
console.log('Error Occurred', error);
}
});
}
},
}
}();

First, you imported Firebase and created a firebaseConfig() object to hold the configuration details of the app created on Firebase console. Kindly replace all the placeholders with the appropriate credentials obtained from the Firebase config snippet earlier.

Next, because it is important to seek the consent of your app users before displaying a push notification, you used the messaging.requestPermission() function to ask a user for permission to send push notification from your chat app, once granted, you retrieved the token by using the messaging.getToken() function. If permission is denied, the Firebase console messaging registration token requests will result in an error.

You then proceeded to use the retrieved token to subscribe to a topic. Topics in Firebase cloud messaging allows messages to be sent to multiple devices that have subscribed to such a particular topic. You can create a random topic and allow any other devices to opt-in for it and they will receive notifications based on that. You can read more about this feature here. At the moment because of the subscription, your browser will receive a message object each time a chat message is being sent to the chat room.
Lastly, add the following code just after the .catch() method:

const pushNotificationService = function() {
let firebaseUid = '';
return {
initializeFirebase: function() {
if (firebase.messaging.isSupported()) {

...
messaging.onMessage(function(payload) {
var sender = JSON.parse(payload.data.message);
console.log('Receiving foreground message', JSON.parse(payload.data.message));
// Customize notification here

if (sender.data.entities.sender.entity.uid !== firebaseUid) {
var notificationTitle = 'CometChat JQuery Push Notification';
var notificationOptions = {
body: payload.data.alert,
icon: sender.data.entities.sender.entity.avatar,
};

var notification = new Notification(notificationTitle, notificationOptions);
notification.onclick = function(event) {
notification.close();
console.log(event);
};
}
});

}
},
}
}();

This will ensure that all the message object sent to the browser as a result of the topic subscribed to, will be handled properly. Here, you used the Notification API to create a new push notification. Before creating the notification payload, we checked to ensure that the sender is not the currently logged in user. This will enable us to control when to display push notifications. The rationale behind this ensures that a user should not receive push notifications for his message.

To track the details of the currently logged in user, add the following code within ./src/pushNotification.js:

const pushNotificationService = function() {
let firebaseUid = '';
return {
...
updateFirebaseLoggedInUser: function(uid) {
if (firebase.messaging.isSupported()) {
firebaseUid = uid;
}
}
}
}();

Now you can invoke the newly added method immediately you obtained the details of the logged-in user. To achieve that, open the chatService.js, locate the getLoggedInUser() method and update it as shown here:

const chatService = function() {
...
return {
...
getLoggedInUser: function() {
CometChat.getLoggedinUser().then(
user => {
...
// update firebase logged in user
pushNotificationService.updateFirebaseLoggedInUser(user.uid);
...
},
error => {
console.log(error);
}
)
},
...
}
}();

Initialize Firebase instance

Navigate back to the script file and initialize firebase:

$(document).ready(function() {
...
// Initialize firebase
pushNotificationService.initializeFirebase(); // add this line
...
});

Here, you referenced and invoked the initializeFirebase() function from pushNotification.js. This will ensure that a new Firebase instance will be initialized whenever the application is running.

Receive notifications in the background using the service worker

To keep receiving notifications even when your application is in the background, you will need to add a service worker. This is a script that your browser will keep running in the background, thereby ensuring that you keep receiving push notifications. By default, when you start Firebase, it looks for a file called firebase-messaging-sw.js in a location where your files are served.

Create a new file named firebase-messaging-sw.js within the root of the application and paste the following content in it:

// /firebase-messaging-sw.js

importScripts("https://www.gstatic.com/firebasejs/6.4.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/6.4.0/firebase-messaging.js");

if (firebase.messaging.isSupported()) {
var firebaseConfig = {
messagingSenderId: "YOUR_FIREBASE_MESSAGING_SENDER_ID"
};

firebase.initializeApp(firebaseConfig);

const messaging = firebase.messaging();

messaging.setBackgroundMessageHandler(function(payload) {
console.log(' Received background message ', payload);

var sender = JSON.parse(payload.data.message);
var notificationTitle = 'CometChat JQuery Push Notification';
var notificationOptions = {
body: payload.data.alert,
icon: sender.data.entities.sender.entity.avatar,
};

return self.registration.showNotification(
notificationTitle,
notificationOptions
);
});

self.addEventListener('notificationclick', function(event) {
event.notification.close();
//handle click event onClick on Web Push Notification
});
}

The messaging.setBackgroundMessageHandler() function will listened and received messages as payload and use it to create a push notification. Replace the YOUR_FIREBASE_MESSAGING_SENDER_ID placeholder with your Firebase app messagingSenderId.

Finally, update the index.html file by including Firebase SDK and the created pushNotifications script immediately after jQuery scripts as shown below:

// /index.html

<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
...
<!-- Firebase SDK -->
<script src="https://www.gstatic.com/firebasejs/6.4.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/6.4.0/firebase-messaging.js"></script>

<!-- Push notifications scripts -->
<script src="js/pushNotification.js"></script>
...
</body>
</html>

Testing the application.

Open the index.html again or refresh the page if you’re tab hoarder! You’ll see this:

Next, open the application on two different browsers and log in as separate users. You can log in with any two of the test users provided by CometChat for every new application: superhero1, superhero2, superhero3 as shown here. Send a message to continue a chat session and you will receive push notifications:

Conclusion

In this tutorial, you have successfully learned how to add push notifications feature to an existing jQuery chat application in no time. You start by downloading an existing code from the previous tutorial which contains the required amount of code for a functional group chat application powered by CometChat. You then proceeded to leverage CometChat and Firebase Messaging Service to add push notifications features.

This will increase and enhance user interactivity for your application. The complete source code for this application built here can be found on GitHub. Feel free to download it and add more features as you deem fit.