A private analytics dashboard built to connect traffic with the changes I make to a product.

Visit project

shipwake.dev  ·  Analytics

Shipwake analytics dashboard showing traffic over time and key metrics.

I was paying for analytics tools for my own projects.

At some point I realised I could probably build the small version I actually needed. So I started. 100+ commits and two months later, I had something I was proud enough to share.

The first thing I tracked was a page visit. Nothing fancy. I wanted to send an event from a browser, receive it, and see it again in my own dashboard.

Then the questions got more interesting. I wanted to see AI crawler activity too. Then I connected GitHub, so the changes I was making were closer to the numbers. After that, I started marking changes in the timeline and looking at what happened around them.

This is Shipwake. A private analytics dashboard for my own stuff.

You can visit Shipwake or open the read-only timeline demo.

The first version

I started with a lightweight first-party tracker. It sends browser events to my own VPS, which was enough to replace the basic analytics tools I was paying for.

I did not start with a huge dashboard plan. I just wanted the smallest useful thing to work first.

Raw events are processed in the background and turned into time and dimension rollups. A small real-time window keeps the current numbers useful too.

Then I kept adding context

Pageviews are useful, but they do not tell me what I changed.

So I added conversion goals and a way to mark product changes. The idea is simple: record a change, look at the window around it, and see what happened.

AI crawler tracking came next. Some requests do not look like human visits, and I wanted to keep answer visits, indexing, and training activity separate from the rest of the traffic.

GitHub was next. Recording every change manually is fine until I forget to do it. Connecting the repository lets Shipwake show relevant commits beside the analytics.

That is basically how the project has grown. I start with one small signal, then add the thing I need when the first version leaves a question unanswered.

What Shipwake has so far:

  • Cookie-free, first-party analytics for pageviews and events.
  • Live and historical traffic with time and dimension rollups.
  • Conversion goals, engagement, referrers, pages, devices, browsers, and countries.
  • AI crawler tracking, kept separate from regular visits.
  • GitHub context and a timeline for seeing changes beside the numbers.

The bit I care about

Most analytics tools answer a question like how many visits did this page get?

I keep wanting to ask what did I change, and what happened after that?

That is why the timeline matters. Conversions, referrers, engagement, AI traffic, and changes have to sit close enough together that I do not need to reconstruct the story in three different tools.

How it evolved

I did not build this from a giant dashboard specification. It grew in layers:

  1. Track a visit. A lightweight browser tracker sends first-party events for a site.
  2. Make the read path useful. Raw events are processed in the background and aggregated into time and dimension rollups.
  3. Add the missing context. Conversion goals, product changes, AI crawler classification, GitHub context, and engagement views answer the questions that came next.

I also care about the difference between live and historical data. “Right now” does not need the same data path as a thirty-day trend.

How it is put together

  • Browser tracker. A first-party event leaves the page.
  • Analytics endpoint. A lightweight 202 response keeps it moving.
  • Queue + rollups. Raw events become useful time windows.
  • Laravel + Inertia. The dashboard puts the story back together.

Live counts stay separate from historical rollups, so the dashboard can answer “right now” without rebuilding the whole timeline.

The ingestion path is short. Processing happens on a dedicated analytics queue. Longer windows use pre-aggregated data, while the live count is refreshed separately.

That split keeps the dashboard quick enough without pretending every question needs real-time computation.

What I still want to prove

Collecting more numbers is easy. Finding one view that changes what I do next is harder.

I still want to see a recorded change lead to a concrete follow-up, not just a nicer report.

More projects