GoHighLevel · Implementation Guide
How to Automate Lead Follow-Up in GoHighLevel
Knowing you need a trigger, a cadence, and an exit condition is the easy part — covered on the platform-agnostic lead follow-up guide. This page is the part that guide skips: the actual mechanics of building it inside GoHighLevel's workflow builder — which trigger type to pick, how the Wait step's options genuinely differ, how If/Else branching evaluates a contact, and how exit conditions are really configured, not the generic version.
On This Page
How to Build an Automated Follow-Up Workflow in GoHighLevel
This is the build order I actually use inside the GHL workflow builder itself — trigger, first touch, wait, branch, channel actions, then the exit logic, in that order.
Pick one trigger — Contact Created, Form Submitted, or Pipeline Stage Changed
Use Contact Created when you want every new contact hitting the account — from a native form, a funnel, an integration, the API — to enter the sequence the instant they exist. Use Form Submitted when only one specific form should start it, not every intake channel. Use Pipeline Stage Changed when follow-up should begin at a specific point in the sales process rather than at first contact — filtered by Pipeline, Pipeline Stage, Tags, or Assigned To so it only fires for opportunities actually moving into that stage, not every stage change in the account.
Send the first touch immediately, then add a Wait step — not a guess
Fire the first SMS, email, or WhatsApp action with no delay in front of it, then drop in a Wait step. GHL's Wait action is a menu, not one setting: Fixed Duration holds a contact for a set time regardless of what they do; Contact Reply is the one that actually waits for an event — it pauses the contact until they respond on the channel you specify, with an optional timeout so nobody sits there forever if they never reply.
Branch immediately after the wait with If/Else
The If/Else action checks the conditions you define — a tag, a custom field, whether a reply came in — and routes the contact down the first matching branch. It's evaluated once, as a snapshot, at the exact moment the contact reaches that step, not continuously monitored in the background. That's why it belongs right after a Wait step: check the contact's state the moment the wait releases them, not several steps later when the data may already be stale.
Layer Send SMS, Send Email, and WhatsApp action steps into the same workflow
All three sit in one workflow as separate action steps, each writing to the same contact record and the same Conversations thread — no need for three parallel workflows per channel. One GHL-specific catch worth knowing before you build the WhatsApp branch: sending a free-form WhatsApp message only works inside the 24-hour customer service window after the contact last messaged you; outside that window, the action needs an approved Meta template instead, or it won't send.
Configure a Goal Event so the workflow knows what 'done' looks like
The Goal Event action defines a milestone — a form submitted, a payment received, an appointment confirmed, the contact replying — and lets you choose what happens the moment a contact hits it: end the workflow for them, let them continue anyway, or hold them until the goal is met. Only one Goal Event action can exist per workflow, and once a contact satisfies it, they're not evaluated against it a second time in that same run.
Use Remove from Workflow for the exits a Goal Event doesn't cover
An explicit opt-out is the clearest case: a tag like 'stop-contacting' triggers a small separate workflow whose only job is a Remove from Workflow action, scoped to Current Workflow, a named workflow, All Except Current, or All Workflows — the last option is the one that matters for opt-outs, since it pulls the contact out of every active sequence in one action instead of needing a Goal Event configured into each workflow individually. It's worth knowing removal isn't automatically reversible — re-enrolling a contact later takes a separate deliberate action.
Wait Steps, If/Else, and Exit Conditions — Where People Actually Get Stuck
Three parts of the GHL workflow builder cause almost every follow-up sequence bug I get asked to fix. Worth understanding properly before you build, not after.
The Wait action isn't a single setting — it's a menu of genuinely different behaviors. Fixed Duration and Specific Date/Time hold a contact against the clock, full stop. Contact Reply and Contact Action are the event-based options: Contact Reply pauses a contact until they actually respond on a channel you specify, and Contact Action pauses until they click a trigger link or engage with an email, both with an optional timeout so nobody gets stuck waiting forever. The mistake I see most often is a Fixed Duration wait used where a Contact Reply wait belongs — the sequence then sends its next touch on schedule regardless of whether the lead already replied, which is exactly the "why did they get a follow-up message after they already answered" complaint that makes automation look sloppy.
If/Else branching is a snapshot check, not a live monitor. When a contact reaches an If/Else action, GHL reads the contact record and that run's event data as they stand at that exact instant, compares them against your conditions top to bottom, and drops the contact into the first branch that matches. It does not keep re-checking afterward. That's the practical reason to put the branch immediately after the Wait step it depends on — check the reply status right when the wait releases the contact, not three actions later once the state it's checking may already be stale.
Exit conditions run through two distinct actions, and picking the wrong one is a common design mistake. Goal Event is scoped to one workflow — it defines a milestone (a reply, a booking, a payment) and lets you set what happens when a contact hits it: end the workflow, continue anyway, or wait until it's met. Only one Goal Event action is allowed per workflow, and a contact isn't evaluated against it twice. Remove from Workflow reaches further — Current Workflow, a named workflow, All Except Current, or All Workflows — which is the one you want for a genuine opt-out, since it can pull a contact out of every active sequence in the account with a single action instead of needing a Goal Event built into each workflow separately. Neither reverses itself automatically; re-enrolling a removed contact is a deliberate, separate step.
Frequently Asked Questions
Fixed Duration holds the contact for a set length of time no matter what they do — 2 days, 6 hours, whatever you set — and then continues regardless. Contact Reply is event-based: it pauses the contact until they actually respond on the channel(s) you specify, with an optional timeout so they're released either way instead of sitting in the wait step indefinitely. If the whole point of the pause is to give a lead a chance to reply before you send the next touch, Contact Reply is the correct wait to use — a Fixed Duration wait will fire the next message on schedule even if they replied five minutes after it went out.
Want This Workflow Built in Your GHL Account?
Everything above is genuinely buildable inside your own GoHighLevel account with an afternoon and this page open in another tab — I'd rather you actually ship it than not. If you'd rather it just be built correctly the first time — trigger, Wait logic, If/Else branching, and exit conditions all tested against real scenarios before it goes live — this is exactly what I build through GHL automation in Dubai, or remotely anywhere else through GoHighLevel automation consulting, worldwide.
- 7+ years building GoHighLevel workflows and CRM automation for businesses worldwide
- 100,000+ leads delivered through follow-up systems built the same way this guide describes
- One real estate automation system alone responsible for 50,000+ of those leads
Ready to Get This Running in Your GHL Account?
Fastest way to start: message me directly on WhatsApp with what your current GHL setup looks like. Or send the details below and I'll get back to you.