Author: Hussain Mir Ali

I am interested in web and mobile technologies.

If you have any questions or feedback then message me at

How to build Chrome extensions with JavaScript

In this blog post a Chrome extension is built for tracking website visits. The UI type implemented is a 'browser action' with 'persistent background script' for logic.  For more information on technical specification the blog post having the title 'Technical Specs of Chrome extensions' can be reviewed. 

Creating Extension

Step 1:

The first step when developing a Chrome extension is to create the manifest.json file. This file holds all the configuration information pertaining to this extension and also has permissions to access certain API.
"name": "Visitrack",
"version": "1.0",
"description": "This extension helps track website visits.",
"manifest_version": 2,
"permissions": ["storage", "history"],
"background": {
"scripts": ["js/background.js"],
"persistent": true
"browser_action": {
"default_icon": {
"16": "images/16.png",
"32": "images/32.png",
"48": "images/48.png",
"128": "images/128.png"
"icons": {
"16": "images/16.png",
"32": "images/32.png",
"48": "images/48.png",
"128": "images/128.png"
This extension uses browser action page with persistent background script. This allows the extension to continuously watch over the website visits and keep track of total number of visits to a specific URL. The storage and history permissions allow this extension to store the visits count and enables listening to URL visit event respectively.  The 'default_icon' and 'icons' keys map to object literals containing icon paths for this extension. 

Step 2:

Implementing the persistent background script in background.js file.
// React when a browser action's icon is clicked.
chrome.browserAction.onClicked.addListener(function(tab) {
//Open the current website visit statistics.
url: chrome.extension.getURL('views/stats.html')

// React when the user visits a url.
chrome.history.onVisited.addListener(function(history) {

let url = history.url;

//Get visit counts map from storage.['visitCount'], function(items) {

let visitCount = items.visitCount;
// Check if the url already exists and increment the visit count.
if (visitCount[url] !== undefined) {
let count = visitCount[url];
visitCount[url] = ++count;
// If the url doesn't already exist then add to the map and set visit count to 1.
else {
visitCount[url] = 1;

// Update it using the Chrome extension storage API.{
'visitCount': visitCount
function() {
console.log('Data updated.');

// React when the extension is first installed.
chrome.runtime.onInstalled.addListener(function() {
// Save it using the Chrome extension storage API.{
'visitCount': {}
}, function() {
console.log('Data initialized.');

For this application the background script consists of event listeners for specific events in the Chrome browser.

The first event listener listens for click event on the extension icon ('chrome.browserAction.onClicked') in the toolbar. When this event is triggered it opens up the visit statistics page in a new tab.

The second event listener is for the event when user visits a new website URL from the browser address bar('chrome.history.onVisited').  When this event is triggered the code inside the callback function will get the visit count for existing URL in the 'visitCount' object and increment it by 1. But if the URL doesn't already exist then the value for that key is set to be 1.

The third event listener triggers when this extension is first installed('chrome.runtime.onInstalled'). The code inside the event callback will initialize an empty 'visitCount' object in Chrome's storage.

Step 3:

Implementing UI for the visit statistics page stats.html.
<link href="../css/main.css" rel="stylesheet"></link>
<script src="../js/statspage.js" type="text/javascript"></script>
<div class="stats-info-container">
<div class="stats-info-heading">
<h3>Visitrack Stats</h3>
<div class="stats-info-table">
<th>Visit count</th>
This page contains heading and a table which shows the visit count for a particular URL. The 'Website' table heading corresponds to URL and 'Visit count' table heading corresponds to total visit count.

Step 5:

Implementing logic to populate the visit statistics page table(stats.html) in statspage.js.
window.document.addEventListener("DOMContentLoaded",function populateTable(){
//Get visit counts map from storage.['visitCount'], function(items) {
let visitCount = items.visitCount;
let urls = Object.keys(visitCount);
let tbody = document.querySelector('.stats-info-table > table > tbody');
let rows = '';

for(let i=0; i<urls.length; i++){
rows+= `<tr><td title=${urls[i]}>${urls[i]}</td><td>${visitCount[urls[i]]}</td></tr>`;

tbody.innerHTML = rows;
The above code gets the 'visitCount' object from Chrome storage and then populates the table in stats.html page.  

Step 4:

Implementing the CSS(for stats.html) in main.css.
margin: 0 auto;
position: relative;
left: 0;
right: 0;
width: 500px;

text-align: center;

.stats-info-table table, th, td{
border: 1px solid #000000;
border-collapse: collapse;

.stats-info-table > table > thead > tr th{
width: 250px;
font-weight: normal;

.stats-info-table > table > tbody > tr{
border-top: 1px solid #000;

.stats-info-table > table > tbody > tr td{
font-weight: normal;
max-width: 250px;
text-overflow: ellipsis;
overflow: hidden;

.stats-info-table > table > tbody > tr td:nth-child(2){
text-align: center;
This CSS pertains to the stats.html page and stylizes all the elements in that page. 

Step 5:

Setting up the file structure.

The folders are divided into 4 categories. The 'views' folder contains stats.html. The 'js' folder contains statspage.js and background.js. The 'css' folder contains the css for the stats.html page in main.css. Finally 'images' folder contains the icons for the extension with 128x128, 64x64, 48x48 and 16x16 image sizes.

Step 6:

Running Locally: 

To run the extension locally developers can open 'chrome://extensions/' using the Chrome address bar. Then 'LOAD UNPACKED' can be clicked to select the 'Visitrack' folder. 

Then the extension gets automatically loaded.

After visiting some sites the extension icon in the toolbar can be clicked to open statistics page.