How to test a GoHighLevel workflow properly: the exit conditions are the test
Most workflows start correctly. Far fewer stop correctly. A repeatable test pass for GHL workflows covering entry, branch, wait, exit, opt-out and the double-enrolment problem.
Almost every GoHighLevel workflow you will ever open starts correctly. Somebody fills a form, the workflow fires, a message goes out. That part is easy to build and easy to verify, which is why it is the part everyone verifies.
The failures are all at the other end. The sequence that keeps texting after the person has booked. The reminder that fires for a cancelled appointment. The reactivation campaign that enrols a contact who is already in the nurture sequence, so they get two messages an hour apart from the same business. None of those are visible when you test by submitting a form and watching the first message arrive.
Here is a test pass that finds them.
Set up a testing rig you can reuse
Before testing anything, build this once per sub-account:
- A test contact with your own phone number and email. Not the client’s. You are going to send the same message eleven times.
- A second test contact for anything that needs two people in different states.
- A tag that identifies test contacts, so you can find and delete them, and so reporting can exclude them.
- A note of the current published state of every workflow, taken before you start. After an hour of testing, “was this one on before?” has no answer otherwise.
That rig takes ten minutes and gets reused on every subsequent change to the account.
The six things to test on every sending workflow
1. Entry
Trigger it the way a real person would — submit the actual form, book on the actual calendar, send an actual inbound message. Not the manual “add to workflow” button, which bypasses the entry condition you are trying to verify.
2. Branch
Every decision point, both ways. If the workflow branches on a custom field, run it with the field set and again with it empty. Empty is the common production case and the rarely-tested one.
3. Wait steps
Temporarily shorten long waits to minutes so you can watch the whole sequence in one sitting — then write down every wait you changed, and change them back. A day-three email that ships as a three-minute email is the single most embarrassing testing artefact there is.
4. Exit
This is the real test. For each sending sequence, ask: what should stop this? Usually some combination of:
- the person books
- the person replies
- the person buys
- the appointment is marked completed
- the person unsubscribes
- the person enters a different, higher-priority sequence
Then produce each of those states on a test contact and confirm the sequence actually stops. Not “should stop” — watch the next scheduled message not arrive.
5. Opt-out
Reply STOP from the test phone. Confirm the contact is marked unsubscribed, confirm the current sequence stops, and then confirm the contact is not enrolled by any other workflow afterwards. Opt-out handling at the platform level does not stop a second workflow deciding to enrol them.
6. Double enrolment
Trigger the same workflow twice for the same contact. Decide whether that should be allowed — for a booking confirmation, no; for a service reminder, probably yes — and confirm the setting matches the decision. Duplicate enrolment is the mechanism behind most “why did they get two texts” complaints.
The full-account test script
Individual workflows passing does not mean the account works, because the failures at scale are between workflows. Run this end to end on a fresh test contact:
- Submit a form from the client’s live public site.
- Confirm the contact appears in this account, with the source attributed.
- Let the first follow-up message arrive. Read it as a customer would.
- Book an appointment from the message link.
- Confirm the nurture sequence stops and the booking confirmation starts.
- Confirm the appointment appears in the human’s real external calendar.
- Let the reminder cadence run.
- Mark the appointment as a no-show. Confirm the recovery sequence starts.
- Reschedule. Confirm the recovery sequence stops.
- Mark the appointment completed. Confirm the review request fires.
- Reply to the review request. Confirm the follow-up stops.
- Reply STOP. Confirm everything stops.
Steps 5, 9, 11 and 12 are the ones that fail. Every one of them is an exit condition.
If you are running this before a launch, it belongs alongside the rest of the sub-account launch checklist; if you have just loaded a snapshot, it is the test pass referred to in loading a snapshot without breaking it.
Testing after a snapshot load specifically
Two extra checks, because a loaded snapshot has failure modes a hand-built account does not:
- Read the rendered message, not the template. A custom value referenced with a typo renders as nothing, and nothing is invisible in a template. See custom values vs custom fields.
- Confirm the data landed in this account. Trigger links and form redirects often still resolve to the account the snapshot was built in, so the test appears to pass while the record goes elsewhere. If the contact does not appear, that is the cause — see snapshot not loading.
Five bugs this pass finds that nothing else does
The sequence with no exit at all. Built in a hurry, entry condition only. It will text somebody for the rest of the account’s life. Nothing in the interface flags it; only walking the exits does.
The exit that is on the wrong step. The stop condition exists but sits after the message rather than before it, so the customer gets one more text after booking. Technically correct, practically the same complaint.
The two workflows that both watch inbound SMS. Common after a snapshot has been merged into an account that already had assets. Both fire, both reply, and the customer receives a conversation with itself.
The reminder that ignores cancellation. Appointment reminders keyed to the original booking, with no check for the appointment’s current status. Someone who cancelled on Monday gets a “see you tomorrow” on Wednesday.
The wait that was never changed back. Yours. It happens to everyone once.
Make it a monthly walk, not a launch ritual
Exit conditions degrade. Somebody adds a workflow, a new tag starts meaning something slightly different, a calendar is replaced and the old one still has a sequence pointed at it. None of that announces itself.
A short version of the script — one contact, one full journey, twenty minutes — run monthly on each live account catches almost all of it before a client does. On a portfolio built from one blueprint you can go further: run it properly on one account and spot-check the rest, because identical accounts fail identically. That is a benefit of standardisation nobody sells you on, and it only works if the accounts really are identical.
Cleaning up
Delete the test contacts, restore every wait step you shortened, restore the published states you recorded, and re-read your list of intentionally-disabled workflows so nothing ships switched off by accident.
Then write the test script into the account’s documentation. The point of a script is that the next person runs the same one — and if you are building accounts at volume, “the same one” is what makes forty accounts a single product rather than forty opinions. That is the standard every sub-account kit is built to, and it is what our sub-account setup service hands back alongside the live account.
This note is one stage ofthe complete guide to GoHighLevel sub-accounts — seven stages from a signed client to a live account.