Self-Hosting a Free Private Google Analytics Alternative

Umami Dashboard
Google, the company behind Google Analytics, is the largest ad-tech company in the world. They leave no stone unturned when it comes to data collection and tracking individuals across the internet.

Similar to Google Chrome, Google Analytics is yet another tool that Google uses to achieve this.

It’s tools like Google Analytics that have helped Google pioneer the business model of surveillance capitalism.

It doesn’t stop there. If you don’t care about data privacy, here are a few more reasons why you should consider moving away from Google Analytics:

    It’s bloated, affects your website’s speed

    It’s unnecessarily complex for the majority of cases

    You are giving away your site visitor’s data to Google

I can go on and on, but I will stop there.

In this blog post, I will go over a free and private alternative to Google Analytics called Umami. I will start with a brief overview of Umami, and then explain how I self-hosted an Umami instance to track my website (built with NextJS) stats.

Let’s get started.

Umami System Architecture

Umami — What is it?

Umami makes it easy to collect, analyze, and understand your web data — while maintaining visitor privacy and data ownership.

It’s open-source, does not use cookies, can be self-hosted, and gives you total control of your sites and visitors’ data.

You can measure several metrics using Umami. I will list out a just few highlights:

    Views, unique visitors, bounce rate, average visit time

    Supports custom time ranges to slice the data

    Views by referrers, browsers, OS, devices

    Views by countries, regions, cities, languages, etc

    Custom events to track button clicks, form submissions, etc

    Both real-time graphs and offline-generated reports

    Powerful filters allow you to do deep dives into your data

Umami Analytics 1

Umami Analytics 2

My personal use case of analyzing web traffic data of can be 100% satisfied with Umami. Since I realized that, I moved away from Google Analytics immediately.

Now, let me walk you through the steps I took to self-host an Umami instance and use it in my NextJS app.

How to Self-Host?


If you haven’t read my blog recently, you might be interested to learn about my journey towards self-hosting:

Keeping with the theme of “tech self-reliance”, I chose to self-host Umami in my cloud server.

The first step was to install Umami and run it locally inside a docker container. It took me 3 commands and 5 minutes to complete this step.

  git clone
  cd umami
  docker-compose up -d

A couple of highlights I want to call out about the docker container that will spin up:

    By default, it will run on port 3000 (configurable)

    Automatically spins up a Postgres instance with a dedicated volume

    Uses weak security — username and password — so you MUST change them ASAP

That said, once you complete this step, you have a locally running Umami instance on your server.

Where’s the Umami Script?

This is the part that took me some time to figure out. So buckle in (especially if you don’t have a ton of networking knowledge like me!).

Similar to Google Analytics, Umami has a script file that contains all the “analytics code”. This script file needs to be loaded into your website before data can start flowing in your dashboard.

So, 2 questions:

    Where is this script file located?

    How do I load the file into my website?

We will start with the first question.

If you have followed the steps above, you have a locally running Umami instance inside a docker container. By default, it’s running on your server’s port 3000. The script file lives inside this docker container.

Your website will somehow need access to this file from the public internet. Fascinating!

There are a few ways to achieve this. I will walk you through the way I did it using a Nginx reverse proxy.

Accessing Script.js from the public internet

Your website will be running on the visitor’s browser.

So, somehow network calls made by a stranger’s browser need to end up inside your docker container to retrieve the Umami script.

Here’s how I did it:

    My server’s root domain is

    I created a new subdomain

    Using Nginx Reverse Proxy, I forwarded incoming requests to to port 3000 (where my Umami instance is running).

server {
  listen 443 ssl;
  location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;
  ssl_certificate /etc/letsencrypt/live/;
  ssl_certificate_key /etc/letsencrypt/live/;
server {
  listen 80;

  # Redirect HTTP requests to HTTPS
  if ($scheme != "https") {
      return 301 https://$host$request_uri;

It only takes a few lines of Nginx configuration to achieve the above.

So now we have built a mechanism for your visitor’s browser to access the Script file. The next step is to make the network request from your website. Let’s do that.

NextJS + Umami

I built with NextJS.

Integrating Umami into the NextJS website was very straightforward. All I had to do was add an HTML script tag to my website’s header.

export default function MyApp({ Component, pageProps }) {
  return (
    <ChakraProvider theme={theme}>
        <title>Irtiza Hafiz</title>
        <link rel="icon" href="/irtiza-avatar-ayesha.png" />
      <Component {...pageProps} />;

Two key things to focus on:



You will see that the source of the script is my umami subdomain (as explained above) and the data-website-id is provided by the Umami instance once you add your website through Umami’s portal.

With that, we have a replacement for Google Analytics that’s self-hosted, private, and completely free.

Closing Thoughts

If you have made it this far, I hope you found this valuable.

Feel free to follow me on Medium, subscribe to my website, or follow me on YouTube.

Irtiza Hafiz