generate statistics on the number of audience minutes your site is generating, and if readers make it to the end of your screeds

Overview

audience-minutes

generate statistics on the number of audience minutes your site is receiving, and if readers make it to the end of your screeds.

“If we have data, let’s look at data. If all we have are opinions, let’s go with mine.” - Jim Barksdale.

There is some sample data linked from the end of this file

What is this?

If you publish articles, you probably want to know if people are reading them. You can count raw hits but especially if you aren't drawing a lot of traffic, many of these hits are actually bots and crawlers.

In addition, that the page got loaded doesn't tell you if the visitor actually read your work.

Some time ago I was involved with a Dutch newspaper article, and they could tell me how many minutes of reading time it had generated. And this made me somewhat jealous.

With these three scripts, you can instrument your pages with a tiny bit of javascript that probabilistically samples if a reader was active over the past minute (mouse/touch movement or scrolling). In the default settings, 10% of every active minute will be reported.

Or in other words, if you get 10 reports, something like 100 minutes was spent reading your site. Sorta.

In addition, these reports measure at what percentage of the content your reader is positioned. This helps you determine if people are making it to the end of your page or not.

At the end of this page I've included some discussion how to interpret the data.

Privacy

These scripts use no cookies and no local storage. There are no identifiers. You can run this without having to add a cookie or GDPR banner etc. However, I personaly prefer to sample as little as possible. Many sites will track your every click, and even note if you switch to another tab. I find that somewhat upsetting.

You can tailor your level of intrusiveness with the reportingProbability setting. The busier your site is the lower you can set this at and still have decent statistics.

Javascript

Insert or link audience-minutes.js from all pages you want to measure on. There are some settings at the beginning of the file where you can tweak how intrusive you want the measurements to be. In other words, do you want to sample 10% of every viewing minute? Or 1%? The busier your site is the lower you can set this.

In the same place where you put the javascript file, also put an empty file called report.json. This will receive reports of active minutes. If you don't generate this file, the browser console will show 404s which is ugly.

The easiest way to parse the results is to grab them from an access.log file.

AWK

Yes, AWK! With this little script you can trawl your access.log files and generate a CSV file that only has URLs, scroll percentages and minute counts.

This CSV file has no privacy considerations, there are no IP addresses in there. Unlike your original access.log.

Jupyter notebook

To turn the CSV file into a graphs, use this Jupyter script, from which you can also extract Python 3 if you don't want to run Jupyter. It is based on Pandas and Matplotlib.

How to interpret the results

For starters, you'll notice that even quite high visitor numbers translate into not that many "audience minutes". This is not due to this script, it is a common disappointment. So if your calculations show that an article had 100 reading hours, this actually is quite a lot.

For obvious reasons, professional media operations are not very forthcoming with these statistics on their readership. One big newspaper article I worked on garnered 75 confirmed reading hours, for example.

So why are these numbers so low? For starters, you may not be seeing all readers. Perhaps the script doesn't fire on all devices. I've done some research, I don't think this is a major factor. But it could be.

On the other hand, there is a ton of automated traffic coming to sites these days, lots of crawlers, bots, strange scanners etc. Mind you, some of these will even execute Javascript! But most won't. This non-human traffic may have been inflating your numbers previously.

In terms of the graph, if you have a ton of data, interpretation is easy. I find that you can even see where you put big photos in an article - these sections do not get a lot of reading minutes.

If you have less data, you need to reduce the number of 'bins' in the histogram. I find that 10 bins work pretty well for general conclusions, and that might get you this:

If you get this, you can conclude that 1) most people that visited the URL actually wanted to read this kind of content and 2) most readers made it to the end of your article. The profile is mostly flat, with only some drop-off near the end, and no suspicious peak at the beginning.

Contast this with:

This was an article that was extremely popular on HackerNews and a few other places. But we can see that readership clearly peaked in the first 10%. Lots of people decided that they had read enough at that point. This is caused by how the article got promoted, and it is not necessarily the "fault" of the writer.

If we ignore the "mistargeting", from that point on, almost everyone makes it to the end of the article.

Sample data

If you want to help improve these small tools, but you don't yet have a lot data to work with, please find attached two weeks of data collected by berthub.eu/articles in the sample-data directory.

You might also like...

Job queues and scheduled jobs for Node.js, Beanstalkd and/or Iron.io.

Ironium Job queues and scheduled jobs for Node.js backed by Beanstalk/IronMQ/SQS. The Why You've got a workload that runs outside the Web app's reques

Dec 14, 2022

Bree is the best job scheduler for Node.js and JavaScript with cron, dates, ms, later, and human-friendly support.

Bree is the best job scheduler for Node.js and JavaScript with cron, dates, ms, later, and human-friendly support.

The best job scheduler for Node.js and JavaScript with cron, dates, ms, later, and human-friendly support. Works in Node v10+ and browsers, uses workers to spawn sandboxed processes, and supports async/await, retries, throttling, concurrency, and graceful shutdown. Simple, fast, and lightweight. Made for @ForwardEmail and @ladjs.

