How to Send Notifications in Chrome Extensions
Tags: webdev, tutorial, programming, javascript
Published: 2021-04-24 13:10:08

_This article was originally posted on [my personal blog](https://blog.shahednasser.com/how-to-send-notifications-in-chrome-extensions/)_

In this tutorial, we'll go over how to send notifications in Chrome Extensions. We'll go over how to send one notification, and how to schedule notifications to be sent at a later time.

---

### Prerequisites

This tutorial assumes you already know how to create a Chrome extension. If you don't, then [here](https://blog.shahednasser.com/chrome-extension-tutorial-replace-images-in-any-website-with-pikachu/) is one you can start with first.

---

### Setting Permissions

Before you can send any type of notification, you need to first add in your`manifest.json`in`permissions`key the following:

```json
"permissions": [
          "notifications"
          //other permissions in your extension
  ]
```

This means that the user when installing or updating your extension has to accept that they will receive notifications in order to use the extension.

---

### Send a Notification

To send a notification, you need to use the[Notifications API](https://developer.chrome.com/docs/extensions/reference/notifications). In particular, the`chrome.notifications.create`method which takes the following required options:

```js
chrome.notifications.create('NOTFICATION_ID', {
    type: 'basic',
    iconUrl: 'path',
    title: 'notification title',
    message: 'notification message',
    priority: 2
})
```

Here's what each of these options means:

1. **NOTIFICATION\_ID:** The id of the notification. This can be necessary for updating the notification or clearing it.
2. **type:**The type of notification. Its values can be "basic", "image", "list", "progress"
3. **iconUrl:** The path to the icon that should be shown in the notification. This should be relative to the root of your extension.
4. **title:** the title of the notification.
5. **message:** the message to be shown in the notification.
6. **priority:** this one is not required, but I recommend including it. The value for it can range from -2 to 2, where -2 is the lowest priority and 2 is the highest. The default for this option is 0, so your notifications can go by unseen if you don't include this option. It should also be noted that a value less than 0 will produce an error on devices that don't have a notification center.

There are some other options that are optional:

* **buttons:** buttons that you want to be shown in the notification. This takes an array of buttons with at most 2 buttons. The array should be an object with the property `title` which will be the title of the button. For example:

```js
buttons: [
    {
        title: 'Yes'
    },
    {
        title: 'No'
    }
]
```

* **contextMessage:** This message will be shown in a lower font weight.
* **eventTime:** Timestamp associated with the notification. For example:

```js
eventTime: Date.now()
```

* **items:** This will only be shown for Mac OS X. This could be useful for notifications of type `list`. For example:

```js
items: [
    {
        title: 'Item 1',
        message: 'This is first item'
    }
]
```

* **progress:** This can be useful for notifications of type `progress`. It takes a value between 0 and 100
* **requiresInteraction:** This one will only work for Chrome versions since 50. The value for this is boolean. If set to true, it means that the notification will not disappear from the screen until the user interacts with the message by either clicking on it or dismissing it. The default value for this is false.
* **silent:** This one will only work for Chrome versions since 70. The value of this is boolean. If set to true, then the notification will not make sound or vibration. The default is false.

To send a basic notification that just shows a message to the user:

```js
chrome.notifications.create('test', {
    type: 'basic',
    iconUrl: 'images/1.png',
    title: 'Test Message',
    message: 'You are awesome!',
    priority: 2
});
```

This will send one notification at the moment it's executed.

---

### Scheduling Notifications

In a lot of cases, you don't actually want to send the notification now or you want to send notification at some interval like once a day. For this, we will use the [Alarms API](https://developer.chrome.com/docs/extensions/reference/alarms/).

Alarms allow us to schedule something to be run at a later time. When you create an alarm, you can specify the time interval it will run at. Then, you can listen to the alarm and when it runs executes whatever code you want.

To be able to use Alarms, we need to also include it in our permissions in `manifest.json`:

```json
"permissions": [
          "alarms",
          "notifications"
          //other permissions your extension require
  ],
```

To send notifications at a certain schedule, here's how the workflow goes:

1. Create an alarm that runs at certain intervals
2. Listen for when the alarm runs
3. When the alarm runs, execute some logic and create a notification

**Create an alarm that runs at certain intervals**

To create an alarm, we will use the method`chrome.alarms.create`:

```js
chrome.alarms.create('ALARM_NAME', {
    //options
});
```

You only need to specify the name of the alarm`ALARM_NAME`, which will be used later when listening to the alarm. No other options are required. However, if you use it without options, the alarm will run only once at the time it was created.

The options you can pass are:

* **when:** When should the alarm start working. If you want it to start right away:

```js
when: Date.now()
```

* **periodInMinutes:** This is where we specify when the alarm will run. It takes a number, which is the number of minutes between each time the alarm fires. So, if I want the alarm to be fired every five minutes:

```js
periodInMinutes: 5
```

* **delayInMinutes:** This specifies if the`onAlarm`event should delay a little before firing.

The most important option here is`periodInMinutes`. It specifies when do we want to create our notification.

So, if we want to create an alarm that will let us create a notification that runs everyday:

```js
chrome.alarm.create('testAlarm', {
	periodInMinutes: 1440
});
```

**Listen for when the alarm runs**

The next step would be to listen when the alarm runs. This should be usually done in background scripts for Manifest V2, or service workers for Manifest V3.

_You can read more about the differences between Manifest V2 and V3 [here](https://blog.shahednasser.com/chrome-extension-tutorial-migrating-to-manifest-v3-from-v2)._

If you don't know what a background script is, it's, as its name says, a script that's always running in the background, even if your extension's page or pop up or whatever your extension uses is not open or running. This helps us listen to events, alarms, messages, etc... at all times.

Service workers were introduced in Manifest V3 as a replacement for background scripts. The main difference is service workers are not always running. Service workers register event listeners to alarms, messages, etc... same as background scripts, so only the listeners run when necessary like when an event occurs.

If you don't already have a background script in your chrome extension, you need to first include it in`manifest.json`:

```json
"background": {
    "scripts": ["js/background.js"],
    "persistent": false
},
```

Or if you're using Manifest V3 you need to register a service worker:

```json
"background": {
    	"service_worker": "js/background.js"
 },
```

Then, in the script, we will listen to the alarm using`chrome.alarms.onAlarm.addListener`which takes a callback function, which will be our listener. This callback function will be executed every time an alarm in our extension is run, so we need to make sure we only listen to the alarm we need which we named`testAlarm`:

```js
chrome.alarms.onAlarm.addListener((alarm) => {
    if (alarm.name === "testAlarm") {
        //our alarm is running, send notification
    }
});
```

We need to check that `alarm.name === "testAlarm"` to make sure that our notifications alarm is running. This is important if you have multiple alarms in your extension as well to make sure you're executing the desired logic for the correct alarm.

So, if the condition is true, we can create the notification.

### When the alarm runs, execute some logic and create a notification

Depending on your use case, you might execute some logic, maybe send a request to a server or any other logic, then run the notification.

What we will do is that we'll just create the message when the alarm runs. This is how it can be done:

```js
chrome.alarms.onAlarm.addListener((alarm) => {
    if (alarm.name === "testAlarm") {
        chrome.notifications.create('test', {
            type: 'basic',
            iconUrl: 'images/1.png',
            title: 'Test Message',
            message: 'You are awesome!',
            priority: 2
        });
    }
});
```

After these 3 steps, our extension will create an alarm that will run once a day and executes the code in the listener we added to the`onAlarm`event. This listener will create a notification. Thus, a notification will be sent to the user every day.

---

### Sending a Notification on Firefox

Sending a notification on Firefox is exactly the same, except you just need to replace `chrome.*` in all of the methods used with `browser.*`. You can read more about the difference between Firefox and Chrome [here](https://blog.shahednasser.com/making-your-extension-compatible-with-both-chrome-and-firefox/).

---

### Summary

To create a notification you need to:

1. Add `notifications` to the `permissions` array in `manifest.json`
2. Use `chrome.notifications.create` to create a notification and send it.

To schedule a notification to run at an interval of time, you need to:

1. Add `alarms` to the `permissions` array in `manifest.json`
2. Use `chrome.alarms.create` to create an alarm.
3. Listen to the alarm with `chrome.alarms.onAlarm.addListener` and create a notification inside the listener.

_If you would like to connect and talk more about this article or programming in general, you can find me on my Twitter account[@shahednasserr](https://twitter.com/shahednasserr)_