Umami Cloud is a simple, fast, privacy-focused alternative to Google Analytics. It provides a clean dashboard with all the essentials: total views, unique visitors, live user count, and more.

I use Umami Cloud for my personal websites because it’s open-source and incredibly easy to integrate with Hugo - I just added 1 line of code to my website’s configuration file.

customHeadHTML = '''
    <script defer src="https://cloud.umami.is/script.js" data-website-id="f7c4c668-8892-4890-8b5a-980f942439bc"></script>
  '''

Why I Built an API Wrapper

While developing a custom homepage for my homelab using Homepage, I wanted to view the stats for my website in the last 24 hours.

The problem? The Umami Cloud API expects you to define a time range using two parameters: startAt and endAt — both as UTC timestamps in milliseconds. So, if you want to display “Last 24 hours” or “Last 7 days”, you have to calculate those timestamps yourself every time.

To make this easier, I built a simple ASP.NET Core API wrapper that accepts user-friendly labels like 24hours, 7days, 30days, and automatically converts them into the required timestamps.

Example Usage

How It Works

Running Locally

To run the API locally for testing, use the following command:

dotnet run --launch-profile https

Then you can get stats for the last 7 days for a website:

GET /api/{websiteId}/stats?range=7days
Headers:
  x-umami-api-key: <your-api-key>

Example output:

{
  "startAt": 1749279600000,
  "endAt": 1749884399999,
  "apiStats": {
    "pageViews": {
      "value": 16,
      "prev": 24,
      "diff": "-33%",
      "valueWithDiff": "16(-33%)"
    },
    "visitors": {
      "value": 11,
      "prev": 23,
      "diff": "-52%",
      "valueWithDiff": "11(-52%)"
    },
    "visits": {
      "value": 14,
      "prev": 24,
      "diff": "-41%",
      "valueWithDiff": "14(-41%)"
    },
    "bounces": {
      "value": 12,
      "prev": 24,
      "diff": "-50%",
      "valueWithDiff": "12(-50%)"
    },
    "totalTime": {
      "value": 62,
      "prev": 0,
      "diff": "0%",
      "valueWithDiff": "62(0%)"
    }
  }
}

Running in Docker

You can run this API using Docker Compose. Here is an example docker-compose.yml:

services:
  umami-cloud-api-wrapper:
    container_name: umami-cloud-api-wrapper
    image: ghcr.io/briancollet/umami-cloud-api-wrapper:1.0.0
    environment:
      - ASPNETCORE_HTTP_PORTS=7887
    ports:
      - 7887:7887
    restart: unless-stopped

Check It Out on GitHub