Customer-recovery automation · 06 / 09
WhatsApp Bot
Finds inactive WhatsApp customers and runs paced, opt-out-safe win-back campaigns from a local dashboard.
- Role
- Solo developer · client project
- Year
- 2026
- Status
- MVP complete
- Platform
- Windows (WSL2 + Docker)
Overview
The project.
Built for a shipping and shopping company with thousands of WhatsApp Business conversations. Customers who stop writing get lost in the volume; the owner wanted to find people inactive for 30, 60 or 90+ days and win them back.
The tool runs beside WhatsApp Business on the office PC. It pairs as a linked device, syncs chat activity, segments customers by inactivity and sends small campaigns slowly and safely. It installs on Windows with an isolated WSL2 and Docker runtime and encrypted backups.
The problem
Re-engaging old customers on WhatsApp without breaking trust: keep WhatsApp Business in daily use, never spam or message anyone twice, and honour opt-outs like “STOP” or “لا تراسلوني”.
My solution
A Laravel and Filament dashboard that syncs chats through WAHA, targets inactive customers and sends 10–80 message campaigns through one paced queue worker, with at-most-once delivery, cooldowns and bilingual opt-out detection.
What it does
Key features.
- 01
QR linking
Pair the company's existing WhatsApp number as a linked device from the dashboard, and manage the session there.
- 02
Customer sync
Pages through every chat, normalizes Libyan phone numbers (including Arabic-Indic digits) and records each sync run with its counts.
- 03
Campaign builder
Pick an inactivity window and a target count, and write a message with a {{name}} placeholder.
- 04
Live campaign control
Start, pause, resume and stop, with sent and total progress.
- 05
Send safety
45–90 second jittered pacing, a daily limit, a per-customer cooldown and one active campaign at a time.
- 06
Bilingual opt-out
Detects Arabic and English opt-out messages and keeps an audit trail; staff can also opt people out manually.
- 07
Arabic & English panel
A bilingual admin panel with theme controls and security headers.
- 08
Installer and backups
Windows setup, start and stop launchers, plus GnuPG-encrypted backup and verified restore.
Under the hood
How it's built.
Architecture and the engineering decisions behind it.
01
A linked device, not a new number
WAHA's NOWEB engine pairs with the existing WhatsApp Business account by QR, so staff keep using WhatsApp normally while the tool reads activity and sends.
02
Sync before every campaign
Sync pages through chat overviews 100 at a time, re-reads the first page to catch chats that moved, then upserts customers. It runs on demand, before each campaign and every 15 minutes.
03
Recipients chosen in one transaction
Starting a campaign takes a global lock, then selects recipients who are not opted out, are past the inactivity and cooldown windows and have no unconfirmed sends, longest-inactive first.
04
One paced worker
A job batch on a single queue worker enforces pause and stop, a minimum gap between sends, the daily budget and an atomic claim on each message before calling WAHA.
Problems solved
Technical challenges.
No double sends after a network failure
Each message is claimed exactly once under a row lock. Only a 4xx counts as “not sent”; timeouts and 5xx stay unconfirmed and are never retargeted until an operator reviews them.
Pacing that survives pauses and restarts
The minimum gap is checked again at send time, releases during a pause are jittered so resuming doesn't burst, and the daily budget is counted from the database.
Opt-outs in Arabic and English
Arabic letters and diacritics are normalized, single words match only as the whole message (so “cancel my order” isn't an opt-out) and negations block a phrase match.
A slow admin panel on Windows
Moving the code off the Windows-to-WSL bind mount took page times from 1.0–1.8 s to about 0.05–0.07 s, and removing external fonts and avatars cut browser load further.
Development status · MVP complete
What's next.
Everything above is built and working. These parts are planned and not implemented yet:
- Instant opt-out handling (today it syncs every 15 minutes)
- Official WhatsApp Cloud API as an alternative channel
- Phone formats beyond Libya and richer message templates
- A live send test on the client's account and a clean-machine install test