Softnami
Author: Hussain Mir Ali

I am interested in web and mobile technologies.

If you any questions or feedback then message me at devtips@softnami.com.

Announcements
Ads

Call predictor: AI based call prediction

Download

2020

Feb
Jan

2019

Dec
Nov
Jul
May
Mar
Jan

2018

Nov
Sep
Jul
Jun
Apr
Feb
Jan

2017

Dec
Oct
Sep
Aug
Jul
Jun
May
Apr
Mar
Jan

2016

Dec
Oct
Sep
Aug
Jul

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. 

GitHub: https://github.com/husenxce/Visitrack
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.
chrome.tabs.create({
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.
chrome.storage.sync.get(['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.
chrome.storage.sync.set({
'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.
chrome.storage.sync.set({
'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.
<html>
<head>
<title>Visitrack</title>
<link href="../css/main.css" rel="stylesheet"></link>
<script src="../js/statspage.js" type="text/javascript"></script>
</head>
<body>
<div class="stats-info-container">
<div class="stats-info-heading">
<h3>Visitrack Stats</h3>
</div>
<div class="stats-info-table">
<table>
<thead>
<tr>
<th>Website</th>
<th>Visit count</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</body>
</html>
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.
chrome.storage.sync.get(['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.
.stats-info-container{
margin: 0 auto;
position: relative;
left: 0;
right: 0;
width: 500px;
}

.stats-info-heading{
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.