How I removed google analytics and still have good data to analyze. It was just recently, that I opened my google analytics account and added it to this website. I wanted to get some insights, about my website’s visitors. But compared to the google search console, there was not much information interesting to me.

And actually I worried a little. Is it legal to just add analytics? analytics was easy to add, just adding a script tag into my page. In EU it is needed to inform the user about non essential cookies. Before setting one, it is needed to ask the users consent. However, analytics got added using a static html tag and there is no way to control what cookies are set immediately.

I was not sure if I should create that script tag dynamically after asking the user, using some client side javascript. and would analytics still work?

On the internet when searching for analytics without cookies there are many websites advising to use motomo. It is a very good solution made with php and mysql. But for my little blog setting up this server seem a little to much. Also because I would have to look that I keep it up do date and do some more security measures. For real production application, google analytics and motomo, both will be a better choice recording lots of data you don’t know now you want to have in the future.

My Solution to do Analytics without Analytics

I added a little script into my website. Instead of cookies it uses local storage. local storage can not be used to track users across other websites. So I think this should comply with the law. Also in the storage there is nothing stored to identify the user.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

// analytics
const lastViewTime = parseInt(localStorage.getItem('lastViewTime')) || 0;
const viewCount = parseInt(localStorage.getItem('viewCount')) || 0;
const lastViewPage = localStorage.getItem('lastViewedPage') || '';

localStorage.setItem('lastViewTime', Date.now())
localStorage.setItem('viewCount', viewCount+1)
localStorage.setItem('lastViewedPage', document.location.href);

fetch('/api/pageViews', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
page: document.location.href,
viewCount,
time: Date.now(),
lastViewTime: lastViewTime,
lastViewPage: lastViewPage,
userLanguage: navigator.language,
userAgent: navigator.userAgent,
referrer: document.referrer,
dayTime: parseInt(req.body.dayTime+''),
})
})
.then( r => r.json())
.then(data => console.log('pageViewResult:', data);

On the server I just dump this information into a jsonl file, meaning one json log entry each line. It can easily be converted to csv for analyses via excel. Draw some charts or count per interval weekly and monthly interval.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const router = require('express').Router();
module.export.pageViewRouter = router;

const file = fs.createWriteStream(fileName, {
flags: 'a' // 'a' means appending (old data will be preserved)
});

router.post('/api/pageViews',async (req,res) => {
res.json(true);
file.write(JSON.stringify({
page: body.page,
time: Date.now(),
userLanguage: (req.body.userLanguage+'').substr(0,500),
userAgent: userAgent.id,
viewCount: parseInt(req.body.viewCount),
lastViewTime: parseInt(req.body.lastViewTime+''),
lastViewPage: req.body.lastViewPage,
referrer: req.body.referrer,
dayTime: new Date().getHours()
})+'\n', (err)=>{
if(err) console.log(err)
});
});

Do you see, that I do not check if the browser supports the fetch API and modern arrow functions? I was thinking about it, and decided that I don’t need to care about old browser compatibility for this optional feature.

You see all the fields that are getting stored. These are what I came up with. That I think are interesting. To be honest, the API shown is not exactly the one running at tnickel.de, but the concept is this. On my running implementation I validate the received data, store urls and user agent string into a separate json file database and write the id into the log file. But with this example you can understand how you can implement the server side yourself.

How others do it

As by chance: The dev.to community, was just asked about analytics tools. And I described my little solution. The comment received a reply by Charanjit Chana, saying he is using a similar solution, here is what I found on his websites source code (it was minified, so I formatted it a little):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function allowedToTrack() {
return !(window.doNotTrack || navigator.doNotTrack || navigator.msDoNotTrack || window.external && "msTrackingProtectionEnabled" in window.external) || "1" != window.doNotTrack && "yes" != navigator.doNotTrack && "1" != navigator.doNotTrack && "1" != navigator.msDoNotTrack && !window.external.msTrackingProtectionEnabled()
}
if (allowedToTrack()) {
let o = Math.floor(8999999 * Math.random()) + 1e6;
let n = window.innerHeight + "x" + window.innerWidth;
// this request then set the cookie.
fetch("https://123.charanj.it/xyz/api/" + o + "/false/" + n);
}

if (void 0 !== console) {
console.log("%c👋 Hey!", "font-size: 16px; font-weight: 600");
console.log("%cIf you can see this I would love to hear from you.", "font-size: 16px;");
console.log("%cYou can find me at https://twitter.com/cchana.", "font-size: 16px;");
console.log("%cUse the hashtag #cchanaconsole", "font-size: 16px;");
console.log("%c🤙 🖖", "font-size: 16px;");
}

Seems as head of development he is interested in finding new developer talents for his team. I like the allowToTrack function used before the analytics request is made. This request then set a cookie, so multiple page views can be related to the same user and session. I don’t know about the rules in England after it left the EU, but I believe in Germany, an additional popup banner would be needed. Other than me, Charanjit is interested in the users screen resolution to know what to optimize the page for.

How do you analytics on your website?

You now have seen two valid approaches to building the client side for collecting analytics information. With this article, I hope you find how how this website does analytics, without tracing the users all over the internet and even into their darkest dreams.

Contents
  1. 1. My Solution to do Analytics without Analytics
  2. 2. How others do it
  3. 3. How do you analytics on your website?