Rhafael CorpuzShopify & CRM automation · US, UK, AUBook a call
Case study · CRM automation

A leaking CRM, turned intothe system it runs on.

An Australian registered training organisation had GoHighLevel, but leads landed with no owner, forecasts were inflated, and a broken follow-up had stranded students mid-application.

ClientRegistered training organisation, Australia
RoleAudit, architecture, and build
StackGoHighLevel, n8n, webhooks, REST API, Node.js
What the audit found

Counted, then fixed.

Every finding came with a number, so the fix list could be ranked by cost and risk.

FindingCountFixStatus
Custom fields duplicated as mirror copies27Merged, with tighter access on sensitive fieldsdone
Contacts stuck in unpublished workflows~244Surfaced and routed back into live workflowsdone
Students stranded by a document chase with a bug26Chase rebuilt around a live checklistdone
New inquiries with no ownerallRound-robin assignment on arrivaldone
Ad spend in the marketing dashboard·Being wired inpartial
The architecture

GoHighLevel is the front door. n8n runs the logic.

GoHighLevel

What the team sees and uses every day
Contacts and custom fieldscrm
Pipelines and stagescrm
Calendars and bookingscrm
Two-way shared inboxcustom channel
Embedded marketing dashboardtoken-gated

n8n

The logic GoHighLevel can’t do natively
True days-in-stage averagescalc
Live evidence checklist in each emailrender
Net profit and amount-due roll-upcalc
Self-refreshing integration tokensauth
Access-controlled Drive foldersstorage
The evidence chase

A follow-up that stops on its own.

Each email lists only what’s still missing. Press play to watch one example file fill up.

Student file
Photo IDreceived
Qualification certificatesreceived
Employment evidencereceived
Signed declarationreceived
To: Sam (example student)Subject: Your file is complete
File complete. The chase has stopped.

No more reminders go out, and the opportunity moves on by itself.

Under the hood

The check that ends the chase.

// What is still missing from this student’s file?
const required = $json.course.requiredDocuments;
const received = $json.contact.documents;
const missing = required.filter((d) => !received.includes(d));
 
return [{
  json: { missing, complete: missing.length === 0 },
}];
n8n: evidence chase · code node
upload receivedget contactwhat’s missing?complete: stop chaseelse: email checklist
1The checklist is worked out per student, so every email lists only what is still missing.
2When complete is true, the chase stops on its own. The old one never stopped, which is how 26 students got stranded.
Simplified for reading. Client names and data removed.