Skip to main content

Home / Case study · CRM + operations

Inspection Revenue Engine

Production GoHighLevel and n8n system for a multi-inspector home-inspection company.

Ran in production, May to September 20262026

GoHighLevel · n8n · Python · Supabase · Inspection-software webhooks

n8n production dashboard, June 2026: 318 production executions, 0 failed, 0% failure rate, 0.7 second average run time, with the inspection-software-to-GoHighLevel event workflows published.
  1. 1Every production run was logged here. Zero failed in this read, at a 0 percent failure rate.
  2. 2Three event workflows: every booking, report, and payment wrote into the CRM automatically.
  3. 3A separate alerting workflow emailed me the moment any event failed.
The n8n production dashboard, read in June 2026. These are the real numbers the stats above are read from.
0
failed of 318 executions, one dashboard read
May 2026
went live
318
production executions
0.7s
avg run time
~8,000
contacts migrated
6,500+
opportunities migrated

Context

A multi-inspector US home-inspection company ran everything on its inspection software, with no CRM underneath. Years of client and agent history sat locked in one tool. No marketing attribution, lead generation by hand, follow-up by memory. Real revenue and real customers, and a history they couldn't market from or report on.

I built the production system around it. A GoHighLevel CRM from scratch, a custom integration bridging the inspection software into it over self-hosted n8n, a full historical migration of their book of business, and a marketing-to-revenue attribution layer. It went live in May 2026, ran in production on the business's real booking, report-delivery, and payment events, and was shut down on 2026-09-16.

Constraints

The original scope assumed a two-way sync, data flowing back into the inspection software. Deep discovery killed that assumption. The platform is outbound-webhook-only, with no inbound API and no programmatic write path of any kind. The direction we'd promised was impossible.

Most builders either quote that two-way sync and miss at the deadline, or quietly drop it and hope nobody notices. I put the correction in writing as an explicit scope change while there was still time to act on it, then re-architected around the real constraint.

The data had to migrate clean on top of that. Years of records, with duplicate contacts and phone-number collisions that GoHighLevel rejects at the server. A migration that loses relationship history is worse than no migration.

Approach

Instead of a fake sync, I built forward-direction enrichment. When a booking fired, the bridge looked the agent up in GoHighLevel and created or updated the contact, and a one-time historical backfill ran through the platform's CSV export path. The client got a complete, continuously updated CRM and no pretend two-way sync.

The integration ran on self-hosted n8n on a hardened Linux VPS. Three production event workflows, booking created, report delivered, and payment completed, routed every inspection across a 50-service catalog. Every inbound event deduped against a composite-keyed Postgres ledger, so vendor retry storms couldn't double-write the CRM. Phone-number collisions got caught, retried without the colliding field, and tagged for human review instead of failing silently. A separate workflow polled hourly and emailed me the moment any event failed.

The attribution layer tied a marketing touch to the booking it eventually drove. Per-event QR codes fed a tagged capture form and a structured nurture sequence, and the booking webhook traced that touch back months later.

Exhibits

The Booking Created workflow canvas in n8n, showing the intake, dedup, collision-handling, and opportunity-creation nodes.
  1. 1Every booking entered on the left and deduped against a keyed ledger, so vendor retries never double-wrote the CRM.
  2. 2Phone-number collisions got caught, retried without the colliding field, and tagged for review instead of failing silently.
  3. 3On the right the booking became an opportunity in the CRM, stamped with the agent who sent it.
Booking Created, one of three production event workflows. It routed every inspection across a 50-service catalog with dedup, retries, and idempotency.
The failure-alerting workflow canvas in n8n: a scheduled poll, a real-error filter, and an email step.
  1. 1A schedule kicked it off every hour.
  2. 2It filtered for real failures, not routine noise.
  3. 3Then it emailed me the moment a production event actually failed.
The failure-alerting workflow. It polled hourly, filtered for real errors, and emailed me the moment a production event failed.

Status

Status

Shipped
Inspection software to GoHighLevel data bridge
Shipped
One-time historical backfill
Shipped
Agent and CE nurture intake
Shipped
Weekly automated health audit
Shipped
Lifecycle automations
Shipped
Team operations dashboard, behind auth
Results

Revenue results are the client's private data. I publish capability, not his numbers.

Result

Went live in May 2026 and ran in production on the business's real booking, report-delivery, and payment events. Real revenue data, not test traffic. One read of the production dashboard in June 2026 showed 318 executions, 0 failed, a 0% failure rate, and a 0.7-second average run time. The residential pipeline alone held about 5,800 opportunities at the time of the backfill.

The historical migration moved roughly 8,000 contacts and 6,500-plus opportunities with clean deduplication and zero lost relationship history. The lifecycle-automation milestone went live, and a custom team-operations dashboard ran behind auth on the client's own subdomain. The system was shut down on 2026-09-16.

Stack

GoHighLevel · inspection software (Advanced-tier webhooks) · n8n (self-hosted) · Python · Supabase / Postgres · Resend · Next.js · hardened Linux VPS behind Caddy with auto-TLS