AI Systems · MarketingOps · Demo, public

Forward the report email to MarketingOps, and the master data updates itself

A marketing-ops reporting assistant: report emails get forwarded to one inbox, an AI pass extracts and cleans the numbers, a human approves them, and every figure lands in a version-controlled master dataset.

Demo · publicstatus
Human in loopextract → review → commit
The first morning of the month

The export that ate the first morning of every month

Every month a raw Excel export from HQ landed in my inbox: inconsistent column names, mixed formats, missing values, and enough PII that pasting it into any external tool was off the table. Cleaning it by hand took one to two hours at every monthly close, plus about fifteen minutes a day once the exports went daily.

The part that finally made me act was quieter than the lost hours. Several of us were each running a private version of the same cleanup, and nobody could say which cleaned copy was the latest without asking around. The obvious shortcuts were fenced off, because the file carried personal data that could not legally leave the building. Somewhere between the third rename of KYC Status and the second duplicate row, I stopped treating this as housekeeping and started treating it as a system I should build.

Before · the monthly close
Cleaning the HQ export, by hand1–2 h
Same cleanup, run privatelyseveral copies
PII blocks external toolshard wall
The starting state: a messy monthly export, hours of manual cleaning duplicated across the team, and a compliance wall around every off-the-shelf shortcut.
The research

BI connectors, Excel macros, a chatbot

Three routes, three wallswhy none of them shipped
BI connectors: the data has to leave, PII says no
Excel macros: break on every renamed column
Paste into a chatbot: no PII gate, no review trail

Connector suites solve the pulling problem well, and the scale of the problem is documented: Supermetrics' 2025 Marketing Data Report found marketers handling 230% more data than in 2020, while 56% say they don't have time to analyze it thoroughly.

But a connector needs the data to leave the building, and ours could not. Spreadsheet macros stayed inside the wall, so I tried those first; every column rename from HQ broke them, and whoever wrote the macro became its single point of failure. Pasting the raw file into a chatbot was ruled out for the same PII reason before accuracy even entered the conversation. What I actually needed was narrower than any tool on the list: strip the sensitive columns before any model sees a row, extract into a fixed schema, and keep a human between the model and the record.

What it refused to become

I wrote down what it would refuse to do first

The scope started as a list of things it would not do. It would not become a BI suite. No dashboard engine, no charting library.

Goals: the monthly close finishes in under five minutes; PII never reaches a model, stripped in the workflow layer before extraction; and corrections compound, so a mapping fixed once stays fixed in every later run. One inbox, one review gate, one versioned store, eight standing reports.

monthly close · end to end PII stops here corrections commit · the next run inherits every fix Report email forwarded in input Zapier clean PII gate clean Custom GPT extract pass extract Review Queue human approves gate Master Data versioned store 8 reports refreshed output
The path a report takes: reports forward to one inbox, a Zapier pass strips PII and normalizes fields before any model, a custom GPT proposes the extraction, a human approves it, and approved figures version into Master Data that feeds eight standing reports. Corrections committed at the gate flow back into the next run.
A weekend of pipeline

A weekend of pipeline, months of review queue

A Zapier flow watched the inbox, pulled the attachment into a protected Drive folder, dropped the sensitive columns, and renamed fields so kyc_status meant one thing. A custom GPT with a schema doc did the extraction. The pipeline took a weekend, most of it spent pair-writing the schema doc with the model instead of typing code. Deliberately boring, because I had zero engineering bandwidth and a compliance team with opinions.

The plumbing held. What broke was accuracy. Published benchmarks on field-level LLM extraction put the best configurations at 71–84% agreement with human coders, and my logs matched: about one field in five needed a person. Re-checking everything would have been the old job back with extra steps, so the redesign went into the review step instead. Confidence flags per field, diffs against last month, and arithmetic that never goes through the model. The web app below, built the same AI-paired way, wraps that queue in a clickable interface.

Shipped on
Next.js Gemini Vercel Zapier Custom GPT
The loop, on screen

Nothing commits to master data until a person clears the exceptions

marketing-report-web.vercel.app
Marketing Ops Assistant landing page stating the manual-reporting problem
Marketing Ops review queue with source-badged reports awaiting human approval
Marketing Ops Master Data view with versioned, snapshot-dated reports
Marketing Ops report copilot answering questions from the approved data store

The published version of this one is deliberately framed as a demonstration rather than a product, and the landing page says so: I built it because I hate manual data entry, and complaining about a five-hour weekly tax is less useful than removing it. Three claims sit behind the four screens.

01 Collection stops being manual

Reports arrive by forwarding an email to an inbox. Nobody opens a CSV, renames a column, or pastes a range into the wrong tab at the end of a long day.

02 Dirty data stops breaking attribution

Inconsistent column names and duplicate rows are normalised on arrival, which is the quiet failure that makes a model wrong without making it look wrong.

03 There is one current version

Master Data holds the approved snapshot under version control, so the question of which spreadsheet is the latest one has a single answer.

The close, after

The close shrank, and every correction stuck

The monthly close that took one to two hours of hand-cleaning now finishes in under five minutes, and daily snapshots, which we never had time to produce at all, became routine.

The quieter change is the one I value more. A correction made in the review queue lands as a versioned commit, so the same fix never has to be made twice, and any month's numbers can be rebuilt from the record instead of from somebody's memory.

Monthly close
<5 min was 1–2 hours
Corrections compound
Fix a mapping once
Every next run inherits it
Any month reproducible
Before and after: the close drops from one to two hours to under five minutes, and because every correction versions into the master dataset, the review work compounds instead of evaporating.
Keep reading
What it runs on

The least interesting stack here, which was the point

Application

Next.js logoNext.jsThe review queue, master data view and report copilot. React logoReactThe UI layer. TypeScript logoTypeScriptIncluding the extraction schema.

Automation

Zapier logoZapierWatches the forwarding inbox and moves the attachment into the protected folder.

Models

Gemini 1.5 logoGemini 1.5Field-level extraction into a fixed schema, and the plain-language questions over approved snapshots.

Delivery

Vercel logoVercelHosting and the extraction endpoint.

Nothing here is novel and nothing here needed to be. I had zero engineering bandwidth and a compliance team with opinions, so every component is one somebody else could take over.

Want this kind of tooling on your team?

Nine systems shipped, compliance, reporting, intelligence, content.