Javascript Track User Activity on Webpage With Custom Script

Time Spent, User Country, Scrolling, Mouse & Button Clicks, Mouse Movement, and Key Presses

Track webpage activity of a user

In this post, we create a custom JavaScript front-end script to track user activity on a webpage.

The tracking of course is not as sophisticated as Google Analytics. It surely is incomplete, may have bugs, and might miss edge cases. But it’s a starting point nonetheless.

Live Example

First, let’s see the page information and real-time counters in the table below. Scroll, click (anywhere in the body, then on dummy buttons and link at the bottom), move mouse, and key press to see the values increment. Change tabs or windows to see timer stop and start. Sit idle for 10 seconds, and it will stop too.

Time Zone
Region
Country
Page
Time Spent (secs) 0
Scrolling
Mouse Clicks
Button Clicks
Link Clicks
Mouse Movement
Key Presses

Dummy Buttons:




Dummy Link


The Implementation

Let us quickly discuss a few implementation details:

The Page Path

We get that by window.location.pathname, as soon as the DOM content loads.

Getting Time Zone, Region and Country of the User

The details of how to do this is explained in this post: get user country and region on browser with JavaScript only.

Initial Wait

When the page loads the timer starts automatically. The initial wait is 3 seconds, in which if there’s no activity, the timer stops.

Interval Wait

For every activity, we reset the start time. The interval wait is 10 seconds from the start time, after which, if there’s no activity recorded, we stop the timer.

10 seconds is a reasonable choice because if the user is not interacting with the screen in any way for more than 10 seconds, then they’re most likely not viewing the page. But it’s still an arbitrary value that you can change to more or less than 10 seconds.

Timer

Our calculations for the timer are in milliseconds, which we convert to hh:mm:ss format with a helper method.

Timer Check Interval

We check and refresh the timer every second.

Screen Visibility

Every second we check if the screen is visible or not with Document.hidden check before doing any other calculation. So if you’re on another tab or window, the timer stops immediately.

Events to Track

We listen to mouseup, keydown, scroll and mousemove events. For Button and Link clicks, we check their event target nodeName to be “Button” or “A” respectively. In the case of Button clicks, we keep track of total and individual click count.

Using the Tracked Values

Since this implementation is for demonstration, we use the counter values for display only. In the code shared below, we do that by getting the elements by their ids and replacing their innerHtml with their counter values.

To create a complete custom analytics solution of your own, however, you’ll need to send these values to the backend and persist them in a database. You could use polling or sockets to transfer the data from the front-end.

To find the location of the user, you can use two approaches: 1. find the country and the region of the user on browser with JavaScript only. 2. For more accurate detection of the user country use a geolocation API, such as ipstack, and track a session with cookies.

You could also exclude yourself (the owner) from being tracked following something similar to what I have shared for excluding yourself from Google analytics.


The Code

<script>

  var INITIAL_WAIT = 3000;
  var INTERVAL_WAIT = 10000;
  var ONE_SECOND = 1000;

  var events = [
    "mouseup", 
    "keydown", 
    "scroll", 
    "mousemove"
  ];
  var startTime = Date.now();
  var endTime = startTime + INITIAL_WAIT;
  var totalTime = 0;
  var clickCount = 0;
  var buttonClicks = {
    total: 0,
  };
  var buttonClickCount = 0;
  var linkClickCount = 0;
  var keypressCount = 0;
  var scrollCount = 0;
  var mouseMovementCount = 0;
  var linkClickCount = 0;

  setInterval(function () {
    if (!document.hidden && startTime <= endTime) {
      startTime = Date.now();
      totalTime += ONE_SECOND;
      document.getElementById("timer").innerHTML = formatTime(totalTime);
    }
  }, ONE_SECOND);

  document.addEventListener("DOMContentLoaded", function () {
    document.getElementById("page").innerHTML = window.location.pathname;
    events.forEach(function (e) {
      document.addEventListener(e, function () {
        endTime = Date.now() + INTERVAL_WAIT;
        if (e === "mouseup") {
          clickCount++;
          document.getElementById("click").innerHTML = clickCount;
          if (event.target.nodeName === 'BUTTON') {          
            if(!buttonClicks[event.target.innerText]){
              buttonClicks[event.target.innerText] = 0;
            }
            buttonClicks[event.target.innerText] += 1;
            buttonClicks.total += 1;
            document.getElementById("button").innerHTML = JSON.stringify(buttonClicks, null, 2);          
          }
          else if (event.target.nodeName === 'A') {
            linkClickCount++;
            document.getElementById("link").innerHTML = linkClickCount;
          }
        }
        else if (e === "keydown") {
          keypressCount++;
          document.getElementById("keypress").innerHTML = keypressCount;
        }
        else if (e === "scroll") {
          scrollCount++;
          document.getElementById("scroll").innerHTML = scrollCount;
        }
        else if (e === "mousemove") {
          mouseMovementCount++;
          document.getElementById("mouse").innerHTML = mouseMovementCount;
        }
      });
    });
  });


  function formatTime(ms) {
    return Math.floor(ms / 1000);
  }

</script>




See also

When you purchase through links on techighness.com, I may earn an affiliate commission.