Case Study 07 · Marketing Operations

Lead Allocation Engine

One dashboard-controlled Cloudflare Worker that replaced a fleet of roughly forty near-identical automation flows, one per lead campaign, each carrying its own hardcoded caller list, rotation counter, and Discord notification map that had to be edited by hand every time something changed.

Industry

EdTech / Marketing Operations

Build and Deploy Time

Designed, built, and deployed in one working session

Platform Cost

$0 (Cloudflare free tier)

Stack

Cloudflare Worker + D1 · Apps Script · Airtable · Mailchimp · Discord

~40 Fragile flows collapsed into one worker
1 Toggle to add or pause a closer, everywhere
<1 min To onboard a new lead campaign
$0 Monthly platform cost

A fleet of near-identical flows, all edited by hand.

Every Facebook lead form fed its own tab in a central spreadsheet, and every tab had its own dedicated automation flow: a trigger, phone and grade formatting, a caller-rotation step, record creation across two CRM bases, a repeat-signup check, a mailing list sync, and a Discord notification. Multiplied across campaigns, general trial classes, subject-specific classes, writing programs, book promotions, this became a fleet of roughly forty tabs that all had to be maintained one at a time.

The list of closers who receive leads was hardcoded inside every flow in three separate places: a rotation array, and a closer-to-Discord-ID lookup map duplicated across two independent notification branches. Adding a closer, removing one, or pausing someone for a week meant repeating the same three edits across every rotating flow. If one Discord map was missed while the rotation array was updated, a lead would be assigned to the new person and recorded in the database with nobody pinged to call it, a failure invisible until someone noticed silence.

"Basically what I want is: if it's already assigned to me or my colleague, keep it that way and don't reassign it to someone new." The closer, on the call that shaped the fix

Before

  • Caller list hardcoded in three places across every one of ~40 flows
  • Rotation counters tracked independently per flow, drifting apart
  • Repeat signups rotated to a new closer, duplicating outreach
  • Existing WhatsApp leads re-rolled to a stranger by a new ad click
  • Contact matching by phone only, creating duplicate family records
  • Meta form re-versioning silently broke triggers, leads vanished
  • No shared log, failures were invisible until someone noticed silence
  • API credentials embedded in plain text inside every flow definition

After

  • One closer registry, adding or pausing someone is a single toggle
  • One shared rotation counter, fair allocation across the whole business
  • Keep-owner rule: an active closer's contact never gets re-rolled
  • Existing relationships preserved automatically across lead types
  • Contact matched by email OR phone, one-row-per-family rule holds
  • Longest-prefix source matching absorbs form re-versioning automatically
  • Every lead logged: ok, paused, error, or unconfigured, nothing vanishes
  • Credentials moved into the platform's encrypted secret store

One pipeline, per lead, every time.

A single Apps Script watches the entire spreadsheet across all tabs and posts new rows to the worker's ingest endpoint. From there, one pipeline runs the same six steps for every lead, regardless of which campaign it came from.

01

Detect

02

Normalise

03

Match

04

Decide Owner

05

Sync Systems

06

Notify

One worker. Every hardcoded value turned into data.

The entire fleet of flows collapsed into a single Cloudflare Worker governed by one self-serve dashboard, with every previously-hardcoded value turned into editable configuration stored in a database. One Apps Script watches all tabs, with a five-minute timed sweep as a safety net. New tabs need zero setup.

01

Source resolution by longest-prefix match

The worker resolves an incoming tab to a configured source. Matching is exact first, then longest-prefix, so a source saved under a form's base name automatically catches every future Meta re-version suffix without any change. Unknown tabs surface in the dashboard as unconfigured. Paused sources log their arrivals without processing them, so nothing is invisible.

02

Header-name field extraction, not column letters

Fields are read by header name rather than column position, so a form with an extra question no longer shifts every downstream mapping. Phone numbers are normalised to local format, year levels to a standard form, before anything else touches the record.

03

Email-or-phone contact matching

The family is looked up in the contact master by email OR phone, with tolerant last-digits matching. A parent enquiring with a new phone number but the same email is still found, protecting the one-row-per-family rule that phone-only matching had been quietly violating.

04

Caller decided once, fanned out everywhere

The caller is decided a single time, then written to every destination: the campaign's intake table, the central all-leads table, the CRM, and the Discord mention all carry the same name by construction. The class of bug where the tables said one closer and Discord pinged another is structurally impossible.

For an active source, the pipeline runs the repeat-signup check and stamps history onto the record, upserts the CRM contact with tags merged and never duplicated, upserts and tags the contact in the mailing platform, and posts to the campaign's Discord channel with a prominent warning block if the family has signed up before or already received a free class.

The feature a salesperson asked for in plain words.

The most painful symptom surfaced on a team call: two closers were sometimes chasing the same family. A parent might sign up for a trial class twice, rotating to two different closers. Worse, a parent already being worked as a WhatsApp lead, someone the closer had called and built rapport with, would later click a Facebook ad and get re-rolled to a colleague by an automation blind to existing ownership.

The fix became a per-source toggle: keep the existing owner on repeat contact. When enabled, the worker checks the matched CRM contact before rotating. If the recorded owner is an active closer in the registry, that closer keeps the lead, no re-roll, no overwrite, the rotation counter isn't even consumed, and the Discord ping goes to the existing owner with the repeat warning attached so they know their parent has re-engaged.

