§ Build log · Build log · Helder Cristal

Building a quote calculator that pre-qualifies leads.

§ Quote · step 3 / 5

How big is the space?

Auto-quote in range · routes to instant email

The Helder Cristal calculator is the bit of the project we're proudest of. It started as a half-built form on the old site: eight fields, no logic, no follow-up. Today it routes 60% of inbound leads without a human, sends a real quote to ~half of them within 30 seconds, and saves the planning team about 14 hours a week.

This is the build log. The data model, the UX choices we got right, the ones we got wrong in week one, and the polite-decline email that turned out to be the most loved piece of copy on the site.

60%
Leads auto-qualified
30s
Median time to quote
14h
Saved per week, planning desk
+22%
Lead-to-customer conversion

From the first 14 weeks of production data

The job before the form.

We watched the planning team take five enquiries by phone before we wrote a single line. The shape of every conversation was identical: what kind of place, how big, how often, where, by when, what budget. Six questions in roughly the same order. The interesting bit was the branching. One early answer (kind of place) changed which follow-ups mattered.

So the form isn't really a form. It's a decision tree that looks like a form. Each step exposes the next based on the previous answer. The user never sees an irrelevant question.

Data model: keep it boring.

We resisted the urge to model this as a generic “survey” engine. It's one form, for one company, for one decade. The Postgres schema is six columns and a JSON blob:

db/migrations/001_quote_requests.sqlsql
1create table quote_requests (
2 id uuid primary key default gen_random_uuid(),
3 created_at timestamptz not null default now(),
4 contact_name text not null,
5 contact_email text not null,
6 contact_phone text,
7 outcome text not null, -- 'quoted' | 'visit' | 'declined'
8 estimated_value numeric(10, 2),
9 answers jsonb not null -- the full decision tree
10);

The answers JSON keeps the full tree of what they clicked. We don't join on it. The planning team queries the SQL columns. The JSON is for the auditor in us: if the calculator ever sends a wrong quote, we can see exactly what was answered.

The five-step flow.

One question per screen. Big buttons. Progress bar. Back button that actually goes back without resetting state. The five steps:

  1. Where: postcode + city. Out of zone? Polite decline, with referrals.
  2. What kind of place: office / shop / warehouse / something else. “Something else” routes to a visit.
  3. How big: m² range. Below the floor or above the ceiling routes to a visit.
  4. How often: once / weekly / fortnightly / custom.
  5. When: a calendar widget for first visit. Routes to the right planner's queue.

That's it. No phone number until the end. No email until step 4. The fewer fields rule beats the more fields = better lead quality myth. We tested it: shorter form, higher qualified-lead rate.

What broke in week two.

The calculator went live on a Monday. By Wednesday we had 90 enquiries and three angry phone calls. All three were people who'd been quoted a price they thought was too low: small offices that needed deep cleaning, where the standard rate didn't cover it.

The bug was a missing question: “how dirty is it, honestly?” The planners ask this on the phone, every time. We'd cut it from the form because it felt rude. Replacing it with three options, “normal,” “needs a deep clean first,” “haven't cleaned in months,” fixed it in 48 hours.

If the planning team asks it on the phone, it's a real question. No matter how rude it sounds in a form. Cut at your own risk.

The polite-decline email.

About 15% of leads get routed to a polite “this isn't us” email. Either too small (a one-time apartment clean), too specialised (industrial chemical residue), or out of zone. We were nervous about automating a no.

The email got rewritten three times. The version that's live now is six sentences:

emails/polite-decline.txttxt
1Subject: About your cleaning request · Helder Cristal
2
3Hi {firstName},
4
5Thanks for reaching out. Based on what you told us,
6this isn't a fit for us. Your place is just outside
7the zone we service, or smaller than the jobs we take on.
8
9Here's who I'd actually call: {referral.name}.
10They handle this kind of job and we trust them.
11
12If anything changes (bigger space, regular contract),
13we'd love to hear from you again.
14
15— {planner.firstName}

It's signed with the planner's name (rotated per week), not “The Helder Cristal Team.” The referral is real. We keep a small list of trusted regional alternatives. The thank-you reply rate is ~12%. People like being told no clearly, with a useful next step.

What we'd do differently.

Three things, in hindsight:

1. Ship the “how dirty” question on day one. The week-two scramble cost us trust with three customers and a small refund.

2. Log the abandons. We added abandonment events to PostHog after month two. Should have been there day one. ~18% of users abandoned at step 3 (size), and we couldn't see why until we instrumented it. Turned out the m² ranges were too coarse. Fix took an hour.

3. Build the planner-facing inbox first. The team initially saw new leads via email. After two weeks they wanted a proper queue with status, assignment, follow-up reminders. That should have been part of the V1, not a v1.5.

The calculator isn't a sexy piece of engineering. It's a form, a couple of tables, and an email template. But it does more for the business than the rest of the site combined, because it talks to a real person, in their words, about a real decision they already make every day.

— A.B., from the studio, after a calculator review meeting.