Dec 30, 2022

Type-safe and Promisified API for Web Worker and Iframe

💛 You can help the author become a full-time open-source maintainer by sponsoring him on GitHub. typed-worker Install npm i typed-worker Usage Create

Dec 31, 2022

Premium Queue package for handling distributed jobs and messages in NodeJS.

Premium Queue package for handling distributed jobs and messages in NodeJS.

The fastest, most reliable, Redis-based queue for Node. Carefully written for rock solid stability and atomicity. Sponsors · Features · UIs · Install

Dec 31, 2022

Redis-backed task queue engine with advanced task control and eventual consistency

idoit Redis-backed task queue engine with advanced task control and eventual consistency. Task grouping, chaining, iterators for huge ranges. Postpone

Dec 15, 2022

A fast, robust and extensible distributed task/job queue for Node.js, powered by Redis.

Conveyor MQ A fast, robust and extensible distributed task/job queue for Node.js, powered by Redis. Introduction Conveyor MQ is a general purpose, dis

Dec 15, 2022

Example repo for getting NextJS, Rust via wasm-pack, and web workers all playing nicely together.

Example of integrating WASM & web workers with a Typescript NextJS project. Running yarn yarn dev Open localhost:3000 Layout Rust code is in ./rust, g

Dec 23, 2022

Challenge [Frontend Mentor] - In this challenge, JavaScript was used to filter jobs based on the selected categories. Technologies used: HTML5, CSS3 and React.

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Apr 13, 2022

A simple package for single or batch image download and conversion using node streams.

image-batch-download A simple package for basic image downloading and processing. Supported formats: JPEG PNG WebP Installation With Yarn: yarn add im

Jan 2, 2022
Comments
  • access log for Github Pages

    access log for Github Pages

    Hi -- I want to use this js snippet for my personal website hosted via github pages, but I don't think github pages (xyz.github.io) provide access.log files -- is there a workaround to this? Thanks!

    opened by suryabulusu 0
  • Make 'scroll' event handler passive

    Make 'scroll' event handler passive

    See https://makandracards.com/makandra/487215-passive-event-listeners-may-speed-up-your-scroll-and-touch-events and https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners for a suggested test for compatibility

    opened by jbemmel 2
Cloudflare Worker to make a R2 Bucket public!

r2-public-worker A Cloudflare Worker to make your R2 bucket public! Minimum Requirements Cloudflare Account wrangler >= 2.0.2 Note: Ensure you are usi

Cole Mackenzie 20 Sep 19, 2022
Build and deploy a roadmap voting app for your porject

Roadmap Voting App You can deploy Roadmap application yourself and get feedback from your users about your roadmap features. See the live example. In

Upstash 91 Jan 3, 2023
Making service workers easy so that your app is fast and reliable, even offline.

tulo.js Making service workers easy to use so that your app can be fast and reliable, even offline. Welcome to tulo.js, a service worker library that

OSLabs Beta 37 Nov 16, 2022
Out of the box modern User Interface, so you can see and manage your Workhorse jobs in realtime

WORKHORSE UI Out of the box modern User Interface, so you can see and manage your Workhorse jobs in realtime. Start local Run npm i Copy and name prox

Workhorse 2 Apr 15, 2022
⚡️ Supercharge your ViewComponent development process 🚀

L ?? kbook ⚡️ Supercharge your ViewComponent development process ?? About Lookbook provides a ready-to-go UI for navigating, inspecting and interactin

Mark Perkins 466 Dec 26, 2022
Use Cloudflare Workers Cron Triggers to keep your Hetzner Cloud Firewall allowing the latest list of Cloudflare IPs, or any other lists!

Hetzner Cloud Firewall automation with Cloudflare Workers Heavily inspired by xopez/Hetzner-Cloud-Firewall-API-examples, this repository holds a Cloud

Erisa A 9 Dec 17, 2022
Build your Cloudflare Workers with esbuild.

build-worker Bundle your Cloudflare Worker with esbuild instead of webpack. (It's ridiculously faster!) Wrangler v1 uses webpack. Wrangler v2 is using

Rom 7 Oct 24, 2022
A Remix.run stack to monitor your BullMQ queues

Remix Matador stack A bold interface that helps you monitor your BullMQ queues. Learn more about Remix Stacks. $ npx create-remix@latest --template nu

Andrea 19 Dec 15, 2022
Adds clap button (like medium) to any page for your Next.js apps.

@upstash/claps Add a claps button (like medium) to any page for your Next.js apps. Nothing to maintain, it is completely serverless ?? Check out the d

Upstash 49 Nov 23, 2022
A bot that notifies you on Slack whenever your company/product is mentioned on Hacker News. Powered by Vercel Functions & Upstash.

Hacker News Slack Bot A bot that notifies you on Slack whenever your company/product is mentioned on Hacker News. or deploy your own Built With Vercel

Vercel Labs 162 Jan 3, 2023