## How to create your own web stats in the age of GDPR and Ad Blockers ![WebStats CLI](pic/status.png) In the days of the Old Web, getting to know your visitors was simple. You just throw some web counter code on the page, wait and see. After some time you would get some insights if your writings are actually read by anyone, or you should move on next project. These days are long over. Nowadays, there are [ad blockers](https://www.statista.com/statistics/874736/ad-blocker-usage-in-united-kingdom/), bots, and other stuff. Any popular analytics tool is very inaccurate. And also there are murky GDPR laws. For example, on this [blog](https://developer.run) [counter](https://developer.run/29) shows exactly zero visitors per day, Cloudflare Server Side logs shows hundreds of visitors, but the reality is somewhere in the middle. Recently Cloudflare released their own Client Side [Web Analytics](https://blog.cloudflare.com/privacy-first-web-analytics/). But they called their script `beacon.js`. Cmmon, scripts named `*beacon*` are usually first to be ad-blocked. If you have your own server, you can get real data using [GoAccess](https://goaccess.io). If you host elsewhere, your only option is to roll your own analytics. Because there is a very small chance of your uniq solution being blacklisted by ad blockers. Just be creative! Let me share a way how to homebrew super-simple analytics for free. First, you need some PAAS provider that allows storing functions (lambdas) and data. I recommend [Back4App](https://back4app.com) because they are great, and implement [Parse API](https://parseplatform.org) which is open and portable between platforms. Their free plan is great as well. Start with creating a [database](https://www.back4app.com/docs/get-started/add-get-data-with-back4app) called `Visitor`. That's where hits will be stored. Probably make sense to restrict [possibility to delete](http://docs.parseplatform.org/ios/guide/#security) for public to avoid vandals. Next you create a simple [function](https://www.back4app.com/docs/get-started/cloud-functions) which will be called from your website. Function will store visitors hits: ```javascript // Make sure to not store ip. Because you know, GDPR laws are murky and fines are scary. function hash(s) { return s.split('').reduce(function (acc, c) { return acc + c.charCodeAt(0); }, 0); } // Write to `Visitor` database we've just created const Visitor = Parse.Object.extend('Visitor'); Parse.Cloud.define("hello", function(request, response){ const token = hash(request.ip); const myNewObject = new Visitor(); myNewObject.set('token', token); myNewObject.set('url', request.headers['referer']); myNewObject.set('browser', request.headers['user-agent']); // As I'm using CloudFlare I can even get country data myNewObject.set('country', request.headers['cloudfront-viewer-country']); myNewObject.set('ref', request.params.ref); myNewObject.set('title', request.params.title); myNewObject.save() response.success("hello!"); }); ``` On your website host some script to call this cloud function. You can look at [mine](https://developer.run/hello2.js) for example. After that hits will be available as rows in the `Visitor` database. You can [view it in CLI](https://github.com/dmi3/bin/blob/master/status.sh) or connect to some dashboard. CLI using [jq](https://stedolan.github.io/jq/) and [spark](https://github.com/holman/spark) will show date, visitors, page views and countries. Will look like this: ``` 📈 Blog ▁▂▁▁█▄▃ "2020-10-16" 106 220 " AT AU CA CH CZ DE DK FR GB HU IE IT LV ME NL NO NZ PL "2020-10-17" 158 388 " AR AU BD BE BR CA CZ DE DK ES FI FR GB GU HU ID IL IQ "2020-10-18" 52 110 " AR BR CA DE DK DO ES FI FR GB IT JP LU LV NZ SE SG US "2020-10-19" 42 84 "AR AT AU BE BN BR CA CZ EG FR GB GR HU LV MX NL NZ US" "2020-10-20" 577 3960 " AE AR AT AU BA BE BG BR BY CA CH CL CO CZ DE DK EE ES "2020-10-21" 342 1603 " AE AR AT AU BE BG BR CA CL CO CZ DE DK EE ES FI FR GB "2020-10-22" 225 635 "AR AT AU BA BE BH BR BY CA CH CL CZ DE EG ES FI FR GB 🐦 Twitter 13 followers ``` 🏷️Cloudflare 🏷️Tip 🏷️Cli 🏷️Webmaster ---