A multi-tenant reporting platform for a marketing agency. It pulls every client's data in automatically each week, shows it on dashboards the agency configures per client, and surfaces insights from rules the agency writes itself.
Web apps, Data & reporting, Integrations, Automation
My Marketing Agency sells performance reporting as part of its service. Clients love seeing where their money goes. Producing it was the problem.
Every month the team pulled numbers out of Google Analytics, Shopify and ad platforms, pasted them into spreadsheets, rebuilt the charts, wrote recommendations by hand and emailed each client a PDF. About two and a half hours per client, every month. Reporting was the agency's selling point and its bottleneck: every new client added another day of spreadsheets.
The Data Lab turned that service into a product. Each client logs in to their own live dashboard. The data arrives by itself every week, and the insights are generated from the agency's own expertise, written down as rules.
Impact
To produce a client's report, down from about 2.5 hours
Minutes
Of agency time handed back a year
~750 hrs
Metrics a dashboard can be built from
128
Insights email to every client, sent automatically
Weekly
"Anthony has been an absolute legend in helping us build The Data Lab. We're genuinely excited about the clarity it gives our clients, but just as importantly, it's been a complete game-changer for our own team."
— Rosie Graystone, Creative Director, My Marketing Agency
How it grew
May 2025The first dashboard
Supabase auth, invite links and a client dashboard. Numbers were still entered by the agency, but clients could finally explore their own data.
June 2025Insights and admin tools
The first version of the rules engine, plus letting agency staff view the app exactly as any client sees it.
August 2025A dashboard per client
An ecommerce brand and a physio clinic care about different numbers. Layouts became configurable per client.
October 2025Automated data
Weekly Google Analytics sync, then Shopify, Casa subscriptions and LoyaltyLion in November. No more copying numbers.
2026A product the agency sells
Education mode, guided client onboarding, a Tuesday insights email and a public Shopify app so clients can connect their own store.
How it was built
The Data Lab is a Next.js app on Vercel with Supabase behind it. The interesting part happens before anyone opens a dashboard: a weekly pipeline that pulls every client's data, maps it onto a shared set of metrics and stores one clean row per client per week.
Data flows left to right. Every Monday, each client's sources are pulled, mapped and stored as one weekly row. Dashboards, insights and the Tuesday email all read from it.
Web app: Next.js and React on Vercel, with shadcn/ui, Tailwind and Recharts, and Zustand for dashboard state.
Data and auth: Supabase Postgres, with row-level security isolating every client's data.
Pipelines: Inngest runs the weekly syncs on New Zealand time, with retries, per-source error handling and a Slack summary after every run.
Integrations: the Google Analytics 4 Data API, Shopify's GraphQL API over OAuth, Casa subscriptions and LoyaltyLion. Credentials are encrypted at rest.
Email: Resend and React Email for invites and the weekly insights email, with delivery tracked back into the admin portal.
What I built
Data pipelines: a weekly sync that turns four different APIs and CSV uploads into one consistent set of metrics.
Integrations: a connect-and-map flow the agency uses to plug in a new client's sources in minutes.
Dashboards: metric cards, traffic, funnels and trends, with period comparisons and plain-English explanations.
Configurable layouts: each client's dashboard is assembled from 128 metrics and a set of charts, by drag and drop.
Multi-tenant access: invite links, one login across several businesses, and data isolated at the database.
A rules engine: insights written and maintained by the agency, with no code changes needed.
Pipelines that run themselves
Every source speaks a different language. Google Analytics reports sessions by source and medium. Shopify reports orders. LoyaltyLion reports members. The pipeline's job is to turn all of it into the same weekly row.
Every Monday, a background job pulls last week's data for each client and maps it onto metric keys. Paid social traffic from Facebook and Instagram becomes "paid social visitors", and a thank-you page becomes a completed booking. If something comes through that nobody has mapped yet, it isn't guessed at. The sync is marked for review and the agency sees exactly what's new.
The details matter. Automated values add to the week and manual corrections replace them, and every field remembers where its number came from. Google Analytics counts a user once per source, so a second de-duplicated query stops the totals being inflated. If one source fails, the others still land and the failure is reported.
Connecting a client's data
The agency adds a new client's sources from one screen. Each integration shows whether it's connected, when it last synced and how its data is mapped. The Google Analytics setup walks through mapping traffic sources, page paths and events, and it previews real data before anything is saved.
A client's data sources. Each one syncs weekly, shows its status and mappings, and can be re-run on demand.
Dashboards clients actually use
The dashboard answers the questions clients ask: is it working, where are people coming from, and where do they drop off. Every metric compares against the previous period, and a green or red badge shows whether the change is good. Cost going down is good, even though the arrow points down. Education mode flips each card to explain what the number means and how it's calculated, so clients learn to read their own data.
A client dashboard. Insights sit at the top, then headline metrics with period-on-period change, traffic by source and the conversion funnel.
A dashboard for every business
An online store cares about conversion rate and average order value. A physio clinic cares about bookings and cost per lead. So every layout is configurable per client. The agency picks a grid, then drags metrics and charts into place from a registry of 128 metrics, 32 of them calculated from the others. Metrics can be renamed per client, and there are sensible defaults for ecommerce and lead-generation businesses.
Building a client's dashboard. Sections, metrics and charts are dragged into place from the metric registry.
One login, many businesses
Clients join through an invite link that ties their account to their business. Someone who runs two businesses gets one login and a switcher. Data is isolated in the database itself: every table has row-level security, so a client can only ever read their own numbers, however the app is used.
The agency sees everything from the admin portal. Every client, their status, their invite link and the health of their data sources are in one table. Staff can view the app exactly as a client sees it, and a presentation mode hides the admin tools for client meetings.
The agency's client list. Invite links, data-source health and 'view as client' are one click away.
Insights the agency writes itself
The insights are the agency's expertise, not a black box. Instead of hard-coding advice, I built a rules engine the agency maintains itself. Each rule watches the data: a threshold, a trend over several weeks, a ratio between two metrics, or a mix of conditions. When a rule matches, it lands in one of three groups: needs attention, keep an eye on it, or double down. Each comes with the agency's own recommendation and a call to action.
The team writes and edits the rules in the admin portal without needing a developer. Rules are evaluated live on each dashboard and again for the Tuesday email, so a new rule reaches every client the same week.
An insight rule in the admin portal, and the insight it produces on a client's dashboard.
What I'd take from it
The Data Lab started as "make the reports faster" and became the agency's product. The biggest lesson was to put the agency's expertise into the system rather than into the code: the rules, the mappings and the layouts are all things they own and change themselves. That's what let it scale from a few clients to every client without me in the loop.