Discovering how to make a Chrome extension enables you to use coding skills to simplify tasks through Google Chrome’s extensive APIs.
From creating basic “Hello World!” extensions to advanced tools for web page screenshots, the possibilities are limitless.
Let’s explore how you can do that! 🧭

Key Takeaways
- Create a manifest.json file with key extension details.
- Load your extension via Chrome’s Extensions page for testing.
- Enhance functionality with popups, notifications, and context menus.
📚 Table of contents:
In this tutorial, we will show you how to make a Chrome extension that sends browser notifications from a popup menu. We will also use the context menu and data storage APIs to make the most out of it. We are calling it Notify! with an exclamation mark!

📥 The extension’s code is public on GitHub so feel free to fork and use it.
How to make a Chrome extension: the structure
Before we move ahead, you should look at Google Chrome’s developer documentation to learn about Chrome extension development in general.
Also, if you are looking to write a Chrome extension for the Chrome Web Store, please look at their single-purpose policy.
Let’s start by creating a new folder named notify
on your device. This folder will contain everything that will be part of your extension.
Now, you need to make a manifest file that will contain all the information about our extension. Create a file called manifest.json
and include the following code:
{
"name": "Notify!",
"description": "A Google Chrome extension!",
"version": "1.0",
"manifest_version": 3,
"icons": {
"48": "/assets/icons/48.png",
"128": "/assets/icons/128.png"
}
}
Code language: JSON / JSON with Comments (json)
As you can see, so far, it only contains meta-information about your extension, such as its name, description, and version. The manifest_version
tells Chrome which version of their extensions API you are using.
Loading the extension
After you have your manifest file in place, you can load up your extension in the Chrome browser:

Open the Extension Management page by navigating to chrome://extensions
, or you can also open it from the Extensions menu in the settings.
Once there, enable the Developer mode and use the Load unpacked button to select your extension directory.
Behold thy extension! Now that your extension is loaded, you can improve it step-by-step and observe the changes.
Make sure you add an icon for your extension to the assets/icons/
folder or else a default icon will appear.
Adding a popup user interface
Let’s continue by adding some user interface to the extension from where people can interact with the provided options.
There are multiple ways to do this, such as adding an entire page, but a popup is usually the way to go for most extensions.
To add a popup to the extension, you will have to add this to your manifest.json
file:
"action": {
"default_popup": "popup.html",
"default_icon": {
"48": "/assets/icons/48.png",
"128": "/assets/icons/128.png"
}
},
Code language: JavaScript (javascript)
With this, you tell the extension the location of your popup’s HTML file and the default icons. This is just the default icon as the API allows you to change the icon on the go. For example, if you create a Google PageSpeed test, one can show different icons on the website based on their page rankings.

Google Chrome Extension’s Popup
Now, you can add your popup’s HTML code to the file, as we do in our example:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="assets/css/popup.css">
</head>
<body>
<div id="notify-wrapper">
<div id="notify-header">
<h1>Notify!</h1>
</div>
<div id="notify-containers">
<div class="notify-form">
<label for="text">Notification</label>
<textarea name="text" id="notify-text" placeholder="Let's notify!"></textarea>
</div>
<div class=notify-buttons>
<p>Total: <span id="notify-count"></span></p>
<button class="button" id="notify-reset">
Reset
</button>
<button class="button primary" id="notify-button">
Notify!
</button>
</div>
</div>
</div>
<script src="assets/js/popup.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
This HTML file also links to a stylesheet and script to add style and functionality to our popup.
If you are following along, you can get the CSS code from here. We will add JavaScript to the file later in this tutorial.
So far, you have created a Google Chrome extension that has a popup, and it has taken us only a few lines of code. As we said in the beginning, creating a Google Chrome extension is very easy!
Moving forward in this tutorial, we will add functionality to this extension and make it more than just a placeholder.
Using the notifications API
As the extension’s name suggests, it is a notifications extension, so let’s add some!
Before you use some of the APIs, you need to specify permissions for them in the manifest.json
file. One of the reasons to do this is so that your extension users know which permissions your extension is asking before installing them.
For notifications, you do it like this
"permissions": [
"notifications"
],
Code language: JavaScript (javascript)
You also need to add a service worker to the extension to send notifications. For that, you need to add this to your manifest:
"background": {
"service_worker": "background.js"
},
Code language: JavaScript (javascript)
You need a service worker for the notification API as it cannot be used directly from the popup.js
file.
In the background.js
file, you need to add the following code to send a notification:
chrome.runtime.onMessage.addListener( data => {
if ( data.type === 'notification' ) {
chrome.notifications.create(
'',
{
type: 'basic',
title: 'Notify!',
message: data.message || 'Notify!',
iconUrl: './assets/icons/128.png',
}
);
}
});
Code language: JavaScript (javascript)
Here, we use the onMessage
event listener to get the trigger to push notifications from the popup.
We also use the create
method to create a new notification. Notifications can be of various types, but here the “basic” type is used. You should take a look at all the available options.
Now that the create
method is in place, you can fire it from the popup.js
file like this:
const text = document.getElementById( 'notify-text' );
const notify = document.getElementById( 'notify-button' );
notify.addEventListener( 'click', () => {
chrome.runtime.sendMessage( '', {
type: 'notification',
message: text.value
});
} );
Code language: JavaScript (javascript)
Here, the sendMessage
action is being used to trigger the notification. And voila! We have an extension that triggers a notification.

