We have a new blog post on Debusine to share with you!
It's our first design story for the UI, covering our unique approach towards JavaScript. It goes into detail on how to avoid having Debian infrastructure depend on it, how to integrate interactive widgets with Django, and how to keep complexities down to make Debusine code easier to write and to maintain.
Read more about us using JavaScript in Debusine without depending on JavaScript: https://www.freexian.com/blog/debusine-and-javascript/
Mysterious #javascript question that is harder than it looks:
What does jest.mock(module_path) do?
Not what effect is intended by it. Not what is it for. What does it ACTUALLY DO? What entity at runtime or compile time is changed and in what way?
I've dabbled in #rust and alot of my favorite projects these days are in Rust, like #niri I suck as an application developer. But backend stuff that nobody sees is my art. Because I'm an architect. If I need down to metal language, I use #pascal. For more backend-ey stuff I use #python because #javascript sucks, but I'm LOVING #lisp as a pocket knife that can do everything. But all these beautiful TUI apps are in Rust. They are just beautiful. And I avoid GUI apps when possible.
Behind The Scenes of Bun Install
https://bun.com/blog/behind-the-scenes-of-bun-install
Super interesting read, not just for people into #javascript and #bun but also anyone into optimizing systems programming tasks.
I love #Remarkjs for creating #slides from #Markdown, that is, until I noticed the library is ~650 kB. So, then I went full on #FrugalComputing and looked for the smallest #HTML #presentation library...
That honour, AFAICT, goes to Mark Dalgleish's modular #Bespokejs. The #Yeoman generator failed for me, but with a little perseverance I hand coded a demo:
https://blog.harlow.net.nz/presentations/
that only required 8 kB of #Javascript. Remarkably, that's 1/80th of Remark.js!
“This kind of book is not just a book: this is full of wonders and interesting territories you would like explore and spend some time it.
“You’d like to try these out, build a new toy, play with it, compare it to your well known solutions, try to break it, find its strengths and weak points.”
—pxbdgn on Reddit, 2019
blog! “Reasonably accurate, privacy conscious, cookieless, visitor tracking for WordPress”
I am vain. I like to know which of my blog posts have "done numbers". I get a little thrill knowing that an old post I wrote has been read by someone in a land I've never visited. I'm curious and want to know if a newsletter has…
Read more: https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/
⸻
#HTML #javascript #seo #WordPress
Reasonably accurate, privacy conscious, cookieless, visitor tracking for WordPress
I am vain. I like to know which of my blog posts have "done numbers". I get a little thrill knowing that an old post I wrote has been read by someone in a land I've never visited. I'm curious and want to know if a newsletter has linked to me.
At the same time, I don't want to know too much about people. I don't want to stalk them around the web. I refuse to care how long they spend with me. I can't be bothered setting up a foolproof system that captures 100% accurate information.
After trying several analytics plugins for WordPress, I've decided to have a go at writing my own0.
Before embarking on this, please do read "You Don't Need Analytics on Your Blog" and the slightly more provocative "You do not need “analytics” for your blog because you are neither a military surveillance unit nor a commodity trading company". Both give excellent examples of why this is at best foolish and at worse injurious. Proceed with caution in your heart.
Background
As a consequence of the way the web works, every time you click on a link the website's owner gets the following pieces of information.
There are a few other things sent along but they're not interesting to me.
Using that information, I can construct a reasonably accurate view of how many times a post has been viewed and how many people viewed it.
Defining a page view
If a web page is loaded, that counts as a view. I'm not going to track whether the user stayed for more than 30 seconds or closed their browser in disgust after reading the headline. If the page is loaded, that's a view.
But what if one person repeatedly hits refresh on the same post? To deal with that, I'll need a concept of a visitor.
Defining a visitor
The "normal" way of doing things is to stick a cookie in the user's browser and track them that way. I can't be bothered with that. And, besides, it doesn't account for a person reading on their laptop and then moving to their phone.
So I'm going to use a proxy by creating a cryptographic hash of the visitor's IP address and the browser's User Agent string.
Of course, a household might have one IP address and multiple people with the same phone. But, equally, one person might rove over several WiFi networks in the course of one browsing session, getting a different IP each time.
The aim is to be reasonably accurate.
Hashing the contents means I don't need to store the user's IP address. Once hashed, the information becomes a string like db050e7b853e5856
which is functionally impossible to crack back to an IP address & UA string1.
This also means that I can redefine the concept of a page view. If the same visitor refreshed the page multiple times, it will only count as a single visit.
I'll reset the counter at midnight in my local timezone. If someone visits just before midnight and then just after, it'll count as two visits. Oh well.
Where did they come from?
Generally speaking, there are two ways that visitors share their referrer. One is the "referer" header (yes, it is misspelled). It contains a URl of the referring site or application. For example, if someone clicked from a search result it might say https://yahoo.com
.
The other way is using "Urchin Tracking Module" query strings. At the end of the URl they visit, they might append something like ?utm_source=alices-newsletter
.
Some sites, like Reddit, might use multiple subdomains - old.reddit.com
or out.reddit.com
- so some deduplication may be necessary.
Where in the world are they?
A user's IP address is somewhat accurate method of detecting their location. Yes, users could be proxying through a VPN or using a SIM card from a foreign country. But this isn't an exercise in precise tracking. Rough and ready is fine.
There are a variety of GeoIP Databases which are updated semi-regularly. I'm only interested in the country of origin, I don't care about finer resolution than that.
Again, the aim isn't precise targetting. I'd just like to know that people in Sudan ever read my blog posts.
What else could we use?
It might be nice to know if someone is using a small-screen or large device. But my CSS is responsive, so I don't care.
Similarly, their Internet connection speed might be available. But, again, I try to optimise things so that isn't necessary to know.
Do I need to know if someone speaks Hungarian? No. There's nothing useful I can do with that information.
Could I extract their operating system, device, and browser from their User-Agent? I guess. Would I use the information that X% of my readers use Firefox on Linux? Doubtful!
Collect the information
There are two main methods of collecting these data.
First is a "no JavaScript" solution. This tells the browser to request an image which has a query string to send along the details of the page requested.
PHP<noscript> <img src="/tracking.php?ID=<?php echo $postID ?>" alt="" width=1 height=1 class=hidden></noscript>
The downside is that there's no way to capture referer information. If each page were dynamically generated, I could grab it from PHP's $_SERVER
superglobal. But my website is heavily cached, so that isn't possible.
It is possible to use JavaScript to dynamically send the information for collection:
JavaScriptlet formData = new FormData();formData.append("HTTP_REFERER", document.referrer);formData.append("ID", <?php echo $postID ?>);fetch("/tracking.php", { method: "POST", body: formData,});
This approach has three distinct advantages.
Bot Detection
Not all traffic originates from humans. There are lots of bots which crawl the web. Some are useful - like search engines building up a map. Others are harmful - like AI agents aggressively scraping content to plagiarise.
There are lots of identifiable bots out there - and more which obfuscate themselves. There are some, like Lighthouse which cloak themselves.
I'm not trying to eliminate everything which could be a bot. I am trying for reasonably accurate. So I eliminate any User-Agent which contains:
"/bot|crawl|spider|seo|lighthouse|facebookexternalhit|preview|HeadlessChrome/i"
There are some big lists of bots you can use - but they don't seem to trigger my analytics because they aren't requesting the images or executing the JS.
What bits of the site to measure?
I only care about how many visitors my posts and pages get. I don't need to know if someone visited a tag page, or scrolled back to page 100 of posts from 2019. Those sorts of deep pages are usually only accessed by bots anyway.
I also don't want to count visits from me, myself, and I.
So the tracking is only inserted on single pages which are viewed by non-admins:
PHPif ( is_singular() && !current_user_can( "edit_posts" ) ) { …}
Oddities
Sometimes, the URl requested will look something like: https://shkspr-mobi.translate.goog
- that just means Google has translated it.
Sometimes, the referer will look something like: android-app://com.google.android.gm/
- that just means they clicked from an Android app.
Sometimes, the URl requested will include a fragment or a query string - they can be ignored.
Sometimes, the utm_
will contain all sorts of weird stuff. It isn't always possible to pull out exactly where it has come from.
Sometimes, the referer and utm_
will disagree. Ah well, never mind.
Sometimes, RSS views are counted and sometimes not. Perhaps I should fix that?
Sometimes, users block trackers or use a text-only browser. That's fine, they can keep their secrets.
Saving the data
I started this by just shoving what I collected into a CSV.
PHP// Write the CSV.$line = [date("c"), $ID, $UA, $referer, $domain, $country, $user];// Date-based filename.$filename = "log-" . date("Y-m-d") . ".csv";// Append mode.$handle = fopen( $filename, "a" );fputcsv( $handle, $line );fclose( $handle );
Nothing fancy. Something easily grepable with the ability to query it in more detail if I need. At the number of hits that my site gets, it is less than 1MB per day.
I've since moved it into a single MySQL table. That might not be sustainable with hundreds of thousands of rows. But that's tomorrow's problem.
Accuracy
I've been running this for a couple of days - simultaneously with my other, more professional, stats plugin. It is within 5% accuracy. It appears to slightly exaggerate the number of visitors and undercount my page-views. That's good enough for my purposes and probably good for my ego!
Putting it all together
You can take a look at all the code on my GitLab repo.
What does it look like?
If you've made it this far, you can have a little pictorial treat! Aren't you lucky?
What's next?
For now, a simple table structure is fine. I've shoved it in a basic database. Sure, I don't have any indexes or fancy stuff like that. But modern computers are pretty fast.
Eventually I'll need to create some new tables which will consolidate the data. Perhaps a table for individual posts, using date and country? Or maybe referer? I'll have to see.
I also need a way to get historic data into it. I've blog stats going back to 2009 which I am anxious not to lose.
And, yeah, I'll need a better front-end than manually running SQL queries.
Above all, I want to keep it simple enough that my puny mortal brain can understand it after several years of not touching anything. I want to build something which can run without constant maintenance.
Remember, this is only an exercise in self-learning, self-hosting, and self-respect.
I enjoy learning. If you're about to say "Why not just install…" then you've missed the point. I like understanding how things work, I get joy from discovering some new function, my brain feels happy when it is working on a problem. I don't want to just click install, hit next a few times, and fiddle with a few options. I've written more about my philosophy here. ↩︎
Or is it? There are 4 billion IPv4 addresses - although slightly fewer in actual use. Creating a rainbow table with 4 billion rows is possible if I was just using IP addresses. But there are an almost infinite variety of User Agent strings. It is probably possible to create a rainbow table of, for example, the 10 most popular UAs, concatenate them with every possible IP address, and then see which hashes to 65fef01fef257963
. But even then, what would that get an attacker? Knowing that the most popular model of iPhone is on a mobile network's IP range isn't exactly private information. ↩︎
been doing some cad
3d printing is fun!!
look at this cool little guy!!
(i've been using https://jscad.app, it's been really nice overall)
18 Popular Code Packages #Hacked, Rigged to Steal #Crypto
At least 18 popular #JavaScript code packages that are collectively downloaded more than two billion times each week were briefly #compromised with #malicious software today, after a developer involved in maintaining the projects was #phished. The #attack appears to have been quickly contained and was narrowly focused on stealing #cryptocurrency.
#security
https://krebsonsecurity.com/2025/09/18-popular-code-packages-hacked-rigged-to-steal-crypto/
Aircall is hiring Senior Software Engineer - Bellevue
#javascript #python #ruby #typescript #aws #azure #gcp #seniorengineer
Seattle, Washington
Full-time
Aircall
Job details https://jobsfordevelopers.com/jobs/senior-software-engineer-bellevue-at-aircall-io-jan-23-2025-bd6339?utm_source=mastodon.world&utm_medium=social&utm_campaign=posting
#jobalert #jobsearch #hiring
kripken/ammo.js: Direct port of the Bullet physics engine to JavaScript using Emscripten
Very sophisticated physics engine
Here's a little #game from my 20 years in #JavaScript #development: A #retro #remake of Stone Raider II, from the #Dragon32 (a game which, itself, was a
remake) https://www.marquisdegeek.com/stoneraider2 #html5 #canvas #game
#quickhacks #retro