A server cron scans estimate_links where customer_form_completed_at is null but signed_at is set within the last seven days. At 24h and 48h it raises a deduplicated admin alert and sends the customer a branded reminder email linking straight back to the form, then stamps form_reminder_24h_sent_at / form_reminder_48h_sent_at so nobody is nudged twice.
Also called: customer never filled the form · follow up reminder · intake stalled · chase the customer
- 1Cron selects unfinished links signed in the last seven days (limit 200), skipping demo ids.
- 2Elapsed time picks the 48h bucket first, else 24h, else nothing.
- 3An admin alert is inserted unless an unresolved one already exists for the same type + link ('Customer signed the estimate but hasn't started the information form yet.').
- 4The customer email fires only if the org's granular 'Form reminder' customer-message toggle is on, using the tenant's email brand.
- 5The sent-at stamp is written so 'anything already nagged is never re-nagged'.
This moved server-side after a real gap: 'this was a client-side scan in lib/contracts.ts that only raised ADMIN alerts, so the "form reminder" customer messages in Settings › Notifications never actually reached a customer — and nothing at all fired unless someone from the org happened to be logged in.'
- Approved estimates dying at the intake step with nobody noticing
- Reminders that only fire while a staff member has the app open
- The same customer being nudged repeatedly
See it on your own jobs
Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.
or keep browsing features →