I Was Tired of Sending My Users' Data to Google — So I Built My Own Analytics

javascript dev.to

I'm a final year CS student. I build things in production.

Last year, I was working on [Ucoder](https://www.ucoder.in) — a full-stack platform I've been building since college. At some point I needed analytics. I wanted to know: are people actually using this? Which features are being used? Where are errors happening?

So I did what everyone does. I installed Google Analytics.

It worked. But something felt wrong.


The Problem

GA4 sends every user interaction to Google's servers. Every click, every session, every user's IP and device — all of it leaves your infrastructure and goes somewhere you don't control.

For a platform where I cared about user trust, that felt like a betrayal.

So I looked at alternatives:

  • Plausible — privacy-first, cookie-free, clean dashboard. But it only gives you pageviews, referrers, and bounce rate. No custom events, no error tracking, no real product analytics.
  • Mixpanel — powerful, but $28/month per 10K users. At scale, brutal. And the setup takes half a day just for event taxonomy.
  • Microsoft Clarity — session replays and heatmaps only. No event tracking.
  • Self-hosted Matomo — closer, but heavy to maintain and the UI feels dated.

None of them did what I actually needed:

Track real user behavior, capture errors, support custom events — without cookies, without sending data to a third party, and without a painful setup.

So I built it myself.


Introducing Ucoder Insights

Ucoder Insights is a privacy-first, cookie-free analytics platform with its own npm SDK.

It tracks:

  • 📄 Page views (SPA-aware, works with Next.js, React, Vue)
  • ⚡ Custom events
  • 🔴 JavaScript errors (with stack traces)
  • 📊 Core Web Vitals (LCP, FID, CLS)
  • 🌐 Referrers, UTM params, device/browser info

All without cookies. All processed on your own terms.


How It Works — Technical Overview

The SDK

npm install ucoder-insight
Enter fullscreen mode Exit fullscreen mode
import { initUcoderInsight } from 'ucoder-insight';

initUcoderInsight("projectid"{
  // Your optional settings here
});
Enter fullscreen mode Exit fullscreen mode

That's it. One function call. No configuration overhead.

The SDK is ~9.5KB gzipped. It uses a beacon API to send events so it never blocks the main thread. For SPAs, it listens to history.pushState and popstate to track client-side navigation automatically.

The Backend Architecture

The backend is built with Express 5 + TypeScript. When an event comes in:

  1. Request hits the Express API
  2. Passes through express-validator for input sanitisation
  3. Gets pushed into a BullMQ job queue backed by Redis
  4. A background worker processes the queue and writes to MongoDB

Why a queue? Because analytics should never slow down your app. If the ingestion endpoint is under load, events queue up and get processed asynchronously — your tracked application is never affected.

Client SDK
   │
   ▼
Express API  ──→  BullMQ Queue (Redis)
                       │
                       ▼
                  Worker Process
                       │
                       ▼
                   MongoDB
Enter fullscreen mode Exit fullscreen mode

Privacy by Design

  • No cookies — identification uses a daily-rotated hash of IP + User-Agent. No persistent tracking across days.
  • No PII storage — we never store IPs or personal data.
  • Your data stays yours — events go to your project only, not a shared Google/Meta data warehouse.

What This Solves That Others Don't

1. Error Tracking + Analytics in One Place

With GA4 or Plausible, you need a separate tool (Sentry, LogRocket) for error tracking. With Ucoder Insights, JavaScript errors are captured automatically — with the page URL, user agent, and stack trace — right alongside your pageview and event data.

No context switching between dashboards.

2. Real Custom Events, Simply

import { trackEvent } from 'ucoder-insight';

// Track anything
trackEvent('signup_completed', { plan: 'free', method: 'email' });
trackEvent('feature_used', { feature: 'export_csv' });
Enter fullscreen mode Exit fullscreen mode

Plausible's custom events require manual script tagging. Mixpanel requires you to plan an entire event taxonomy before you start. Here, you call one function.

3. SPA-First

Most analytics tools were built for traditional multi-page websites. Ucoder Insights was built with SPAs in mind from day one — it handles pushState navigation, React Router, Next.js App Router, and hash-based routing out of the box.


The Stack

Layer Technology
SDK TypeScript, Beacon API
Frontend Dashboard Next.js 16, React 19, Tailwind CSS 4
Backend Express 5, TypeScript, Socket.IO
Queue BullMQ + Redis (ioredis)
Database MongoDB (Mongoose 9)
Deployment Docker + PM2 on Linux VPS

Current Status

The platform is live at insights.ucoder.in and running in production on Ucoder.in.

The npm package ucoder-insight is public at v1.1.3.

I'm a solo developer and this is a real project — not a side project I'll abandon. I use it myself, which means I have a real incentive to keep it working and improving.


What's Coming Next

  • Alert system — get notified on Slack/email when error rate spikes or traffic drops
  • Server-side proxy — bypass ad-blockers without compromising privacy
  • Funnel analysis — visualise conversion paths across custom events
  • API access — pull your analytics data into your own dashboards

Try It

npm install ucoder-insight
Enter fullscreen mode Exit fullscreen mode

If you're building something and tired of sending your users' data to Google — give it a try. And if you have feedback, I genuinely want to hear it.


Built by Soumyadip Maity — Full Stack Developer, final year CS student, West Bengal, India.

Source: dev.to

arrow_back Back to Tutorials