1

I am currently developing a feature for my web application that tracks the amount of time a user spends on a specific page. Our backend is built with Django, and the frontend is using React and PostgreSQL as the database. I'm looking for advice on the best practices or approaches to implement this feature efficiently.

I have implemented a system where a REST API is called every three seconds and each time creates a new record, then We aggregate the total time spent by all users on each page. However, I believe there might be a more efficient and accurate way to handle this.

I didn't find any platforms that helps me to do this with the details that I need.

3
  • You probably want to use the Beacon API when the user leaves the page: developer.mozilla.org/en-US/docs/Web/API/Navigator/…
    – amon
    Commented Jan 29 at 16:14
  • @amon been discussing about this with my front team and they said when user closes the tab there is no way to access the request and handling it that way is not good. That's why i did the 3 second approach. is that Beacon actually a good way to do this?
    – scaryhamid
    Commented Jan 29 at 16:43
  • 2
    The intention of sendBeacon() (or fetch() with keepalive) is that the HTTP request gets sent successfully even if the tab is closed during sending. That is, the HTTP connection can outlive the tab. This was specifically designed for such analytics purposes. Your design with requests every N seconds will work as well, of course, and might be more robust on flaky connections. On the backend side, you don't have to create a new DB row for each even, instead you can update the existing row with a new total time (but that might be a bit slower on Postgres).
    – amon
    Commented Jan 29 at 18:01

1 Answer 1

1

As @amon helpfully explains, the Beacon API was designed for this use case:
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon#sending_analytics_at_the_end_of_a_session
It allows for collecting summary stats even after CMD-W dismisses a browser tab. No, sorry, it won't help with kill -9 sent to browser, but that's life.

If for some reason you choose to keep sending 3-second pings, you might prefer to have the server send such updates to a local Redis, instead of Postgres. Every so often have a daemon read the final elapsed time measurements from Redis and perform INSERT / UPDATE transactions. We're just taking advantage of the fact that Redis makes weaker promises, and we don't need to pay the ACID tax once per ping, when once per session suffices.

2
  • Thanks, this answer is good and we probably gonna use this approach. but still looking for other possible ways as well.
    – scaryhamid
    Commented Jan 30 at 16:15
  • 1
    Ummm, maybe have a JS thread do frequent set cookie operations, which keep updating 2nd element of an (initialTimestamp, finalTimestamp) tuple. Downside is you don't get to learn about those timestamps until a subsequent visit, which is problematic if we're measuring whether the user "found content boring and abandoned the site". // I suppose a webworker thread could repeatedly postMessage() to tell whether a web page tab still exists, and contact your web server with a summary observation. // Really, beacons are best!
    – J_H
    Commented Jan 30 at 16:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.