
The data layer behind an ad-reporting SaaS — collecting spend and performance from Meta, Google Ads, Amazon Ads and Amazon SP-API, normalizing it into comparable KPIs, and serving it per customer from one multi-tenant backend.
A business advertising on Meta, Google and Amazon is looking at three separate dashboards that do not agree with each other. Each one names its metrics differently, closes its reporting day at a different hour, and attributes a conversion on its own terms.
So the question every operator actually needs answered — where is the money working, and where is it being wasted? — has no single place to ask it. In practice it gets answered by exporting CSVs and reconciling them by hand in a spreadsheet: a job that has to be redone from scratch every time, and that is out of date the moment it is finished.
Jeremiah Kovacs was building the product that removes that work: an accounting-grade dashboard that pulls every platform's spend and performance into one place, makes the numbers comparable, and puts the KPIs a business decides on in front of it.
That product lives or dies on the layer underneath it — the part that gets the data in, makes it agree, keeps it current, and does all of that separately for every customer. That layer is what this engagement built.
"The project involves a custom, multi-tenant portal for an ecommerce company (pulling data from Amazon, Shopify, etc.; managing orders, inventory, ads, etc.). We'll be sprinkling in AI tooling to standard ETL processes."
Everything the backend does reduces to one job: take numbers that were produced by different companies, under different rules, and make them safe to put side by side.
The order matters. Normalizing at ingest rather than at read time is what keeps the dashboard simple: by the time the front end asks a question, spend is spend and a conversion is a conversion, whichever platform produced the row. Every inconsistency left in the data would otherwise become a special case in the interface — and Jeremiah was building that interface in Retool while this ran underneath it.
Meta, Google Ads and Amazon Ads each have their own authentication model, their own request shape, their own pagination, and their own opinion about what a reporting day is. Amazon's SP-API adds a different flavour again on the commerce side, where the orders and revenue live.
A scheduled pipeline runs per tenant: it loads that customer's credentials, fans out across all four sources in parallel, and pulls the window of data that has changed.
This is the part that makes the product an accounting tool rather than four dashboards in a trenchcoat. Each platform's response is mapped onto one shared row: a tenant, a platform, a date, and the same measures every time — spend, impressions, conversions.
Every row also carries the tenant it belongs to, so a query can never quietly return one customer's numbers to another. Connections are keyed per user and per platform, which is what lets a single pipeline iterate accounts instead of being duplicated per customer.
Once every platform's data shares one shape, the numbers a business actually runs on become simple to compute rather than a reconciliation exercise: total spend across all channels, impressions and conversions in the same units, and blended ratios that only mean anything when the underlying rows agree.
That is the difference the product sells. Not "here is your Meta data and also your Google data", but a single figure a finance conversation can start from, with the platform breakdown underneath it when someone wants to know which channel moved it.
None of the above runs without permission to read each customer's ad accounts, and that was the step standing between the product and its own growth. Every signup meant the founder connecting each platform by hand, walking an authorization flow, capturing the tokens, then cloning and rewiring workflows for that one account.
So the customer does it instead. A registered application on each platform lets a user approve access themselves; a webhook catches the redirect, exchanges the code for tokens, resolves which tenant it belongs to, and stores them. A scheduled job refreshes them ahead of expiry and flags a connection when a refresh fails, rather than letting a sync stop silently.
Meta and Google are well-worn paths. Amazon's Selling Partner API is a different proposition: it sits behind a developer registration, its own Login-with-Amazon credential set, and a signing process that has to be exactly right before it will return a single row — and it is the source for the commerce side of the numbers, so the dashboard is incomplete without it.
The credentials looked present in n8n, so the first requests should have worked. They didn't:
"I saw the Amazon SP API in credential on n8n, so I thought it's added, but it gives an EAUTH error upon request from the HTTP node."— Waqass, diagnosing the blocker
Rather than assume the integration was broken, the question went the other way — to what was actually behind the credential:
"Have you tested the Amazon SP API on n8n to retrieve any data related to orders?"— Waqass
"No, I still need to acquire developer credentials, but I was planning to use an HTTP node."— Jeremiah K.
That answer closed the case in one message. The failure wasn't a bug to debug for days — the developer registration didn't exist yet. The right move was to name the real blocker, hand it back as the client's action, and build every other branch of the pipeline in the meantime so nothing waited on Amazon's approval queue.
It is an unglamorous kind of value: knowing when an error means write more code and when it means this is a paperwork problem, and the code is fine.
The measure of a reporting product is whether someone trusts the number enough to spend against it. That trust is built entirely below the interface — in whether the data arrived, whether it agreed, and whether it is current.
Your profile caught my eye. I wanted to invite you to a job I just posted. It's private, and I'm only inviting a handful of candidates.
An analytics product is a promise that its numbers are right. Most of the work of keeping that promise is invisible from the front end: getting access to four different platforms, mapping four different vocabularies onto one, keeping credentials alive, and doing all of it separately for every customer without the founder in the middle.
Get that layer right and the dashboard is simple to build. Get it wrong and no amount of interface design saves it.
Do your numbers live in four dashboards that don’t agree? That is a data-layer problem, not a reporting one.
Book a call with Botify →