DEV Community

Cover image for Analytics with vanilla JS: page view duration
Ziga Brencic
Ziga Brencic

Posted on • Originally published at

Analytics with vanilla JS: page view duration

Third post in series: Analytics with vanilla JS

Page view duration is essential in determining whether our users read the content of our article or not.

To determine the time of user page visit, we need to detect two events:

  • page view start time: t_page_opened
  • page view end time: t_page_closed

Request page, close page

We first cover the case of page view duration, which is the easiest to measure.

Alt Text

Let's say the user clicks a link or types the address of our web page to the web browser. The user will land on our web page. The page files will be sent over from the server that hosts the web site.

In this case, when the page is loaded, we can detect onload Java Script event and determine that as the start of page visit with:

window.onload = function () {
    t_page_opened = new Date();

Now let's say that the user leaves the web page by closing the browser tab or browser window. We can detect that via beforeunload event by adding the event listener:

window.addEventListener("beforeunload", leftWebSite);

leftWebSite function then get's the time stamp when user left the page:

function leftWebSite() {
    const t_page_closed = new Date();

    const data = JSON.stringify({
        "page_opened": t_page_opened,
        "page_closed": t_page_closed
    post_data(data, "define_URL");

and sends the t_page_opened and t_page_closed to the a prediefined URL with post_data function:

function post_data(data, url) {
    let xhr = new XMLHttpRequest();"POST", url, true);
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {

Job done, right? Far from it.

If we want to have a proper estimate of the read times, we need to be really careful about potential corner cases for page opening and page closing.

Wait? Page view start and page view end should be determinable in a few lines of code. Not quite.

User leaves the web site

Alt Text

What if the user left the page via a link, history forward or history back button, lost internet connection, refreshed the web page. In those cases, beforeunload won't get consistently triggered (from browser to browser).

Let's list the cases we need to cover. When the user leaves the page via:

  • Browser tab/window closing: detected via beforeunload. Solved.
  • internal or external link: detectable via onclick event
  • internet connection lost:
    • connection reestablished during page view: no issue
    • user revisits a page in the future: fetch view data from user browser localStorage if the user didn't clean it
    • the user never comes back to our site: data lost
  • page refresh: can be detected with the help of localStorage
  • page left via history back, forward button: using pagehide event, since page JS won't be re-loaded and beforeunload event won't be triggered.

Keep in mind that the solutions that use localStorage won't work if the user:

  • disabled the use of local storage,
  • uses incognito browser mode.

User opens the web site

To detect if the user opened the web site is slightly easier. There are just three cases to handle:

Alt Text

We already handled the first case with onload. To handle the page left via history back, the forward button, we again use pagehide event.

Tackling edge cases

In the upcoming articles we'll cover the code needed for:

  • detecting: page refresh, history button clicks, internal-external links
  • detection of incognito mode
  • detection of internet connection loss

But even after we handle all of those cases, we won't ensure the correct estimate of reading time. What if the user opens the web page, leaves it open and goes to the toilet. Or scrolls through the article really fast. Well, we could monitor page scrolls. This way, we could eliminate a few more edge cases that could corrupt our read time estimates and analysis. Stay tuned.

Top comments (0)