Jeremiah Kovacs, founder of Thank You Robot
Case Study · SaaS Backend & APIs Botify.
Multi-Tenant SaaS · Ad Analytics

Four ad platforms, one set of numbers a business can act on.

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.

Client
Thank You RobotJeremiah Kovacs, Founder
Industry
SaaS
Ad Analytics
Engagement
< 6 months
Backend build
Core Stack
n8n · Supabase
OAuth · Ads APIs

Three Platforms, Three Dashboards, No Answer

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."

— Jeremiah K., the original brief
Thank You Robot Case Study · BotifyPage 02

Four Steps Between an Ad Account and a KPI

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.

Diagram · the path from ad account to dashboard
🔗
Connect
Customer authorizes
📡
Collect
4 APIs, on a schedule
🔄
Normalize
One shared shape
📊
Serve
KPIs, per tenant
Illustrative diagram — the same four steps run for every customer on the platform.

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.

Thank You Robot Case Study · BotifyPage 03
1

Collecting from four APIs that agree on nothing

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.

Diagram · scheduled multi-platform sync
Schedule
Per tenant
📂
Load token
For this account
📡
Fan out
4 API branches
🔄
Normalize
One shared shape
📊
Upsert
Metrics table
📱
Meta Ads
Marketing API
Spend · ROAS
🔍
Google Ads
Ads API
Clicks · CPC
📦
Amazon Ads
Ads API
ACOS
🏪
Amazon SP-API
Commerce side
Orders
Illustrative diagram — one scheduled pipeline, four sources, a single normalized output.
Thank You Robot Case Study · BotifyPage 04
2

Making the numbers comparable

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.

tenants
idPK
nametext
created_attimestamp
ad_connections
idPK
tenant_idFK
platformenum
access_tokenencrypted
refresh_tokenencrypted
expires_attimestamp
statusenum
ad_metrics
idPK
tenant_idFK
platformenum
datedate
spendnumeric
impressionsbigint
conversionsbigint
Illustrative shape of the Supabase model — normalized metrics land in one table no matter which platform produced them, which is what makes cross-platform totals and blended ratios possible at all.
Thank You Robot Case Study · BotifyPage 05
3

The view the whole thing exists for

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.

Client dashboard
Ad Spend
Impressions
Conversions
Blended ROAS
Spend & performance over time — all platforms combined
Meta Ads
Google Ads
Amazon Ads
Amazon SP-API
Schematic of the end-user view — the metrics the dashboard surfaces once the pipeline has merged every connected platform. Layout only; no client figures are shown.
Thank You Robot Case Study · BotifyPage 06
4

Getting access — once per customer, not once per engineer

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.

Diagram · the connect flow, then the token lifecycle
👤
User connects
In the portal
🔒
Platform consent
Meta / Google / Amazon
🌐
Webhook
Catches redirect
🔑
Exchange
Code → tokens
💾
Store
Per user, per platform
Schedule
Before expiry
🔄
Refresh
Rolling renewal
On failure
Flag the connection
📝
Update
Status + expiry
Illustrative diagram — capture on the top row, keep-alive on the bottom.
Thank You Robot Case Study · BotifyPage 07

Amazon Doesn't Let You In Just Because You Have a Password

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:

HTTP Request → 401  EAUTH

"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.

Thank You Robot Case Study · BotifyPage 08

One Number a Business Can Argue With

4
Ad & Commerce APIs
1
Normalized Metrics Table
Multi
Tenant By Design
0
Founder Steps Per Signup
  • Meta, Google Ads, Amazon Ads and Amazon SP-API land in one normalized metrics table, so the dashboard reads a single shape and cross-platform totals and blended ratios are computable rather than reconciled by hand.
  • The spreadsheet reconciliation the product exists to replace is gone: the numbers are current, comparable, and attributable to a platform when someone asks which channel moved them.
  • Every row carries its tenant, so one pipeline serves every customer without any risk of one account seeing another's figures.
  • Connecting an ad account became something the customer does in a few clicks, which took the founder out of his own signup flow and let the product grow past his calendar.
  • Tokens refresh on schedule and failures surface as a flagged connection, instead of a dashboard quietly going stale.

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.

Thank You Robot Case Study · BotifyPage 09

Hired From a Shortlist of a Few

"

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.

— Jeremiah K., Thank You Robot

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 →
Thank You Robot Case Study · BotifyPage 10