"We take your privacy seriously."
I'm sure you've seen that phrase before and you are as skeptical about it as I am, so on this page, I'll explain some of the design choices that I've made for this site - the reasons for those choices - and how they relate to your privacy.
Hopefully you will agree that this blog is more privacy-conscious than most. That's the aim anyway.
TL;DR - the short read
In summary:
- I have tried to respect the privacy of visitors to my site and will continue to do so.
- There are no ads, tracking cookies or that type of rubbish.
- Somewhat ironically, the only cookie used by this site itself, is called
cookieconsent_status
, used to check if you have already dismissed the little message asking you to read this privacy page. :) - YouTube will set some cookies if you click the 'play' button on an embedded video in a post (if you don't want these YouTube cookies, don't play any videos in the posts).
- The
localStorage
feature of your browser is used - only by the search page - to cache content indexes for performance reasons (if you don't want this to happen, don't use the search page). - The site does not use Google Analytics or similar javascript-based analytics tools.
- Third party resources (e.g. web fonts and jQuery libraries) are loaded from this site's own domain (or subdomain for CDN-cached resources).
- Most images are loaded from the site's own domain(s) as well (see below for exceptions to this).
- Disqus is not used for comments, because it's big, bloated and Disqus has sometimes behaved very badly.
- Comment data on this site is not sent to any third parties.
The long(er) version
Sad, but true: I've spent (a lot) more time developing, enhancing, optimising, tweaking and fiddling with this blog, than I have spent time actually writing content for it.
This is a personal project for fun, and isn't designed to make any money, which means I have the luxury of not needing to try to "monetise my audience".
If the site eventually gets expensive to run, then I may request support via donations, I suppose.
How search works on this site - and why it uses localStorage
I've implemented ghostHunter search to enable you to search the blog's content. This is a client-side search tool, which performs all the indexing and searching within your browser. The server doesn't know what you're searching for, so your search terms remain private to you.
"What's the point in implementing a search facility when you have only a few articles and even fewer visitors?"
That would be a very fair question! But, as I mentioned, this is a personal project for fun, and I thought ghostHunter would be fun to play with. :)
Bottom line: using localStorage to cache the search indexes locally in your browser means that you can still enjoy pretty fast type-ahead searching, without needing to grab all the content for the site every time you want to search for something. I think it's a good compromise compared to sending your search queries to the server, like traditional server-side search requires.
If you're interested, read more about how client-side indexing and caching works in ghostHunter.
Image sources and optimisation
Most of the images on the site are served (securely) from my CDN subdomain - cdn.bytes.fyi. As well as photos that I've taken myself and images from elsewhere that I've uploaded to my server, there are some wonderful images on this site from Unsplash. Because Ghost features very slick integration with Unsplash - and because I'm lazy - some posts include images loaded directly from Unsplash.
I use the excellent ngx_pagespeed module to apply various performance tweaks to the blog, including automatically serving 'next generation' images in WebP format - but only to browsers that support the WebP format. Other browsers get optimised versions of the original jpegs, pngs or gifs, of course.
In order to optimise Unsplash images, they are fetched from Unsplash and the optimised versions are made available from this site's own CDN. The fetching and optimising process needs the page to be processed by ngx_pagespeed, so if you're lucky enough to be the first ever visitor to a new post (or new version of an existing page), then you will get the original version of the page, which may load images from Unsplash directly. After a few page views when the optimised version of the page and its resources are all built and cached, subsequent viewers should get optimised images - in the best format for the device/browser - delivered from cdn.bytes.fyi.
One day, I plan to write an article about the various performance tweaks that I've made to the blog.
YouTube videos
For any YouTube videos that I include in my posts, I have used the so-called 'Enhanced Privacy' version of YouTube's embeds. This essentially means that cookies are only set by YouTube when you click the play button - but not if you just visit the page without playing the video. It also means that if you do opt to watch the video, it won't affect your viewing history/targeting on YouTube:
Privacy Enhanced Mode allows you to embed YouTube videos without using cookies that track viewing behavior. This means viewing inbox isn’t collected to personalize the viewing experience. Instead, video recommendations are contextual and related to the currently played video. Videos playing in a Privacy Enhanced Mode embedded player won’t influence the viewer's browsing experience on YouTube.[1]
I think this is a reasonable compromise that allows a good user experience with videos viewable directly in the content, rather than removing the videos altogether and adding links to YouTube's site. After all, if you leave this site to view the video on YouTube's site, you'll get cookies from there anyway - and having the video preview frame within the blog content allows you to easily decide if you're interested in watching it or not, compared to a link to YouTube.
Third-party libraries and fonts
All of the javascript libraries and fonts that are used on this site (e.g. Prism for syntax highlighting within code blocks and the Source Sans Pro font) are served from this site's domain or its subdomains. This means that third-parties don't get referer headers from this site whenever you visit here.
Analytics
I use GoAccess to check how many (or rather how few) visitors are coming to my site. It works by analysing the web server access log, which records which pages were requested by which IP addresses and when. I don't need to involve Google to tell me that, so I don't use Google Analytics.
If you use a good ad-blocker - and you definitely should use a good ad-blocker - then it will automatically block Google Analytics anyway, so I'd be wasting the bandwidth of both of us by including it on this blog.
As an aside, if you're interested enough in privacy to read this far and you don't already use an ad-blocker, then I highly recommend checking out uBlock Origin. :)
What are those strange "beacon" calls for?
The site applies lazy-loading to 'below the fold' images - i.e. those images which aren't immediately visible without some scrolling. To find out which images are visible when (in order to choose which to load lazily), ngx_pagespeed will occasionally inject some javascript which 'pings' (via XHR) the server when each image is required. This is called page instrumentation, and the performance boost it gives through lazy loading of below-the-fold images - especially on slow/mobile connections - can be significant for pages with many images.
If you use uBlock Origin or similar, you may notice it intercepts these calls, because their URLs match the _beacon?
pattern that is sometimes used by tags or trackers. In this case, it's really just a false-positive, but it won't harm anything if some browsers block the calls, as long as ngx_pagespeed gets enough instrumention data from other browsers.
By automatically instrumenting pages occasionally in this way, ngx_pagespeed can update its list of which images are essential to render above-the-fold content.
You can see this in action if you refresh the page several times with Dev Tools open. Only some of the page loads will include the instrumentation javascript, so you don't get the XHR calls to ngx_pagespeed_beacon?
URLs on every single page load.