The check is deliberately conditional on the owner being active. A contact owned by a closer who has since left the team is treated as unowned and re-enters the live rotation. When a closer departs, toggling them off in the registry is the entire offboarding process, their historical records stay untouched, and their families are naturally reassigned as they next make contact.

Every occurrence is visible in the log as "kept existing owner". The exact scenario the closer raised, her WhatsApp parent re-routed to a colleague by a trial-class ad, is resolved by design, not by a one-off patch.

Business decisions, not code decisions.

A single password-protected page, in the business's own branding, with four sections covering everything that used to require opening the automation platform and editing flows one by one.

Closers registry

Name, Discord ID, sort order, active toggle. Adding a closer once here makes them available to every lead source. Toggling someone off removes them from all rotations instantly. The header shows live state: next caller, active pool, counter position.

Sources, one per campaign

An unconfigured tab appears as a clickable button in a banner. One click opens a prefilled form reading the tab's actual column headers, presented as dropdowns with the correct picks auto-detected. A duplicate button clones a configured campaign, and a test-channel button verifies the Discord bot can post before going live.

Live log

Every lead that has ever hit the worker, newest first, with status (ok, paused, error, unconfigured), extracted contact details, assigned caller, and diagnostic notes such as "kept existing owner" or "repeat warning shown". Failures preserve the raw row for replay.

Settings

The shared rotation counter is adjustable, so the next lead can be steered to a specific closer, and the grade year is bumped once at annual rollover instead of edited inside dozens of code steps.

Auto-filled source creation

Every logged lead carries its header row, so the source-creation form reads real columns and pre-selects the right fields, validated against real form exports. Subject-specific forms without a class question use a fixed-value option typed once, flowing into every table, the CRM, and Discord automatically.

Everything editable per source

Field maps, record tags, mailing list and tag, Discord channel and title line, repeat-check and keep-owner toggles, all live on the same page a non-developer can operate, with no flow cloning, no trigger wiring, and no code.

Earned trust by being useless at first.

The system was designed to be additive until proven. Deploying the worker changed nothing. Connecting the spreadsheet changed nothing. The first configured source shipped paused, so early leads were merely logged. Go-live was per-source: activate one campaign alongside its still-running legacy flow, compare the two systems' outputs on real leads side by side, then retire the old flow, repeated tab by tab, with the ability to pause any source instantly if something looked wrong.

●

Outages delay, never lose

The watcher script never advances its row pointer unless the worker accepts the batch. If the worker is briefly unreachable, leads wait, they do not disappear.

●

Credentials out of flow definitions

All credentials moved into the platform's encrypted secret store, replacing plain text values that previously travelled with every flow export shared for debugging.

●

Standalone by design

Built separately from the business's existing messaging infrastructure, so lead-allocation iteration can never take down time-critical SMS reminders running elsewhere.

New campaigns onboard in under a minute.

A new form's first lead surfaces its tab in the dashboard automatically. One click, a glance at five auto-detected dropdowns, a tag and a title, and the campaign is live. No flow cloning, no trigger wiring, no code. The forty-tab spreadsheet went from a liability, forty triggers to maintain by hand, to an irrelevant detail: one script watches everything.

The pattern that made this work is worth naming: turn every hardcoded value into data, then put the data behind a door the operator can open. Callers, tags, channels, field mappings, table destinations, message titles, ownership rules, none of these are code decisions, they are business decisions that change weekly. The moment they moved from flow definitions into a database with a dashboard, the person who makes those decisions could also implement them instantly, without a developer in the loop.

One worker, one script, replacing dozens of flows.

Component Technology Purpose Cost
Backend and dashboard Cloudflare Worker (single JS file, no framework) All logic, ingest endpoint, and the four-section operations dashboard Free
State and configuration Cloudflare D1 (SQLite) Closer registry, source configuration, shared rotation counter, live log Free
Spreadsheet watcher Google Apps Script, one script for all tabs Detects new rows across every tab, posts to the ingest endpoint on change plus a 5-minute sweep Free
Campaign intake and central CRM Airtable REST API, two bases Per-campaign intake records and the central all-leads table, both stamped with the same decided caller Existing
Contact master and ownership CRM contact base, email-or-phone matching One-row-per-family lookup, upsert with merged tags, existing-owner check for the keep-owner rule Existing
Mailing list sync Mailchimp API Upsert and tag the contact on every lead, kept in step with the CRM Existing
Team notification Discord Bot API Per-campaign channel routing, closer mention, and repeat-signup warning block Existing

Dozens of edits collapsed into one toggle.

Rotation changes went from dozens of edits across the flow fleet to one dashboard action, taking effect on the very next lead across every campaign simultaneously. The silent-failure mode, rotation updated but the notification map forgotten, no longer exists, because there is no second place for the truth to live.

Duplicate assignments stopped by design. With the keep-owner rule enabled, a family already owned by an active closer stays with that closer across repeat signups and across lead types, because every source consults the same contact master. Contact duplication closed, since email-or-phone matching finds a family even when one identifier changes. New campaigns onboard in under a minute, and nothing disappears anymore: every lead, processed, paused, unconfigured, or errored, is logged with its raw payload.

The system earned trust by being useless at first: it shipped paused, logged everything, touched nothing, and ran side by side with the legacy flows until outputs matched on real leads. And the most valuable feature in the system did not come from an architecture review. It came from a salesperson saying, in plain words, "if it's already assigned to me, just keep it that way."