DataLook — Success-Event Analytics for SaaS Founders
Your analytics counts visits. DataLook counts customers — a privacy-first analytics product built around the success event a founder actually cares about.
DataLook is a privacy-respecting analytics product for small SaaS teams, built around one idea: the unit of value is the success event the customer defines — a signup, a purchase, a booking, an activation — not a pageview.
Plausible and Fathom count visits well but treat every visit as roughly equal. Mixpanel and Amplitude can model success properly but are priced and shaped for product teams with an analyst on staff. DataLook aims at the gap: four flat tiers from $5 to $99 a month, an install that takes under ten minutes, and a first question that is not "which metrics do you want?" but "what does success look like for your product?"
It is live in production at datalook.app — a Next.js 16 app with a ClickHouse event pipeline, a tracking SDK under a hard 3.5 KiB budget, a full RBAC admin portal, self-serve billing, and an interface in English, Arabic and French.
Key features
Success events as the unit of value — define what a conversion means by URL pattern, button click or a single `analytics.success()` call, with no code required for the first two
One-line script install with auto-tracking for pageviews, sessions, referrers, device, country and UTM
A tracking SDK held under a hard 3.5 KiB gzip budget, enforced by a CI check that fails the build
First-party proxy so the script survives ad-blockers — via DNS CNAME or framework rewrites, documented for 25 stacks
Funnels, retention cohorts and reusable saved segments
Live view with a 3D visitor globe
AI assistant powered by Gemini that answers plain-language questions about your data, with PII sanitised before the prompt leaves the server
Gamified onboarding — a non-linear quest log that gets a founder to first insight in under ten minutes
Admin portal with multi-role RBAC across users, roles, subscriptions, finance, customers, auditing, system health and notifications
Self-serve billing on Lemon Squeezy — checkout, webhooks, invoices and plan changes across four tiers
Privacy by default: cookieless, anonymised IPs, no fingerprinting, plus GDPR export and delete
Trilingual interface — English, Arabic (RTL) and French
The premise
Most analytics tools answer "how many people came?" The question a founder actually has is "did anything good happen, and what caused it?" Those are different products. DataLook makes the customer name their success event during onboarding and then reports against that definition, so the dashboard opens on the number the founder cares about instead of a table of pageviews they have to interpret.
A success event can be defined three ways, and two of them need no code at all: by URL pattern (a visit to `/welcome` counts as a signup), by button click (tag an element with `data-track` and map it in the dashboard), or by an explicit `analytics.success()` call for server-side flows.
The ingest pipeline
The path an event takes is deliberately short and decoupled at exactly one point:
The SDK batches and sends via `navigator.sendBeacon`, falling back to `fetch({keepalive:true})`
`/collect` validates and writes to a Redis Stream — the endpoint never waits on an analytics database
A consumer running under pm2 drains the stream and batch-inserts into ClickHouse
Materialized views and hot/cold tiering keep dashboard queries fast as the table grows
`/api/stats` reads aggregates; the dashboard renders them on hand-built visx charts
Redis Streams is the load-bearing choice there. Without it, a ClickHouse hiccup becomes a dropped beacon on someone else’s website, and the customer never knows they lost data — the failure is silent by nature, which is exactly the kind of failure worth designing out.
The landing page leads with the product’s whole argument: your analytics counts visits, DataLook counts customers.Four flat tiers from $5 to $99 a month — priced so a solo founder lands at the bottom of the range, not the top.Product docs built on fumadocs from MDX, including the first-party proxy install path for 25 frameworks.A public status page backed by the same health endpoints the admin portal reads.The same landing in Arabic. Direction is set per locale on the html element and layouts mirror through logical properties.Pricing in Arabic — all three dictionaries carry the same 1,133 keys.Sign-in on Better-Auth, offering both magic link and email + password.The landing on mobile — the “did it work?” glance is a first-class use case.Arabic on mobile, with full RTL.
Postgres 18 holds users, sites, roles, subscriptions and success rules — relational data that wants transactions and foreign keys. ClickHouse 24.10 holds the events, which are append-only, multi-tenant and queried as time series across cohorts. Postgres alone would have handled V1 volumes comfortably, so this is a bet rather than a necessity: the planned differentiator is a cohort comparison — what did converters do differently? — and that is a query shape ClickHouse is built for. Capturing events there from day one turns a future migration under production load into a feature branch.
Shipping on one box
Production is a single EC2 instance behind Cloudflare. nginx terminates TLS; Next.js and the ingest consumer run under pm2; Postgres, Redis and ClickHouse sit alongside them. Nothing is containerised in production — Docker Compose exists only for local development. A deploy is one command on the box: pull, install, migrate Postgres, migrate ClickHouse, build, reload.
For two part-time builders taking a product to a small hand-picked beta, running four managed services would have meant four dashboards, four bills and four failure modes before the first customer was served. The trade is explicit and documented: velocity now, a known multi-region problem later.
Design as positioning
Every competitor in this category looks the same — teal and indigo on blue-grey chrome. DataLook leaves that band deliberately: a warm cream canvas, a deep honey-gold as the only signal colour, cobalt held back as a cool counterweight inside charts. Tokens are specified in OKLCH with measured contrast ratios recorded against each one, so warmth never costs legibility, and the charts are hand-built on visx precisely so they inherit the palette instead of fighting a library’s defaults.
The same restraint governs the gamification. Onboarding is a non-linear quest log with completion confetti, because getting to first insight deserves to feel like a win — but that mechanic stops at the onboarding boundary and never leaks into the daily surfaces.
Where it stands
DataLook is live in production with the full pipeline wired end to end, self-serve billing on Lemon Squeezy, a Gemini-powered assistant that sanitises PII before any prompt leaves the server, and an RBAC admin portal covering users, roles, subscriptions, finance, customers, audit and system health. Roughly 110,000 lines of TypeScript across 1,357 files, 39 screens, 63 API handlers and 229 components — with the explicit non-goals (no session replay, no heatmaps, no A/B testing) treated as part of the product rather than a gap in it.
Challenges & solutions
Challenge
An analytics script is a tax every visitor to a customer’s site pays. Ship a heavy one and you have made your customer’s product slower in exchange for telling them how slow it is — which is the fastest way for a founder to rip your tag out.
Solution
The SDK is written in TypeScript and bundled by esbuild into a single IIFE with a hard 3.5 KiB gzip ceiling, asserted by a check that runs before every push and fails the build if it is exceeded. Transport uses `navigator.sendBeacon` with a `fetch({keepalive:true})` fallback, so events survive the page unloading without blocking navigation. The budget is a build-time constraint rather than a good intention, which is the only way a size limit survives a year of feature work.
Challenge
Ad-blockers and privacy extensions block analytics scripts by domain. For a product whose entire value is counting conversions accurately, silently losing a third of the data is worse than losing all of it — you cannot tell that it happened.
Solution
DataLook serves through a first-party proxy: the script and its collection endpoint are reachable on the customer’s own domain, either by a DNS CNAME or by a rewrite in their framework config. I wrote and tested that install path for 25 different stacks so the setup is a copy-paste rather than a support ticket, and Cloudflare caches the SDK at the edge so the extra hop costs nothing.
Challenge
Event ingest and application reads have opposite shapes. Success events are high-volume, append-only, multi-tenant and queried as time series across cohorts; users, sites, roles and subscriptions are low-volume relational data that needs transactions and foreign keys. One database serving both does one of them badly.
Solution
I split them: Postgres 18 holds application data, ClickHouse 24.10 holds events with hot/cold tiering and materialized views, and Redis Streams sits between the collector and the consumer so a slow write never drops a beacon or backs pressure up into the HTTP endpoint. Postgres would have coped at V1 volumes, but the planned wedge feature — comparing what converters did differently — is a cohort query ClickHouse is built for, and capturing events there from day one avoids a migration under load later.
Challenge
The obvious architecture for this product is four managed cloud services. For two part-time builders chasing a beta with a handful of hand-picked users, that is four dashboards, four bills and four failure modes before a single customer is served.
Solution
Everything runs on one EC2 box: Next.js and the ingest consumer under pm2, nginx terminating TLS from Cloudflare, and Postgres, Redis and ClickHouse alongside them. Nothing is containerised in production — Docker Compose is strictly a dev convenience. Deploys are one command that pulls, migrates both databases, builds and reloads. It is a deliberate trade of future scaling work for present velocity, and it is written down as a known v2 problem rather than pretended away.
Challenge
Three locales — English, Arabic and French — where Arabic needs right-to-left layout and a different script. Loading Arabic webfonts for every visitor would penalise the majority of pages that never render a single Arabic glyph.
Solution
All three dictionaries carry the same 1,133 keys, with unfilled keys falling back to English at render time rather than showing a raw key. Direction is set on the `html` element per locale, and layouts mirror through logical Tailwind properties with chevrons flipped by an `rtl:` variant. Noto Sans Arabic is chained behind Geist with a `unicode-range` descriptor, so the Arabic face is only fetched by pages that actually contain Arabic characters.
Challenge
Analytics dashboards look the same: teal and indigo on blue-grey chrome. Looking like every competitor is a positioning problem, not just an aesthetic one — the product’s whole argument is that it measures something different from the tools it sits beside.
Solution
The identity moved out of that colour band entirely, onto a warm cream canvas with a deep honey-gold as the single signal hue and cobalt kept only as a cool counterweight in charts. Every token is specified in OKLCH with its measured contrast ratio recorded next to it, so the warmth never costs legibility. Charts are hand-built on visx rather than a charting library’s defaults, which is what lets them inherit the brand palette instead of fighting it.
Takeaways
DataLook is the project where I learned that the hardest engineering decisions on a small product are subtractive. Choosing ClickHouse alongside Postgres, holding the SDK under a build-enforced size ceiling, and writing down that session replay and heatmaps will never ship — each of those closed a door on purpose, and each one made the remaining product sharper.
The single-server architecture is the clearest example. It is not the architecture I would choose at scale, and I did not pretend otherwise: it is documented as a deliberate trade with a named expiry condition. Being explicit about what a decision costs, and when it will need revisiting, turned out to be more valuable than getting it theoretically right on day one.