Tutorials

Tracking Blog Reading Time and User Registrations with Custom Analytics Events

Tracking Blog Reading Time and User Registrations with Custom Analytics Events

Flowsery Team
Flowsery Team
2 min read

TL;DR — Quick Answer

2 min read

Custom events let you measure real blog readership (scroll depth + reading time) and track server-side registrations accurately -- going far beyond basic pageview metrics.

Custom event tracking opens up powerful possibilities beyond basic page views. This guide covers two practical use cases: measuring how long visitors actually spend reading your blog posts, and reliably tracking user sign-ups from the server side.

Measuring Blog Article Reading Time

Standard page view analytics tell you that someone visited a post, but not whether they actually read it. By combining scroll tracking with time-on-page calculations, you can determine genuine readership.

Defining "Fully Read"

An article counts as fully read when two conditions are met: the visitor has spent enough time on the page to have plausibly read the content, and they have scrolled to the bottom. The minimum reading time is derived from the article's word count, using an average reading speed of roughly 200-220 words per minute.

Implementation Steps

1. Add the events tracking script

Include your analytics platform's event tracking snippet in the <head> of your pages. If you use a static site generator like Hugo, this goes into your base template.

2. Attach article metadata

On each article page, include a small script element that carries the article title and word count as data attributes:

<script type="text/javascript" src="/js/article.js"
    id="article"
    data-title="Your Article Title"
    data-words="1200"></script>

3. Write the tracking logic

The script needs to do three things:

First, calculate the scroll position to detect when the reader reaches the bottom of the article:

function getScrollPercent() {
    const h = document.documentElement,
          b = document.body,
          st = 'scrollTop',
          sh = 'scrollHeight';
    return Math.floor((h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 100);
}

Next, on page load, read the word count and title from the data attributes and compute the minimum reading time:

window.addEventListener("DOMContentLoaded", () => {
    const script = document.getElementById("article");

    if(script &&
        script.hasAttribute("data-words") &&
        script.hasAttribute("data-title")) {
        const title = script.getAttribute("data-title");
        const minReadingTimeSeconds = Math.floor(
            parseInt(script.getAttribute("data-words")) / 220
        ) * 60;
        const start = new Date().getTime();
        let done = false;

Finally, listen for scroll events. When the visitor scrolls past 85% of the page and has spent at least the minimum reading time, fire a custom event:

        window.addEventListener("scroll", () => {
            if(!done && getScrollPercent() > 85) {
                let readSeconds = Math.floor(
                    (new Date().getTime() - start) / 1000
                );
                if(readSeconds >= minReadingTimeSeconds) {
                    done = true;
                    // Send custom event with duration and article title
                    trackEvent("Read article", {
                        duration: readSeconds,
                        meta: { title }
                    });
                }
            }
        });
    }
});

4. Review the data

Once events start flowing in, they appear in your analytics dashboard. Open the detailed event view to see which articles are being read and the average time visitors spend on each one.

Tracking User Registrations from the Backend

Front-end conversion goals that fire when someone visits a confirmation page are unreliable since anyone can navigate directly to that URL. A more accurate approach is to send a custom event from your server only after a registration is actually confirmed.

Flowsery
Flowsery
Flowsery

Real-time dashboard

Goal tracking

Cookie-free tracking

Here is an example in Go:

func SignUp(w http.ResponseWriter, r *http.Request) {
    // Validate captcha, create user account, etc.
    if err != nil {
        // Handle error
    } else {
        go func() {
            if err := analyticsClient.Event("Registration", 0, nil, r); err != nil {
                // Log error
            }
        }()
    }
    // Render the response page
}

By firing the event only on a successful account confirmation, you get a trustworthy count of real sign-ups rather than inflated numbers from incidental page visits.

Key Takeaway

Custom events let you measure virtually anything that matters to your business. Just be careful not to attach personally identifiable information to events, as that would undermine the privacy benefits of cookieless analytics.

Was this article helpful?

Let us know what you think!

Before you go...

Flowsery

Flowsery

Revenue-first analytics for your website

Track every visitor, source, and conversion in real time. Simple, powerful, and fully GDPR compliant.

Flowsery

Real-time dashboard

Goal tracking

Cookie-free tracking

Related Articles