The chrome notifications API is responsible for displaying different types of what is called rich notifications in your users’ system tray.
Chrome Notifications API works well with the Web-push Notifications (Google Cloud Message) but more on that in our next article about Understanding Chrome Extensions GCM. Although we can choose what kind of template of notification to use, we are still limited to the elements we can add to the notification and the look and feel across devices. Notification will present themselves with the default notification design across OS.
How to declare it in Manifest.json
{
`...,
"permissions":[
"notifications"
],
...
}
Chrome Notification API functions and listeners CANNOT be used in content scripts
Chrome Notification API Templates
There are four different types of notification templates we can use.
- Basic
- Image
- Progress
- List
Let’s look at each one more
Basic
Basic: “Contains an icon, title, message, expandedMessage, and up to two buttons.”
chrome.notifications.create("any-id", {
title: "The title goes here",
iconUrl: "icon.png",
appIconMaskUrl: "icon.png",// does not show up on MacOS
message: "The main message goes right here",
contextMessage: "Context message are small",
type: "basic",
buttons: [
{title: "Yes"},
{titel: "Yes"}
]
});
Image
Image: “Contains an icon, title, message, expandedMessage, image, and up to two buttons.”
chrome.notifications.create("any-id", {
title: "Image Notification",
iconUrl: "icon.png",
appIconMaskUrl: "icon.png",// does not show up on MacOS
message: "Message goes here",
contextMessage: "Smaller Message goes here",
imageUrl: "image.png",
type: "image",
buttons: [
{title: "Yes Sir"},
{titel: "Yes Sir"}
]
});
Progress
Progress: “Contains an icon, title, message, progress, and up to two buttons.”
chrome.notifications.create("any-id", {
title: "Progress Notification",
iconUrl: "icon.png",
appIconMaskUrl: "icon.png", // does not show up on MacOS
message: "Notify your users on progress",
contextMessage: "",
type: "progress",
progress: 47,
buttons: []
});
List
“Contains an icon, title, message, items, and up to two buttons. Users on Mac OS X only see the first item.”
chrome.notifications.create("any-id", {
title: "Item Notification",
iconUrl: "icon.png",
appIconMaskUrl: "icon.png",// does not show up on MacOS
message: "", // does not show in this type
contextMessage: "",
type: type,
items: [
{ title: "Item 1", message: "Description of Item 1" },
{ title: "Item 2", message: "Description of Item 2" }
],
buttons: []
});
How to interact with the Notification
To listen for onclick events for a notification you have to add a listener in your background scripts / service worker. You can listener for if one of the 2 buttons were clicked or the notification itself was clicked.
// Documentation - https://developer.chrome.com/docs/extensions/reference/api/notifications#event-onButtonClicked
// if the notification was clicked
chrome.notifications.onClicked.addListener((notificationId) => {
if (notificationId == 'any-id') {
// Run your code
}
});
// if one of the notification buttons were clicked
chrome.notifications.onButtonClicked.addListener((notificationId, buttonIndex) => {
if (notificationId == 'any-id') {
if (buttonIndex == 1) {
// Run your code for button 1
} else if (buttonIndex == 2) {
// Run your code for button 2
}
}
})
Sample Project
We are going to make a chrome extensions which show different types of notifications. If the user enter the id martin
or m2k
and clicks on clicks on that notification and/or the buttons another notification will appear.
You can get the source code from this repo: https://github.com/BuildChromeExtensions/chromenotifications
If you use the same
id
to show different and it does not appear. Clear your notifications from your system tray first and try again.
File Setup
We’d need an 2 images one for the iconUrl
which is mandatory for notifications and the other for the imageUrl
if we want to show image notifications. We also need a manifest.json
file, background.js
popup.html
and popup.js
The file structure should look something like this.
manifest.json
{
"name": "Notifications",
"version": "1.0.0.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html"
},
"permissions": [
"notifications"
],
"background": {
"service_worker": "background.js"
}
}
popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
body {
width: 400px;
height: 530px;
padding: 10px 20px;
}
form {
display: flex;
flex-direction: column;
align-items: center;
}
input,
select {
padding: 4px 8px;
margin: 5px 0px;
width: 70%;
border-radius: 30px;
}
button {
background: #03c2fc;
color: #ffffff;
padding: 10px 20px;
border: none;
cursor: pointer;
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
transition: all 0.4s;
border-radius: 30px;
font-weight: 700;
}
button:hover {
background: #026482;
}
</style>
</head>
<body>
<form>
<img src="icon.png" alt="Logo" />
<h1>Chrome Notifications</h1>
<input name="id" type="text" placeholder="Notification ID (Optional)" />
<input required name="title" type="text" placeholder="Title" maxlength="128" />
<input required name="message" type="text" placeholder="Message" maxlength="128" />
<input name="contextMessage" type="text" placeholder="Context Message (Optional)" maxlength="128" />
<label for="progress">Progress</label>
<input id="progress" type="range" name="progress" min="0" value="30" max="100">
<input name="button1" type="text" placeholder="Button 1 Text (Optional)" maxlength="128" />
<input name="button2" type="text" placeholder="Button 2 Text (Optional)" maxlength="128" />
<select name="type" value="0">
<option disabled value="0">Select Type</option>
<option value="basic">Basic</option>
<option value="progress">Progress</option>
<option value="image">Image</option>
<option value="list">List</option>
</select>
<button>Show Notification</button>
</form>
<script type="text/javascript" src="./popup.js"></script>
</body>
</html>
popup.js
// Logo Icon Path
const iconUrl = "icon.png";
const imageUrl = "image.png";
const appIconMaskUrl = "icon.png";
// https://developer.chrome.com/docs/extensions/reference/api/notifications#type-NotificationOptions
document.querySelector('form').onsubmit = function (e) {
e.preventDefault();
const id = e.target.id.value || Date.now().toString();
const title = e.target.title.value;
const message = e.target.message.value;
const progress = parseInt(e.target.progress.value);
const contextMessage = e.target.contextMessage.value;
const type = e.target.type.value;
const button1 = e.target.button1.value;
const button2 = e.target.button2.value;
const buttons = [];
// for item notifications
const items = [
{ title: "Item 1", message: "Description of Item 1" },
{ title: "Item 2", message: "Description of Item 2" }
]
if (button1) {
buttons.push({ title: button1 })
}
if (button2) {
buttons.push({ title: button2 })
}
switch (type) {
case "basic":
chrome.notifications.create(id, {
title: title,
iconUrl: iconUrl,
appIconMaskUrl: appIconMaskUrl,// does not show up on MacOS
message: message,
contextMessage: contextMessage,
type: type,
buttons: buttons
});
break;
case "image":
chrome.notifications.create(id, {
title: title,
iconUrl: iconUrl,
appIconMaskUrl: appIconMaskUrl,// does not show up on MacOS
imageUrl: imageUrl,
message: message,
contextMessage: contextMessage,
type: type,
buttons: buttons
});
break;
case "progress":
chrome.notifications.create(id, {
title: title,
iconUrl: iconUrl,
appIconMaskUrl: appIconMaskUrl, // does not show up on MacOS
message: message,
contextMessage: contextMessage,
type: type,
progress: progress,
buttons: buttons
});
break;
case "list":
chrome.notifications.create(id, {
title: title,
iconUrl: iconUrl,
appIconMaskUrl: appIconMaskUrl,// does not show up on MacOS
message: message,
contextMessage: contextMessage,
type: type,
items: items,
buttons: buttons
});
break;
default:
break;
}
}
background.js
// Documentation - https://developer.chrome.com/docs/extensions/reference/api/notifications#event-onButtonClicked
// if the notification was clicked
chrome.notifications.onClicked.addListener((notificationId) => {
console.log(notificationId)
if (notificationId == 'martin') {
// Run your code
const randomId = Date.now().toString();
chrome.notifications.create(randomId, {
title: "You've clicked a Martin Notification",
iconUrl: "icon.png",
appIconMaskUrl: "icon.png",// does not show up on MacOS
message: "You've Triggered my trap card!",
contextMessage: "Does any one still remember that anime.",
type: "basic",
buttons: [
{ title: "Yes" },
{ title: "No" }
]
});
}
});
// if one of the notification buttons were clicked
chrome.notifications.onButtonClicked.addListener((notificationId, buttonIndex) => {
console.log(notificationId, buttonIndex);
const randomId = Date.now().toString();
if (notificationId == 'm2k') {
if (buttonIndex == 0) {
// Run your code for button 1
chrome.notifications.create(randomId, {
title: "You've clicked a M2K Notification",
iconUrl: "icon.png",
imageUrl: 'image.png',
message: "Thanks for reading the article",
type: "image",
});
} else if (buttonIndex == 1) {
// Run your code for button 2
chrome.notifications.create(randomId, {
title: "You've clicked a M2K Notification",
iconUrl: "icon.png",
progress: 100,
message: "Thanks for reading the article",
type: "progress",
});
}
}
})
Leave a Reply