Firebase Cloud Messaging for Web using JavaScript
Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets us reliably deliver messages at no cost. Using FCM, we can send notification messages that are displayed to the user, or send data messages and determine completely what happens in the application code. It distributes messages to the client app in any of 3 ways- to single devices, to groups of devices, or to devices subscribed to topics.
At first, I found it quite challenging to work with FCM as the documentation is not clear. So, I wrote a basic guide to using FCM for Web using JavaScript.
Download source code from Github.
Add Firebase to our js file
First, we’ll need to include Firebase to a JavaScript app. In our case, it’ll be a simple javascript file. To add Firebase to our js file, we’ll need a Firebase project, the Firebase SDK, and a short snippet of initialization code that has a few details about the project. Follow Add Firebase to your app to get the config snippet.
The final structure of our project will be like this:
fcm-demo
├── firebase-messaging-sw.js
├── index.html
├── manifest.json
└── script.js
Whitelist the GCM Sender ID
Add a web app manifest that specifies the gcm_sender_id
, a hard-coded value indicating that FCM is authorized to send messages to our js file. Do not change the value of gcm_sender_id. Create a manifest.json
file and write:
{
"gcm_sender_id": "103953800507"
}
Add Firebase Messaging Service Worker
We have to create a Service Worker file that will receive and display web notifications. Create a file named firebase-messaging-sw.js
at the root of the project with the following content:
// Give the service worker access to Firebase Messaging.
importScripts('https://www.gstatic.com/firebasejs/4.9.1/firebase-app.js')
importScripts('https://www.gstatic.com/firebasejs/4.9.1/firebase-messaging.js')
// Initialize the Firebase app in the service worker by passing in the messagingSenderId.
var config = {
messagingSenderId: "your_messaging_sender_id"
};
firebase.initializeApp(config);
// Retrieve an instance of Firebase Data Messaging so that it can handle background messages.
const messaging = firebase.messaging()
messaging.setBackgroundMessageHandler(function(payload) {
const notificationTitle = 'Data Message Title';
const notificationOptions = {
body: 'Data Message body',
icon: 'alarm.png'
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
Request Permissions and Get FCM Device Tokens
Create another file called script.js
and add:
// Initialize the Firebase app by passing in the messagingSenderId
var config = {
messagingSenderId: "your_messaging_sender_id"
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
navigator.serviceWorker.register('firebase-messaging-sw.js')
.then(function (registration) {
messaging.useServiceWorker(registration);
// Request for permission
messaging.requestPermission()
.then(function() {
console.log('Notification permission granted.');
// TODO(developer): Retrieve an Instance ID token for use with FCM.
messaging.getToken()
.then(function(currentToken) {
if (currentToken) {
console.log('Token: ' + currentToken)
sendTokenToServer(currentToken);
} else {
console.log('No Instance ID token available. Request permission to generate one.');
setTokenSentToServer(false);
}
})
.catch(function(err) {
console.log('An error occurred while retrieving token. ', err);
setTokenSentToServer(false);
});
})
.catch(function(err) {
console.log('Unable to get permission to notify.', err);
});
});
// Handle incoming messages
messaging.onMessage(function(payload) {
console.log("Notification received: ", payload);
toastr["info"](payload.notification.body, payload.notification.title);
});
// Callback fired if Instance ID token is updated.
messaging.onTokenRefresh(function() {
messaging.getToken()
.then(function(refreshedToken) {
console.log('Token refreshed.');
// Indicate that the new Instance ID token has not yet been sent
// to the app server.
setTokenSentToServer(false);
// Send Instance ID token to app server.
sendTokenToServer(refreshedToken);
})
.catch(function(err) {
console.log('Unable to retrieve refreshed token ', err);
});
});
// Send the Instance ID token your application server, so that it can:
// - send messages back to this app
// - subscribe/unsubscribe the token from topics
function sendTokenToServer(currentToken) {
if (!isTokenSentToServer()) {
console.log('Sending token to server...');
// TODO(developer): Send the current token to your server.
setTokenSentToServer(true);
} else {
console.log('Token already sent to server so won\'t send it again ' +
'unless it changes');
}
}
function isTokenSentToServer() {
return window.localStorage.getItem('sentToServer') == 1;
}
function setTokenSentToServer(sent) {
window.localStorage.setItem('sentToServer', sent ? 1 : 0);
}
Finally Combine All Files
In index.html
file:
<!-- <!DOCTYPE html> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="manifest" href="manifest.json">
<link rel="shortcut icon" href="favicon.ico">
<title>FCM Demo</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css">
</head>
<body>
<h1 style="text-align:center;">
Firebase Cloud Messaging Demo
</h1>
<script src="http://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.9.1/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.9.1/firebase-messaging.js"></script>
<script src="script.js"></script>
</body>
</html>
Run Application
Firebase will not allow running the index.html
file directly. So, I will be running the index.html
file using Python server. Open terminal, navigate to the project directory and run:
python -m SimpleHTTPServer 8000
Open http://localhost:8000
in the browser. A popup will appear to ask for permission to show notifications in the browser. Click Allow
and if everything is fine up to this point, a client token will be generated.
Send Messages
To send a notification, we also need Firebase app’s Server key along with device token. To get it open Firebase app’s Firebase Console > Project Settings > Cloud Messaging
and copy the Server Key.
To send a notification, send the following HTTP request using cURL in the command line:
curl -X POST -H "Authorization: key=<your_server_key>" -H "Content-Type: application/json" -d '{
"notification": {
"title": "New Article",
"body": "Firebase Cloud Messaging for Web using JavaScript",
"icon": "alarm.png",
"click_action": "http://rakibul.net/fcm-web-js"
},
"to": "<your_client_token>"
}' "https://fcm.googleapis.com/fcm/send"
Send Messages to Topics
FCM topic messaging allows sending a message to multiple devices that have opted into a particular topic. We can compose topic messages as needed, and FCM handles routing and delivering the message reliably to the right devices.
Subscribe the Client App to a Topic
Given a registration token and a topic name, we can add the token to the topic using the Google Instance ID server API:
curl -X POST -H "Authorization: key=<your_server_key>" -H "Content-Type: application/json" -H "Content-Length: 0" "https://iid.googleapis.com/iid/v1/<your_instance_token>/rel/topics/<topic_name>"
Subscribe Multiple Client Apps to a Topic
Using the Instance ID service’s batch methods, we can perform batch subscription of app instances:
curl -X POST -H "Authorization: key=<your_server_key>" -H "Content-Type: application/json" -d '{
"to": "/topics/<topic_name>",
"registration_tokens": ["<your_client_token1>", "<your_client_token2>", ...]
}' "https://iid.googleapis.com/iid/v1:batchAdd"
Unsubscribe Multiple Client Apps from a Topic
We can also perform bulk removal of app instances to an FCM topic. Unfortunately, Google Instance ID server API does not provide functionality for simple app unsubscription from a topic. But we can pass a single client token to this API to unsubscribe the single client.
curl -X POST -H "Authorization: key=<your_server_key>" -H "Content-Type: application/json" -d '{
"to": "/topics/<topic_name>",
"registration_tokens": ["<your_client_token1>", "<your_client_token2>", ...]
}' "https://iid.googleapis.com/iid/v1:batchRemove"
Message Types
FCM can send two types of messages to clients:
- Notification messages: Sometimes thought of as “display messages.” These are handled by the FCM SDK automatically.
- Data messages: Handled by the client app. Maximum payload for both message types is 4KB.
Send Notification Messages to a Topic
Notification messages contain a predefined set of user-visible keys. To send messages to a specific topic:
curl -X POST -H "Authorization: key=<your_server_key>" -H "Content-Type: application/json" -d '{
"notification": {
"title": "New Article",
"body": "Firebase Cloud Messaging for Web using JavaScript",
"icon": "alarm.png",
"click_action": "http://rakibul.net/fcm-web-js"
},
"to": "/topics/<topic_name>"
}' "https://fcm.googleapis.com/fcm/send"
Send Data Messages to a Topic
Data messages contain only your user-defined custom key-value pairs. To send messages to a specific topic:
curl -X POST -H "Authorization: key=<your_server_key>" -H "Content-Type: application/json" -d '{
"data": {
"title": "New Article",
"body": "Firebase Cloud Messaging for Web using JavaScript",
"icon": "alarm.png",
"click_action": "http://rakibul.net/fcm-web-js"
},
"to": "/topics/<topic_name>"
}' "https://fcm.googleapis.com/fcm/send"
Also Notification messages can contain an optional data payload:
curl -X POST -H "Authorization: key=<your_server_key>" -H "Content-Type: application/json" -d '{
"notification": {
"title": "New Article",
"body": "Firebase Cloud Messaging for Web using JavaScript",
"icon": "alarm.png",
"click_action": "http://rakibul.net/fcm-web-js"
},
"data": {
"title": "rakibul.net",
"body": "This is a background notification"
},
"to": "/topics/<topic_name>"
}' "https://fcm.googleapis.com/fcm/send"
Get Information about Client App
To get information about an app instance, call the Instance ID service at this endpoint, providing the app instance’s token as shown:
curl -X GET -H "Authorization: key=<your_server_key>" "https://iid.googleapis.com/iid/v1/<your_client_token>?details=true"
Visit About FCM Messages to learn more about FCM messages.
Visit Topic Messaging on Web/JavaScript to learn more about topic messaging.
Visit Server Reference to learn more about server reference API.