Let's build a modern time-on-site counter for your website with timeonsite.js and JS Beacons
Tags: javascript, webdev, programming, beginners
Published: 2022-08-15 12:45:49

 **_Timeonsite.js_** can be used to measure most important metric for you website _time-on-page_ and _time-on-site_. Though it can be calculated simply by finding the difference between page entry and page exit with Javascript's Date object, here we are going to use a powerful web implementation of this with the help of widely popular timeonsite.js library along with the help of **_sendBeacon()_** API for safe data persistence to DB table.

## Basic HTML block
```
<!-- 
HTML page with "counter" div container 
-->
<html><head></head>
    <div id="counter">
    </div>
</html>
```

## Javascript code snippet for building timer
```
// On page Load...
let entryTime = new Date();

//....
//User navigates the website
// some time later....

During Page exit....
let exitTime = new Date();

let timeSpent = exitTime - entryTime;
timeSpent = (timeSpent/1000); //convert to seconds

//Display the time spent with Jquery's API in page:
$(document).ready(function(){
    $('#counter').html('You have spent ' + timeSpent + 'seconds.');
});
```

That's it. We have measured user's time-on-page parameter nicely.  But what about its accuracy, cross-browser compatibility and data persistence when user refreshes the page many times or opens N number of browser tabs of same website? What if user has gone to visit another shopping or social media website leaving the former webpage in open state?

Since **_timeSpent_** is a variable, it cannot control the states occurring in the webpage like inactive tab or multiple tabs opened concurrently for the same website. In this case, the accuracy of the **_timeSpent_** is lost and cannot be reliably measured.  Let's take a look at the APIs exposed by timeonsite.js tracker.

But timeonsite tracker's _`Tos.getTimeOnPage()`_ API exposes _`timeonpage data`_ every time you call the API. And we are going to use this API to show and update our counter with timer data.

```
{
 TOSId: 1129620185532,
 TOSSessionKey: "14802525481391382263",
 TOSUserId: "anonymous",
 title: "Blog application — Nature & Wildlife",
 URL: "http://tos-localdata.london/home.php"
 entryTime: "2021–11–27 13:15:48.663",
 exitTime: "2021–11–27 13:17:31.663",
 timeOnPage: 103,
 timeOnSite: 103,
 timeOnPageTrackedBy: "second",
 timeOnPageByDuration: "0d 00h 01m 43s",
 timeOnSiteByDuration: "0d 00h 01m 43s",
 trackingType: "tos",
}
```



## Step 1
Add the tracker snippet in your HTML page header
```
<head>
     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/timeonsite/1.2.1/timeonsitetracker.js"></script>
</head>
```

## Step 2 
Add the Init code of the tracker

```
<script>
var config = {
    // track page by seconds. Default tracking is by milliseconds
    trackBy: 'seconds',
    callback: function(data) { /* callback denotes your data tracking is real-time */
		console.log(data);
		var endPointUrl = 'http://example.com' //Replace with your actual backend API URL http://localhost/tos
		if (data && data.trackingType) {
			if (data.trackingType == 'tos') {
				if (Tos.verifyData(data) != 'valid') {
					console.log('Data abolished!');
					return; 
				}
			}
			
			// make use of sendBeacon if this API is supported by your browser.
			if (navigator && typeof navigator.sendBeacon === 'function') {
				data.trasferredWith = 'sendBeacon';
				var blob = new Blob([JSON.stringify(data)], {type : 'application/json'});
				navigator.sendBeacon(endPointUrl, blob);
			}
		}
	}
};
var Tos;
if (TimeOnSiteTracker) {
    Tos = new TimeOnSiteTracker(config);
}
</script>
```


## Step 3 
Show the status of your time-on-page data in webpage as well

```
$(document).ready(function(){
	setInterval(function () {
		$('#counter').html('You have spent ' + Tos.getTimeOnPage().timeOnPage + 'seconds.');
	}, 1000); // Update the counter every second for real-time experience.
});	
```

That's it. _Watch for tracker imprint in browser terminal!_ We are done with accurate tracking of user's time-on-site in our website. There is [a demo here ](https://saleemkce.github.io/timeonsite)if you want to see.

You will see counter like this. Customize the look.
![TimeOnSite sample counter in page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zumupm9amkriss03kjyr.png)

Timeonsite.js will take care of everything like,

1, Inactive tabs
2, Data persistence on page refresh and reloads
3, Multiple tabs of same website (because in normal JS Date object, you will end up duplicate and wrong time-on-site data)
4, Saving data to your favorite DB table on page close. (You may use already backend [visual, free backend server](https://github.com/saleemkce/visual) for saving this data in PHP/NodeJS)
5, Most importantly, unprecedented accuracy of the metrics ever captured by an analytics provider!

So, you can show how much time your users spent on your site and also you can show how much time user spent in last session as log taken from DB table.

In step 2, we used following lines,

```
navigator.sendBeacon(endPointUrl, blob);
```
This is one of the most powerful **_Javascript API_** for making HTTP post requests like **_XMLHTTPRequest_** but it works especially for retaining and saving log data during page close.

![Sample SendBeacon() Request on RequestBin site](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/09ymi7o832smgdsv789y.PNG)

You'll see a ping in Network console unlike XHR/HTTP requests. I'm using a sample bin that causes CORS error. In normal app, it should send back success response.

## Bonus point
Timeonsite.js also exposes a `Tos.startActivity()` API along with `Tos.endActivity()`. The advantage of this API is that it can track any specific activity in a site and it's bundled with same capabilities like time-on-page parameter like inactive tab, minimize tab or multiple tabs in measuring timing accuracy. Each pageview includes a `TOSSessionKey` to uniquely identify each activity `ActivityId(TOSId)` occurring in the site. Let's take an example,

```
// After initializing the TimeOnSiteTracker on page load, call startActivity() as
Tos.startActivity({applicantName: 'Nazir Khan'}); // this will start tracking the activity

// .
// .
// .
// after a while,

Tos.endActivity({applicantCountry: 'Romania'});
// calling .endActivity() will give back response

Gives response as,
{
    TOSId: 585872449448,
    TOSSessionKey: "14802525481391382263",
    TOSUserId: "anonymous",
    title: "Test application - TimeOnSiteTracker",
    URL: "http://tos-localdata.london/home.php",
    activityStart: "2021-11-27 13:20:46.707",
    activityEnd: "2021-11-27 13:20:50.213",
    timeTaken:4,
    timeTakenByDuration: "0d 00h 00m 04s"
    timeTakenTrackedBy: "second",
    trackingType: "activity",
    applicantName: "Nazir Khan",
    applicantCountry: "Romania"
}
```

If you liked this article, go ahead and give a [star on github](https://github.com/saleemkce/timeonsite) repository. And share your comments on how it's like to build your own time-on-site counter for your webpage.

**_Notes_**
This timeonsite.js is commercial library but it's also free for non-production sites and personal websites. So, let's use the free version hosted from CDN.js hosting website.