Skip to content
Work

Analytics SaaS · Product engineering

Ad Analyst

Analytics for small agencies running Meta Ads: each client against its own targets, what changed and where spend is wasted, worked out by fixed rules rather than an AI model.

Stage
Built and pricedNot yet deployed; no billing or users
Analysis
10 rule-based detectorsEach finding shows its evidence and the rule that fired
Data
Next.js, Supabase PostgresRow-level security per workspace; Meta Ads CSV import
Validation
315 automated testsIncluding isolation tests on the real migrations
Ad Analyst Overview for the demo client Luxe Skin Co.: return on ad spend of 2.82x, up 17.7% on the previous 7 days but 0.68x short of the 3.50x target, with spend, revenue, purchases and cost per purchase, a daily chart against the previous period and target, and a 'Needs attention' status.
Overview for one client: return on ad spend against its 3.50x target, this week against last, and where spend is concentrated. Demo data.

01

The product

A small agency running paid social for several clients needs to know, before the reporting meeting, what changed, where performance is slipping, where money is being wasted and where there is room to scale. Ads Manager reports the numbers; it doesn’t say which of them matter for this client. Ad Analyst is meant to be a decision layer on top of Meta Ads rather than another reporting dashboard.

One workspace holds every client. Each client has its own currency, its own word for a conversion (purchases, leads or trials) and optional targets for cost per conversion and return on ad spend, and those targets frame every number in the product.

finding types, each a fixed rule
10
finding types, each a fixed rule
question types Ask Analyst can answer
16
question types Ask Analyst can answer
automated tests
315
automated tests
decisions logged, including rejected directions
60
decisions logged, including rejected directions
One plan, nothing gated
The Agency plan is £29 a month for up to ten clients, with the whole product included. Splitting the analysis across tiers would gate its core value, and inventing enterprise features would claim capabilities that don’t exist. Pricing is display-only: billing isn’t built.
Ad Analyst landing page: 'Know what changed before your client asks.', with Try the demo, above a product preview.Ad Analyst pricing: the Agency plan at £29 a month, or £290 a year, and Enterprise at custom pricing for more than ten client accounts.
The public site: the landing page and a single plan, for up to ten client accounts.

02

Findings from rules, not a model

Every finding compares the selected period with the one before it, on stored daily metrics only. The thresholds live in one object that both the detectors and the “Why this was flagged” sentences read, so the explanation can never drift from the rule. The copy is observational: tests fail if a finding claims a cause or offers to take an action.

For example, one demo campaign spent £638 in a week with no purchases, about 9% of the account’s spend. The client’s target is £28 per purchase, and spending at least twice that with nothing to show for it makes the zero-conversion rule fire at high priority: “£638 was spent with no purchases.” The demo data carries no flags; the rule finds it from the numbers.

Deterministic findings before any AI
Findings have to be reproducible, testable and defensible to a client. If a model is ever added, it explains facts the engine has already established; it doesn’t decide what is true.
Small numbers don’t raise alarms
A campaign is assessed only if it carries at least 5% of account spend. Cost and ROAS changes need five or more conversions in each period, and click-through rules need 1,000 impressions in each.
The client’s targets set the priority
The same cost spike is high priority for a client over target and only worth watching for one still within it, and a ‘winner’ is suppressed while its client is over target.
Store the raw numbers once, derive the rest
Only spend, revenue, conversions, impressions and clicks are stored, per ad per day. Every ratio and roll-up is computed when needed, because stored ratios drift and double count across campaigns and date ranges.
Campaigns ledger for Luxe Skin Co.: nine campaigns with spend, purchases, cost per purchase against the £28 target, ROAS and CTR, each compared with the previous seven days. The Overnight Repair Cream campaign shows £638 spent and no purchases.
Every campaign against the client’s £28 target. The Overnight Repair Cream row, £638 spent with no purchases, is the one Insights flags as wasted spend. Demo data.

03

Questions without an AI model

Ask Analyst takes a question in plain English, matches it to one of 16 question types, and answers on the server from the same facts as Insights, for the selected client and period only. It refuses forecasts, budget changes, other clients and dates outside the selection, and says what it can’t answer instead of guessing.

Answer the data, not the question’s assumption
Asked why cost per purchase rose, it answers that it fell 14.2%, and says the direction reflects the data even though the question assumed otherwise.
Ask Analyst answering 'Why did CPA rise this week?' with 'Account: cost per purchase fell 14.2%', the supporting figures, the related campaign finding and suggested follow-up questions. The input notes no external AI.
A question with a wrong premise, corrected from the data, with the evidence and the related finding underneath. Demo data.

04

Imports and tenant isolation

  • Agencies bring data in as ad-level daily CSV exports from Meta Ads Manager. Columns are recognised in any order, and the user is asked only what the file can’t answer, such as which column is the primary conversion.
  • The file is validated in the browser for feedback, then again on the server, which refuses mixed currencies, conflicting rows for the same ad and day, and files over fixed size limits.
  • The whole import is one database transaction: anything that fails rolls everything back. A re-import replaces only the days in the file, so importing the same file twice changes nothing.
  • Sign-in is passwordless, by emailed one-time link. Each person’s first sign-in creates their workspace.
Isolation lives in the database
Row-level security on every table makes cross-workspace reads and writes impossible even for a bug or a forged request. Application-level filtering fails open on the first missed condition, so the app never uses a privileged key.
Writes only through checked functions
A pre-deployment security review found that signed-in users could still write directly to their own workspace’s tables, past the app’s validation. Every direct write was revoked; data now changes only through database functions that check the caller and the input. Five database tests fail without that change.

05

Limits

  • Not launched: no deployment, billing or users yet. Agencies as the market is a hypothesis without customer evidence; small-business owners were the original alternative.
  • The isolation tests run the real migrations in an in-process Postgres, not against a live Supabase project.
  • The importer is built from documented Ads Manager column names and synthetic files; it hasn’t been tested on a real export.
  • Meta only, by CSV: there is no API connection or sync, and imported creatives have no artwork.
  • Creative fatigue is a proxy (click-through falling on steady spend and CPM), not a measured cause.
  • Ask Analyst understands a fixed set of question patterns; anything else gets “I can’t answer that reliably” rather than a guess.