Make sure you are using the latest version of Google Chrome, and have given it permissions to trigger notifications. In short, do not be like me, who spent hours trying to figure out why notifications were not appearing.
Adding a context menu item
As mentioned in the introduction, the context menu is the menu that appears on right click:

There can be many reasons that your extension might have a context menu item. One prominent example is to select some text with the cursor and then search it on Google.
You can add as many items to the context menu as you want, but if your extension adds more than one item, they will be collapsed under one parent item.
For this, you also need to add permissions to your manifest file:
"permissions": [
"contextMenus",
"notifications"
],
Code language: JavaScript (javascript)
Now that you have added permissions for contextMenus
, you can add this to your background.js
file:
chrome.runtime.onMessage.addListener( data => {
if ( data.type === 'notification' ) {
notify( data.message );
}
});
chrome.runtime.onInstalled.addListener( () => {
chrome.contextMenus.create({
id: 'notify',
title: "Notify!: %s",
contexts:[ "selection" ]
});
});
chrome.contextMenus.onClicked.addListener( ( info, tab ) => {
if ( 'notify' === info.menuItemId ) {
notify( info.selectionText );
}
} );
const notify = message => {
return chrome.notifications.create(
'',
{
type: 'basic',
title: 'Notify!',
message: message || 'Notify!',
iconUrl: './assets/icons/128.png',
}
);
};
Code language: JavaScript (javascript)
The above code also includes the code from the previous step for triggering a notification that is now abstracted into the notify
function so it could be reused.
The contextMenus.create
action is used to add an item to the context menu. It is hooked to onInstalled
as it only needs to be initialized once.
After that, similarly to the previous step, we use contextMenus.onClicked
to capture the click and trigger a notification.

It can be a very nifty way to bundle in the functionality of your extension. If you look around at the extensions being used on your browser, you will find many extensions cleverly using this space to enhance the experience of their extension.
Using storage API to store data
Now that your extension has a few features to show off, let’s take a look at the Storage API. Storage API is useful when you want to store some user data to your extension.
There are two types of Storage API: local and sync. Local storage, as the name suggests, is saved in your browser and stays local. In comparison, sync storage allows data to be synced between browsers using the same Google account. For our purposes, we use local storage.
First, you need to add storage permission to your manifest file:
"permissions": [
"contextMenus",
"notifications",
"storage"
],
Code language: JavaScript (javascript)
After this, you can use storage, the storage.local.get
and storage.local.set
, methods to retrieve or save the data.
You can add the following code to your popup.js
file:
const reset = document.getElementById( 'notify-reset' );
const counter = document.getElementById( 'notify-count' );
chrome.storage.local.get( ['notifyCount'], data => {
let value = data.notifyCount || 0;
counter.innerHTML = value;
} );
chrome.storage.onChanged.addListener( ( changes, namespace ) => {
if ( changes.notifyCount ) {
let value = changes.notifyCount.newValue || 0;
counter.innerHTML = value;
}
});
reset.addEventListener( 'click', () => {
chrome.storage.local.clear();
text.value = '';
} );
Code language: JavaScript (javascript)
This code does two things:
- It updates the notification count in the popup when we open the popup or the storage value changes. For listening to storage change,
storage.onChanged
is used. - In part, we clear the storage when the user clicks on the reset button.
The above code does the job of getting the latest count and updates it. Now setting up the data remains. For that, you can update our notify
function with this:
const notify = message => {
chrome.storage.local.get( ['notifyCount'], data => {
let value = data.notifyCount || 0;
chrome.storage.local.set({ 'notifyCount': Number( value ) + 1 });
} );
return chrome.notifications.create(
'',
{
type: 'basic',
title: 'Notify!',
message: message || 'Notify!',
iconUrl: './assets/icons/128.png',
}
);
};
Code language: JavaScript (javascript)
Here, we get the latest storage data and then update it with the latest count.
Similarly, you can use the chrome.storage.sync
API to sync the options between the browsers.
Distributing the extension
Congratulations! You have done it! You have successfully created a Google Chrome extension that uses many different parts of the Google Chrome experience, including:
- Popups
- Notifications API
- Context menu
- Storage API
If you want to see the code for this extension, you can get it in this Notify GitHub repository.
We all like to show off the great work that we do to the world. Once your extension is complete, you can submit it to the Chrome Web Store for other Chrome users to download.
If you want to explore other options that Google Chrome offers to extension developers, we recommend checking the official documentation.
I hope this article did its part in teaching you how to make a Chrome extension. We are excited to see what you can create, so let us know about your adventures with Google Chrome extension development in the comments section below.
You may also be interested in:
…
Don’t forget to join our crash course on speeding up your WordPress site. Learn more below:
Layout and presentation by Chris Fitzgerald and Karol K.