Available for work — Book a 30-minute call

Clinical-Safe Win-Back Campaign Engine

A weekly decision engine that identifies genuinely-lapsed patients for a re-engagement campaign — and, more importantly, identifies who must not be contacted. Encodes nineteen rules covering continuation windowing so nobody is messaged twice, authoritative retention checks that override misleading event logs, identity-safety matching for patients who share contact details, and a sensitivity classifier that withholds anyone whose cancellation reason indicates a medical emergency, a contraindication, a treatment directive, or a bereavement — routing those to a human instead. Implemented twice, in Python and JavaScript, kept behaviourally identical and covered by three test suites, with dry-run-by-default and an explicit human approval step.

Role
Designed and built
Sector
Massage therapy
Status
Active — production workflow live, reference CLI maintained
Stack
Python (pandas, pytest), n8n, JavaScript (node --test), Google Sheets, Slack, GoHighLevel

The problem

Patients who cancel and never rebook are lost revenue — that part is obvious. The risk is what makes it interesting. A blunt win-back campaign re-messages people you already contacted, because a rolling window overlaps last week's. It messages people who actually did rebook, because the event logs lie. And it sends a cheerful "we've missed you, come back" text to someone who cancelled because they were in an emergency department, had a blood clot, or lost a family member.

What was built

Nineteen documented rules, most of them suppression rules, running as a weekly batch over six source tabs and three state tabs, producing a Slack message for human verification before anything is sent.

The sensitivity classifier is layered with severity ordering: medical emergency first, then blood clots and anticoagulants (both a recognised massage contraindication and potentially life-threatening — and word-boundaried so it can't match "cloth"), then treatment directives like chemotherapy or post-operative care, bereavement, process flags, and practice-side cancellations where the clinic cancelled because a therapist was away, which makes a win-back inappropriate.

Crucially, hold recommendations are hold-only: never used as retention or exclusion evidence, and never able to override an existing exclusion. Clinical signals cannot leak into commercial decisions.

The hard part

Three rules that came directly from real data:

A continuation window, not a rolling one. The original rolling seven-day window overlapped the previous week's, re-pushing already-handled patients and sending some a second sequence inside their cooldown. That happened on a real run. The window now starts one second after the last successfully sent window, and the cursor advances only after delivery succeeds.

The authoritative snapshot beats the event log. The reschedule tab looks authoritative and isn't — it's an audit log containing the cancelled appointment's own history, which reads exactly like a rebooking. Trusting it would have silently excluded genuinely-lost patients.

Match on email AND name. Two different patients can share one email address and one CRM contact — families do this routinely. Matching on email alone would credit one person's rebooking as another's save, and worse, pushing would fire the campaign at a contact tied to an actively-booked patient.

What can be verified

  • A real defect caught in production and fixed by design change
  • the authoritative-snapshot rule caught three specific parallel or rebooked appointments the event logs had missed
  • no flagged patient is ever auto-pushed — a human reviews every batch
  • three test suites plus a byte-identical parity diff between the two implementations.

The workflow

The n8n graph for the weekly win-back run: a weekly schedule reads eight Google Sheets in turn, code assembles a batch, an IF gate routes candidates through an AI note screen over HTTP, and the finalised batch fans out to a team Slack message, a receipt message, and three separate append-only log sheets. (select to enlarge)
One weekly run, drawn as a graph. The record counts n8n prints on each connector are the client's own volumes, so those are covered; nothing else needed hiding. Select the image to enlarge it — a graph this wide is not legible on a phone.

On numbers: every figure above is an artefact count or a measured technical value. No business-outcome metric, whether time saved, revenue or conversion, was captured on these engagements, so none is claimed.

On status: reflects repository evidence and platform backups, not a live systems check.

Book a 30-min call