← Back to projects

B2B SaaS · AI · Email Marketing

Anansii Campaign Manager
Because a spreadsheet shouldn't run your pipeline

Year 2026
Stack HTML · CSS · JavaScript · Claude API · Gmail MCP · Apollo.io
Client Anansii × UniPro Foodservice
Campaign 26 contacts · 3-touch email sequence · June 18 webinar

The Original Prompt

The exact words I gave Claude to kick this off.

Build an AI-powered prospecting agent to find CFO, VP of Sales, and Credit Manager contacts at wholesale food distributor companies — then use those contacts for a webinar email campaign. The webinar is "From Paper to Profit: Using AI to Approve New Accounts and Get Orders Moving Faster" on June 18, 3:00 PM ET. We have a UniPro member list of about 1,085 companies to search through.

Explain It Like I'm 5

How it works, why it was built this way, and the thinking behind each decision.

What it solves

Manually hunting for the right contacts at 1,000+ companies, writing personalised emails per persona, then tracking who's registered for the webinar — all of that was going to take weeks. This collapses it into a few focused sessions.

⚙️

What it does

Searches Apollo for CFOs, VPs of Sales, and Credit Managers across a deduped company list, then generates three persona-targeted HTML emails for a timed drip sequence. A 6-tab dashboard handles contact management, email previews, workflow tracking, Zoom registration reconciliation, and test sends — all in a single standalone file.

🧱

How it's built

A standalone HTML/CSS/JS dashboard with no backend or deployment step. It talks to Claude via sendPrompt() to route Apollo MCP searches and Gmail drafts through the chat session. The three emails are built as table-based HTML with all styles inlined on every element — the only format that survives Gmail's aggressive CSS stripping — verified with premailer to confirm zero CSS variables remain.

🤔

Why this approach

Browser-based artifacts can't call MCP servers directly — only Claude in the chat can. So the UI handles state and display while Claude handles the API calls. This keeps credentials server-side, makes sends reviewable before delivery, and means the whole tool works without spinning up a backend or writing a single line of infrastructure.

🚀

How sends are deployed

Send buttons in the dashboard trigger a sendPrompt() message to Claude, which calls the Gmail MCP to create a draft in your actual Gmail account. Drafts — not direct sends — so formatting can be inspected before hitting send. For standalone use outside Claude, a clipboard fallback shim copies the prompt so the user can paste it into chat manually. Zoom reconciliation works via CSV export from the Zoom dashboard, pasted into the tool's Zoom Sync tab to suppress already-registered contacts before each batch.

How It Was Built

Five steps from a raw member list to Gmail-ready emails.

1

Company deduplication

The UniPro member list had 1,085 rows — many were branches, divisions, and location variants of the same entity. A reconciliation pass reduced this to 415 unique companies, each mapped back to the original rows with a removal reason. Quality in means fewer wasted Apollo API calls.

1,085 rows → 415 unique companies
2

AI prospecting widget (Apollo MCP)

Built as an in-chat HTML widget using sendPrompt() to route Apollo searches through Claude. Target titles: CFO, Chief Financial Officer, VP of Sales, Vice President of Sales, Credit Manager. Batches of 20 companies per search. All 415 companies searched across 21 batches — hitting Apollo's 200-calls/hour free tier limit once during Batch 19, resuming after the rate limit reset.

26 contacts found across 14 companies · ~6.3% match rate
3

3-touch email campaign

Three persona-targeted emails for CFO, VP of Sales, and Credit Manager audiences — Email 1 (full invitation), Email 2 (urgency reminder, 5 days out), Email 3 (day-of last call). The first draft used CSS variables and <style> blocks, which looked perfect in browser preview but failed in Gmail. All three were rebuilt as table-based HTML with fully inlined styles.

Syne + Inter · navy #0A0E2E · cyan #00C8FF
4

Campaign manager dashboard

A 6-tab standalone HTML tool: Dashboard (live stats), Contacts (CSV-importable with per-contact status tracking), Email Preview (all 3 emails with send triggers), Workflow (eligibility-filtered 3-step timeline), Zoom Sync (paste registrant CSV to auto-suppress), and Test Mode (sends to test addresses only). No backend. No deployment. Runs as a file in-browser or inside Claude.

anansii_campaign_manager.html
5

Gmail MCP send flow

Send buttons route through sendPrompt() to Claude, which calls Gmail MCP to create drafts. Two bugs fixed: Cannot destructure 'pendingSendStep' as null (send/modal sequencing) and sendPrompt is not defined outside the Claude iframe (clipboard fallback shim added). Draft-first flow means formatting is always inspected before delivery.

Draft → inspect → send

Key Decisions

What worked, what didn't, and why each tradeoff was worth it.

Decision Why Outcome
Route sends through Claude chat, not artifact API calls Artifacts run in a sandboxed iframe and can't call MCP servers. Only the active Claude chat session can. ✓ Worked — clean separation of concerns; UI handles state, Claude handles sends.
↔ Tradeoff — user must trigger sends from chat, not purely from the dashboard.
Table-based HTML with fully inlined styles Gmail strips <style> blocks from <head> entirely. Only style="" attributes on individual elements survive. ✓ Worked — premailer confirmed 0 CSS variables, 0 style blocks in final output.
↔ Tradeoff — verbose and painful to edit by hand.
Gmail MCP creates drafts, not direct sends Allows formatting review before delivery. Safer for production sends to real contacts. ✓ Worked — user inspects the draft in Gmail, then sends.
↔ Tradeoff — extra manual step vs a direct send API.
Zoom reconciliation via manual CSV export Zoom has no public registrant lookup API without full OAuth setup. ✓ Worked — reconcile logic correctly filters registered contacts before each batch.
↔ Tradeoff — can't auto-check in real time.
Verified email filter on Apollo (no relaxing) Lower volume is acceptable; bounced emails damage sender reputation and waste sends. ✓ Worked — 26 high-quality contacts vs a larger, noisier list.
↔ Tradeoff — ~6.3% match rate across 415 companies is low coverage.

What's Next

Where this project could go with more time and feedback.

Near-term

Set up OAuth or use Claude in Browser with Zoom for live registration checks — no more manual CSV exports before each send. Pair with scheduled sends so Email 2 and Email 3 automatically skip registered contacts the moment they sign up, without any human in the loop

Medium-term

Package the prospecting tool as a React/Vite app with a Vercel serverless function proxying Apollo calls. Removes the API key from browser exposure and gives the team a shareable URL that runs without a Claude session open.

Ambitious

Expand into prospecting agent to identify new leads based on Ideal Customer Profile for future campaigns.

Share Your Thoughts

Feedback, ideas, and questions are welcome — I read everything.