Skip to content

How the estimate is built

Data version v2026.1, effective 2026-04-01. Every figure is modelled from published indices and a fixed task library. Nothing is scraped, crowd-sourced or quoted by a contractor.

Labour

Each task carries base hours per unit. Hours are multiplied by rule-driven complexity, the specification tier's install-time factor, a site-access factor and a regional productivity index.

Hourly rates start from published national median wages per trade, multiplied by an employer burden factor of 1.45 (payroll tax, insurance, non-billable time) and the local trade index. Each trade also carries a minimum mobilisation charge so a one-hour job never prices as one hour.

Materials

Quantities come from the task's expression, increased by a tier-specific waste factor, then rounded up to the way the product is actually sold (bundles, squares, sheets) with minimum order quantities respected.

Unit costs are tiered Good / Better / Best and adjusted by a bounded regional material multiplier. Sales tax and delivery are separate lines, never buried in the unit cost.

Overhead, contingency and other costs

Permits, inspections, equipment hire, disposal and protection are allowances gated by rules, scaled by local permit and disposal indices.

Contractor overhead and profit is applied once, as a visible line, in a band that narrows as job size grows: 25% / 21% / 17% at increasing project sizes. Contingency starts from a project base and rises with activated risk rules, capped so it can never dominate the total.

Confidence and ranges

Confidence scores location data quality, how completely conditions were answered, and how much concealed risk the scope carries. The band sets a minimum displayed spread: roughly ±12% at High, ±20% at Moderate and ±32% at Preliminary.

National-average estimates are capped at Preliminary by design. A thinly specified project cannot render a tight number.

Geographic coverage in this data version

Metro samples: Chicago, IL (measured) · San Francisco, CA (measured) · Houston, TX (measured) · Cleveland, OH (measured) · New York, NY (measured) · Billings, MT (interpolated) · Lima, OH (state_default)

State averages: Illinois · California · Texas · Ohio · New York · Montana

Anywhere else falls back to national averages and Preliminary confidence.

Analytics events

No personal data, no free text, no exact totals — money is bucketed before it leaves the page.

EventFires whenProperties
project_selectedA project card is chosenproject_id
calculator_startedThe wizard opens step 2project_id
step_completedEach wizard step is passedproject_id, step, step_index
question_abandonedA visible required field is left blank when leaving a stepproject_id, step, field
validation_errorA blocking validation message is shownproject_id, step, field, rule
estimate_generatedA calculation returnsproject_id, metro_id, data_level, tier, confidence_band, total_expected_bucket, rules_activated
web_vitalThe browser finalises a Core Web Vital for a real page loadmetric, value, rating
estimate_recalculatedInputs change after a first resultproject_id, reason
cluster_page_viewAn SEO cluster page (metro cost page or material variant) is viewedproject_id, metro_id, variant, page_type
tier_changedGood/Better/Best switchedproject_id, from, to
scenario_savedA scenario is stored locallyproject_id, scenario_count
scenario_comparedThe comparison view renders 2-3 scenariosscenario_count, project_ids
detailed_scope_openedA results accordion section is expandedproject_id, section
download_initiatedDownload button pressedproject_id, format
download_completedFile handed to the browserproject_id, format
contractor_interest_clickedContractor-quote CTA pressedproject_id, placement
monetisation_slot_impressionA monetisation slot is ≥50% in the viewport for 1s (once per mount)slot_id, slot_name, page_type, position, project, metro, visibility_ts, device_type, viewport, route
monetisation_slot_impression_endedA seen slot leaves the viewport or unmounts — carries measured attentionslot_id, slot_name, page_type, position, project, metro, visible_duration_ms