V·NESTERENKO
← All work
Solo · 2026 · 3 months

Business-Metrics Data Dashboard

Client confidential – details anonymized.

A multi-brand e-commerce operator was running their week off four systems that had no knowledge of each other. Sales sat in Shopify, the books in QuickBooks Online, ad spend split across Meta and Google. Somebody assembled a picture by hand every week, and by the time it existed it described a week that had already happened.

I built the thing that assembles it automatically.

Connecting four providers

Each integration is its own small problem. OAuth is the easy half; the hard half is what happens afterwards – storing refresh tokens so a connection survives without anyone noticing it lapsed, signing requests correctly, and handling the case where an account is disconnected but its historical data should stay.

Google Ads was the fiddliest, partly because it can return several customer accounts and asking a non-technical user to choose one is a bad first experience. If there is only one, it selects itself.

The data lands in Neon Postgres as dated snapshots rather than being fetched on demand. Dashboards that query four external APIs on page load are slow and break whenever a provider does. Snapshots make the dashboard fast and keep working when Meta has a bad morning.

The client was Canadian and the money was not

Revenue arrived in both CAD and USD. I added a live FX rate with a daily cache and explicit conversion indicators, because a total with silently mixed currencies is worse than no total.

Then I took most of it out

The first version showed everything I had: month-over-month deltas, thirty-day trends, numeric sublabels under every figure. It was thorough and nobody could read it.

Several passes went into removing things. Sublabels went. The 30-day series went. The dashboard UI around sign-in went. Drill-down pages were rebuilt around one number at the top and collapsible detail underneath, so the answer arrives before the evidence does. The version that shipped shows considerably less than the version I first built, and it is better.

I found a bug in that process worth mentioning: channel percentages were multiplied by 100 twice, so a channel at 34% of sales displayed as 3,400%. It was obvious once visible – which is an argument for showing fewer numbers more clearly.

Shape of the work

32 API routes, 17 pages, four provider integrations, four database migrations, built solo over three months across 28 working days. The estimate and phase breakdown were written up front from a recorded client call, which is also how the scope stayed where it started.

Next project →