19 GoHighLevel workflows for three businesses. Try every one yourself.
GoHighLevel is an all-in-one sales and marketing platform: contacts, landing pages, texts, emails, calendars and a sales board in one place. A workflow is a set of automatic steps inside it. When someone fills in a form or calls, a workflow can email and text them, hand the lead to a salesperson, remind that person to call, and stop the moment the customer replies.
I built 19 of them for three made-up businesses: a roofer, a software company and an online coach. Each one also has a working landing page. Everything runs here in your browser, on sample customers or with your own name. Need this for your business, or hiring for GoHighLevel? Get in touch.
How to use this page
- Pick a business. New to GoHighLevel? Start with the roofer.
- Be the customer. Fill in its sign-up form with any name, or pick a sample customer such as “Never replies” or “Submits at 11:48 PM”.
- Press Run. Watch every email, text and task go out, with the time each would happen. Days of waiting are fast-forwarded.
Short on time? Each workflow opens with The problem and What I built in plain words. The diagrams and Build notes are the detail a GoHighLevel builder would check. Words you may not know
- Workflows you can run
- 19
- Automatic steps inside them
- 532
- Sample customers to test with
- 106
- Possible paths, each one reached by a test
- 188/188
Are these real businesses?
No. Harbor & Pine Roofing, Crewlo and Trailhead Career Coaching, and everyone who works there, are made up, so every workflow can be shown end to end with its real messages and tried by anyone. The workflows themselves use GoHighLevel’s real triggers, actions and settings, checked against HighLevel’s help center, so each one can be rebuilt step for step in a real account. Nothing on this page sends a message or keeps what you type.
Who built this
I’m Nick Soderstrom, a project and operations lead who also builds CRM automations in GoHighLevel, HubSpot, Zoho and Zapier. My client work includes a 2025 Upwork contract for GoHighLevel, Zapier and Slack automations (see recent contracts). This page and its simulator were built by directing AI, like the projects on my AI Projects page.
GoHighLevel words in plain English (21)
- GoHighLevel (GHL, HighLevel)
- An all-in-one sales and marketing platform: contacts, landing pages, texts, emails, calendars and sales tracking in one place. Agencies often run it for their clients.
- Sub-account
- One business’s own space inside GoHighLevel, with its own contacts, workflows, phone numbers and settings.
- Workflow
- A set of automatic steps that runs on its own, such as “email the lead, assign a salesperson, wait a day, text again.”
- Trigger (the orange lightning bolt)
- The event that starts a workflow: a form sent, a missed call, a booking, a deal card moving.
- Contact, contact record
- A person in the account, and everything saved about them: details, answers, tags, owner and history.
- Lead score
- A number from 0 to 100 that a workflow gives each new lead from their answers. For the roofer it comes from the service, the roof’s age and where the lead came from. The higher it is, the sooner someone should call.
- Custom field, tag
- A custom field is an extra box on the record for the business’s own answers, like roof age. A tag is a short label, like stl-no-response, that other workflows can react to.
- Pipeline, opportunity, stage
- The sales board. Each deal is a card (GoHighLevel calls it an opportunity) that moves through stages such as New Lead and Job Complete. Its status is Open, Won, Lost or Abandoned.
- Round robin
- Handing new leads to salespeople in turn, so the work is shared evenly.
- If/Else, branch
- A fork in the workflow: “Agreed to texts? Yes: text them. No: email only.” Each path is a branch.
- Wait, Go To, goal
- A Wait pauses for a set time or until something happens. Go To jumps to another step. A goal lets the contact skip ahead once they do what the workflow was after, like booking.
- Stop on Response
- A setting that ends the automatic follow-up as soon as the customer replies, so a person can take over.
- DND (Do Not Disturb)
- A switch on a contact that blocks texts, emails or calls. Texting STOP turns it on for texts; these workflows also turn it on for anyone who didn’t agree to texts.
- Quiet hours, time window, Advance Window
- Settings that hold a message until an allowed time, so nobody gets a sales text at night.
- Re-entry
- Whether someone who already went through a workflow can go through it again later, like a past lead who asks again next year.
- A2P 10DLC
- The registration US phone carriers require before a business can send texts from an ordinary local number. Reviewers check how people opt in.
- UTM tags
- Labels on a link, like utm_source=google, that record which ad or email brought a visitor.
- Landing page, funnel
- A one-purpose web page, or a short series of pages, built to get one action, like booking an inspection.
- Merge fields, custom values
- Placeholders like {{contact.first_name}} that fill in each person’s details when a message goes out. Custom values keep things like the booking link in one place.
- Execution log
- GoHighLevel’s step-by-step record of what a workflow did for one contact, with times. The simulator here shows the same kind of log.
- Custom Code, webhook
- Custom Code runs a short script inside a workflow, here to score leads. A webhook is an automatic message from one app to another, like “trial started.”
Harbor & Pine Roofing
Harbor & Pine is a local roofing company with two estimators, an office manager and a production crew. Leads came from the website, Facebook and the phone, and too many went cold before anyone called back. The owner needed every lead answered in seconds, inspections that people actually show up to, estimates that get a decision, a clean hand-off to the crew, and reviews from every finished job.
- Workflows
- 7
- Steps
- 197
- Sample customers
- 42
- Where
- Chicago suburbs
The sample team
- Maya Ortiz Estimator (sales)
- Luis Grant Estimator (sales)
- Jordan Blake Owner and office manager
- Sam Rivera Production manager
Harbor & Pine Roofing is a fictional company. The people, phone numbers and links are samples.
One pipeline, one customer journey
Each workflow does one job and hands the customer to the next. The orange text with the lightning bolt on each card is its trigger: the event that starts it. The grey chips are the stages of the sales board (GoHighLevel calls it a pipeline), where each customer’s card moves from left to right. Pick a card to open that workflow below.
Roofing SalesNew LeadContactedInspection BookedInspectedEstimate SentJob ScheduledJob Complete
- 01Speed to leadForm SubmittedNew Lead, then a person on reply
- 02Missed-call text-backCall DetailsNew Lead from a missed call
- 03Inspection bookedCustomer Booked AppointmentInspection Booked → Inspected
- 04Estimate follow-upPipeline Stage ChangedEstimate Sent → Won
- 05Won to job hand-offOpportunity Status ChangedJob Scheduled → Job Complete
- 06Reviews and referralsPipeline Stage ChangedReview and referral asks
- 07Database reactivationContact TagOld leads back to New Lead
The landing page, working
Fill in the form as if you were a customer and press Get my free inspection. Use any name and a made-up number if you like: nothing is sent or stored. Then press Watch the workflow run, which appears once you submit, to see each email, text and task you would get from workflow 01 · Speed to lead, and when. It runs at your local time, so if it is late where you are, you will see texts wait for morning.
Chicago suburbs · Free inspection
Storm damage? Get a free roof inspection this week.
One of our estimators checks your roof, photographs anything that needs attention and sends you a written estimate within 24 hours. No pressure and no cost.
- Licensed and insured
- Photos of every issue we find
- Help with insurance claims
Step 2 of 2: pick a time. On the live page the Roof Inspection calendar sits here, with your details already filled in (GoHighLevel’s Sticky Contact). The times below are a preview only. To see what booking does, choose “Book from the link” under Play the customer, then press Watch the workflow run.
Preview only (not clickable)
In short: one goal and no menu, a six-question form, separate unticked boxes for service texts and for offers, hidden fields that record which ad brought the visitor, and the booking calendar on the thank-you page.
How the page is built in GoHighLevel’s funnel builder (7 notes for builders)
- One goal, one actionNo navigation menu on the step, and every button on the page leads to the same form. The copy is short, plain and specific to the offer.
- A short, honest formSingle column, labels above the fields, six questions. The two SMS consent boxes are separate (inspection updates, and offers), unticked and optional, with the Privacy Policy and Terms linked, which is what A2P reviewers look for.
- Hidden UTM fieldsCustom fields utm_source, utm_medium and utm_campaign with Hidden on and a Query Key that matches the URL parameter exactly. GHL already records First and Latest Attribution by itself; the fields are there so workflows, filters and merge fields can use the values.
- Thank-you step with the calendarStep 2 embeds the Roof Inspection calendar. Sticky Contact prefills the booking form, so nobody types their details twice, and booking fires workflow 03.
- Tracking that survives editsMeta Pixel and GA4 go in the funnel’s head tracking code. GHL does not copy tracking code when a step is cloned, so re-checking it is on the launch checklist.
- Fast on a phoneOptimize JavaScript and Image Optimization on, hero image under 200 KB. Any custom script listens for the hydrationDone event, so deferred loading does not break it.
- Test the headline, not the button colorA split-test variation on the step with a 50/50 slider. The Stats tab reports opt-in rate as opt-ins divided by unique page views, and one variation wins before the next test starts.
Pick a workflow, pick a sample customer, press Run
Each tab below is one workflow. Read The problem and What I built for the short version. Then pick a sample customer and press Run workflow: the log lists every email, text and task in order, with the time it would happen, and the diagram ticks off each step as it runs.
For GoHighLevel builders: the diagram reads as it does in the workflow builder, and the simulator follows the builder’s rules: branches never rejoin, a goal pulls the contact forward, Stop on Response ends the run, DND skips the message and time windows hold it. New to the words? Open the decoder.
Speed to lead
Every new lead gets an email, an owner and a call task within seconds, and a text if they asked for one (at night it waits until 8 AM). A person takes over the moment they reply.
The problem
Leads from the website and Facebook sat in the inbox until someone noticed. By the time a rep called, the homeowner had booked another roofer.
What I built
One workflow for both lead sources: it finds or creates the opportunity, scores the lead, assigns a rep by round robin, emails them and gives them a call task, then follows up by text and email for a week. Leads who did not tick the SMS box are switched to email only, and no text goes out before 8 AM. It stops the moment the lead replies, and steps aside as soon as they book.
Companies that tried to reach a web lead within an hour were nearly seven times as likely to qualify it as those that waited even one hour longer, and over sixty times as likely as those that waited a day or more.
- Re-entry
- Allowed
- Stop on response
- On
- Timezone
- Contact
Why these settings, and when it stops early (5)
- Allow Re-entry on: a past lead who asks again next spring gets a fresh follow-up, and the first step takes them out of 07. GHL never enrolls a contact who is still active in the workflow, so a double submit during the week starts nothing.
- Stop on Response on: a reply to any text or email from this workflow hands the lead to their rep.
- No workflow Time Window: it would hold the email to the lead too. The texts wait behind their own 8 AM to 8 PM Advance Window.
- Allow multiple Opportunities is for opportunity-based triggers. Here Find Opportunity and the Duplicate Opportunity toggle on Create Opportunity decide the card.
- Leaves early: Booking fires 03 · Inspection Booked, whose first step is Remove from Workflow: 01 · Speed to Lead. No more "are you still interested?" texts to someone who already booked.
The workflow as it reads in GoHighLevel’s builder. Scroll inside it; each step gets a green tick when the run reaches it.
- Form SubmittedForm is Free Roof Inspection
- Facebook Lead Form SubmittedPage is Harbor & Pine Roofing · Form is Storm Inspection 2026
- Remove from WorkflowOne follow-up at a time
Another Workflow: 02 · Missed-Call Text-Back and 07 · Database Reactivation. A caller or an old lead who fills in the form gets this follow-up only, not a second one running alongside it.
- Find OpportunityOpen card already?Opportunity FoundLatest opportunity in Roofing Sales with Status Open
- Update OpportunityName the card
Opportunity Name is {{contact.name}} · {{contact.service_needed}}. A card 02 made from a missed call only had a phone number to go on. Stage, status and source stay as they are.
- Custom CodeLead score
Scores the lead 0 to 100 from the service, roof age and source, and sets how fast the rep should call: 15 minutes or an hour, or first thing after 8 AM for a lead that arrives outside the hours the texts keep.
View the code
// Custom Code step, JavaScript. Properties added in the step: // service = {{contact.service_needed}} // roof_age = {{contact.roof_age}} // source = {{contact.source}} // hour = {{right_now.hour}} (24-hour; all Harbor & Pine leads are local) // GHL wraps this in an async function and reads the result from `output`. const service = (inputData.service || '').toLowerCase(); const age = inputData.roof_age || ''; let score = 20; if (service.includes('storm')) score += 35; else if (service.includes('replacement')) score += 30; else if (service.includes('leak')) score += 25; if (age === 'Over 20 years') score += 25; else if (age === '10-20 years') score += 15; // The owner asked for lead-ad leads to rank a little below form fills. if ((inputData.source || '').toLowerCase().includes('facebook')) score -= 5; score = Math.max(0, Math.min(100, score)); // Calls keep the same 8 AM to 8 PM hours as the texts. const hour = Number(inputData.hour); const afterHours = hour < 8 || hour >= 20; output = { lead_score: score, call_within: afterHours ? 'first thing after 8 AM' : score >= 70 ? 'within 15 minutes' : 'within 1 hour', }; - Update Contact FieldSave the score
Writes the code output to Lead Score and Call Priority, so reports, filters and later steps can use it.
- Assign To UserRound robin
Maya and Luis, Split Traffic Equally. Only Apply to Unassigned Contacts is on, so a returning customer, or a caller 02 already assigned, keeps their rep.
- Internal NotificationTell the rep
Type Email, To User Type Assigned User, with the score and how fast to call. Not a text to the rep at midnight; the call task below is the second channel.
New lead:
{{contact.name}}, score{{contact.lead_score}}/100{{contact.service_needed}}, roof{{contact.roof_age}}, SMS consent{{contact.sms_consent}}. Call{{contact.call_priority}}:{{contact.phone}} - Send EmailRequest received
Confirms the request, says who will call and links the booking page. Every lead gets it, texts or not.
Your free roof inspection requestHi
{{contact.first_name}}, Thanks for reaching out to Harbor & Pine Roofing.{{user.first_name}}will call you from{{custom_values.office_phone}}to set up your free inspection. If it is easier, pick a time yourself:{{custom_values.booking_link}}An inspection takes about 45 minutes. You get photos of anything we find and a written estimate.{{user.name}}{{location.name}},{{location.full_address}} - If/ElseWhose call?LuisAssigned User is Luis Grant
- Add TaskCall task for Luis
Assign To Luis Grant, Due In: Now. Title "Call {{contact.first_name}} {{contact.call_priority}}". The description has the service, roof age, score and SMS consent, so nobody texts a lead who did not tick the box.
- Go To→ Can we text?
Back to the consent check, so both estimators share one follow-up sequence.
MayaNone of the above- Add TaskCall task for Maya
Assign To Maya Ortiz, Due In: Now. Title "Call {{contact.first_name}} {{contact.call_priority}}". The description has the service, roof age, score and SMS consent, so nobody texts a lead who did not tick the box.
- If/ElseCan we text?SMS consentSMS consent (service) is Yes, and the contact is not DND for SMS
- WaitQuiet hours
A set period of time of 0 minutes with an Advance Window: resume between 8 AM and 8 PM in the contact's time zone, so a lead at midnight gets their text at 8 AM.
- Send SMSInstant reply
From the rep, with the booking link and the opt-out line.
Hi
{{contact.first_name}}, it's{{user.first_name}}at Harbor & Pine Roofing. Got your inspection request. Pick a time here:{{custom_values.booking_link}}or reply with a good time to call. Reply STOP to opt out. - Wait1 day
One day.
- Send SMSNudge
Short, from the same rep, one link.
Hi
{{contact.first_name}},{{user.first_name}}again from Harbor & Pine. Still want that free roof inspection? It takes about 45 minutes. Book here:{{custom_values.booking_link}} - Wait2 days
Two days.
- Send EmailWhat we check
Says what the inspection covers instead of another "just checking in".
What we look for on a free roof inspectionHi
{{contact.first_name}}, On every inspection we check shingles and flashing, vents and pipe boots, gutters and the attic for signs of leaks, and we photograph anything that needs attention. No pressure and no cost. Book a time that suits you:{{custom_values.booking_link}}{{user.name}}{{location.name}},{{location.full_address}} - Wait4 days
Four days.
- Send SMSLast try
Closes the loop politely. A reply to this one still stops the workflow.
Hi
{{contact.first_name}}, I'll close out your inspection request for now. If you still want one, reply here or book:{{custom_values.booking_link}}Thanks,{{user.first_name}} - Add Contact Tagstl-no-response
Marks the lead for the no-response report and for the 07 · Database Reactivation list later.
- Go To→ Still at New Lead?
Joins the email path at the close-out, so there is one copy of it.
No consent, or texts offNone of the above- Enable/Disable DNDTexts off
Direction Outbound, Enable, selected channel SMS. They did not tick the box, so 02, 03 and every later workflow skip texts to them as well. Email and calls stay open.
- Add Contact Tagsms-off-no-consent
A receipt for the DND above. If they tick the texts box when they book, 03 · Inspection Booked reads it as a new opt-in, lifts the DND and removes the tag.
- Wait1 day
One day.
- Send EmailFollow-up
Booking link and the office number.
Still want your free inspection,
{{contact.first_name}}?Hi{{contact.first_name}}, Following up on your free roof inspection request. Pick any open time here:{{custom_values.booking_link}}, or call us at{{custom_values.office_phone}}.{{user.name}}{{location.name}},{{location.full_address}} - Wait3 days
Three days.
- Send EmailClosing the request
Last email, easy to answer.
Closing out your inspection requestHi
{{contact.first_name}}, I will close out your request for now. If your roof needs a look later, reply to this email or book at{{custom_values.booking_link}}.{{user.name}}{{location.name}},{{location.full_address}} - Add Contact Tagstl-no-response
Same tag as the text path, so the report counts both.
- Find OpportunityStill at New Lead?Opportunity FoundLatest opportunity in Roofing Sales, Stage New Lead, Status Open
- Update OpportunityAbandoned
Status Abandoned, not Lost: they never said no. The board only shows live leads, and 07 · Database Reactivation can pick them up later without a clean-up first.
- End
Opportunity Not FoundNone of the above- Add to NotesCard already moved on
The card is past New Lead or already closed, so a rep has it. The follow-up ends and leaves the card as it is.
- End
Opportunity Not FoundNone of the above- Create OpportunityNew lead
Roofing Sales › New Lead, named {{contact.name}} · {{contact.service_needed}}, Opportunity Source {{contact.source}}. Duplicate Opportunity on: this only runs when there is no open card, and with it off a lead whose only card was lost last year would get none.
- Go To→ Lead score
On to the score. Nothing later updates the card, so it does not need to be found again.
Running with you as the customer: , at your local time, with your form answers. What you do next: (your choice under Play the customer, on the landing page). Nothing is sent or stored.
- Pick a sample customer above, then press Run workflow. Each line is one step, with the time it would happen: blue bubbles are texts, boxes are emails, and notes marked To: or Slack go to the team. Days of waiting are fast-forwarded.
Build notes
The detail a GoHighLevel admin would check before trusting this workflow. Start with What if… for the unusual cases in plain words. Words you may not know
- Lead comes in at midnightThe email to the lead, the rep's email alert and the call task happen immediately, but the code sets Call Priority to "first thing after 8 AM", so nobody is told to phone a homeowner at midnight. The text waits for the Advance Window and goes out at 8 AM, around the same time as the call.
- No SMS consent, or DNDThe If/Else sends them down the email path, which turns SMS DND on first, so 02, 03 and the rest skip texts to them too. Ticking the box on the inspection form again does not turn texts back on. Ticking it on the booking calendar does: 03 · Inspection Booked treats that as a new opt-in and lifts a DND that carries the sms-off-no-consent tag, never one from a STOP. Any other new consent, the office checks and switches SMS DND off by hand.
- They reply on day threeStop on Response takes them out wherever they are in the sequence, because they answered a message this workflow sent. The conversation is already assigned to their rep. An out-of-office auto-reply counts too, which is fine here: a person looks at every reply anyway.
- They book without replying03 · Inspection Booked removes them from this workflow in its first step, so the follow-ups stop.
- Called first, then filled in the form02 made a New Lead card from the missed call and may still be waiting to send its own follow-up. The first step takes them out of 02, Find Opportunity finds that card and renames it, and Only Apply to Unassigned Contacts keeps the rep 02 assigned.
- Double submitThe first run is still active, and GHL does not enroll a contact twice in the same workflow, so the second submit starts nothing. One text, one email, one deal.
- Asks again next yearRe-entry is on, so the new request gets the full follow-up. Their old card is Abandoned or Lost, so Find Opportunity finds nothing open and Create Opportunity adds a new one, with Duplicate Opportunity on. If they were in the middle of 07, the first step takes them out.
- Someone edits the Facebook formMeta gives a duplicated form a new ID, which silently breaks the trigger filter. The SOP says to re-select the form in the trigger after any change.
- Agree the rules with the owner. What counts as a lead, who calls, how fast, and when it is too late to text. The answers became the score thresholds, the round robin and an 8 AM to 8 PM texting window: federal quiet hours end at 9 PM, but Florida, Oklahoma and Maryland stop at 8, so the strictest window is the safe default.
- Data model before workflow. Custom fields and dropdown options first, spelled exactly as the form shows them, because the scoring code compares strings. Pipeline stages and custom values next, so no message has a hard-coded link or phone number.
- One workflow, two sources. The website form and the Facebook lead form both trigger the same workflow, so there is one place to change the follow-up. The form carries hidden UTM fields and two SMS consent boxes, service and offers, both unticked and optional.
- Clear the way, then find the card. The first step removes the contact from 02 · Missed-Call Text-Back and 07 · Database Reactivation, so a caller or an old lead who fills in the form gets one follow-up, not two. Find Opportunity then looks for the latest open Roofing Sales card. If 02 already made one from a missed call, Update Opportunity gives it the name and service. If not, Create Opportunity makes one at New Lead with Duplicate Opportunity on, because GHL checks duplicates by contact, and with it off a lead whose only card was lost last year would get none. A Go To joins the two paths at the score.
- Score with Custom Code. Three properties go in through inputData, and a score and a call window come out through output. I tested the step with three sample contacts so later steps could map its output, then saved both values to contact fields with Update Contact Field.
- Route, alert, and one task per rep. Assign To User rotates Maya and Luis equally, only for unassigned contacts. The alert is an Internal Notification of type Email to the assigned user, not a text at midnight. Add Task takes one named user, so an If/Else on Assigned User gives Maya a task for her leads and Luis one for his, due now, and a Go To puts Luis's leads back on the shared sequence.
- Compliance branch. An If/Else checks SMS consent (service) and SMS DND. The text path waits for an 8 AM to 8 PM Advance Window and carries the opt-out line in the first text. The other path turns on SMS DND with Enable/Disable DND, so no later workflow texts someone who did not tick the box, and follows up by email and phone.
- Settings that decide behavior. Stop on Response on, so any reply hands the lead to a person. Re-entry on, so a lead who asks again after a finished run is followed up again; GHL does not enroll a contact who is still active, so a double submit does not double-text. 03 removes the contact from this workflow when they book.
- Test, publish, hand off. Six test contacts, one per scenario above, checked against Execution Logs and Enrollment History before publishing. Then a short Loom walkthrough and a one-page SOP for the office.
| Custom field | Type | Notes |
|---|---|---|
Service Neededservice_needed | Dropdown (single) | Leak or repair · Storm damage · Full replacement · Not sure yet |
Roof Ageroof_age | Dropdown (single) | Under 10 years · 10-20 years · Over 20 years · Not sure |
SMS consent (service)sms_consent | Checkbox | The first box: texts about the inspection, estimate and job. Unticked by default, not required to submit. The If/Else reads it |
SMS consent (offers)sms_marketing_consent | Checkbox | The second box: offers and seasonal reminders. Only 07 reads it |
Lead Scorelead_score | Number | Written by the Custom Code step |
Call Prioritycall_priority | Single line | "within 15 minutes", "within 1 hour", or "first thing after 8 AM" for a lead that arrives between 8 PM and 8 AM |
UTM Source / Medium / Campaignutm_source | Single line ×3 | Hidden form fields filled from the URL |
- stl-no-response
- Finished the sequence without replying or booking. One of the two lists 07 starts from
Roofing SalesNew LeadContactedInspection BookedInspectedEstimate SentJob ScheduledJob Complete
Custom values: {{custom_values.booking_link}} {{custom_values.office_phone}}
- Test contact with consent: email, rep alert, task and SMS arrive, and the score matches the code
- Test contact without consent: SMS DND is on, no SMS is sent, the email path runs, and the task shows SMS consent No
- One test lead for each rep: the task goes to the rep who owns the contact, and both reach the same texts
- Submit after 8 PM: the SMS shows as waiting in Execution Logs and sends at 8 AM
- Reply to the first text: the contact leaves the workflow and the conversation is assigned
- Book through the link: the contact is removed by 03 and gets no more follow-ups
- Miss a call from a test phone, then submit the form from it: 02 shows the contact as removed, one card, renamed, same rep
- Submit twice: one opportunity, one set of messages
- Every merge field renders on a real phone and in Gmail and Outlook, and every email ends with the postal address
Lead score (Custom Code step)
// Custom Code step, JavaScript. Properties added in the step:
// service = {{contact.service_needed}}
// roof_age = {{contact.roof_age}}
// source = {{contact.source}}
// hour = {{right_now.hour}} (24-hour; all Harbor & Pine leads are local)
// GHL wraps this in an async function and reads the result from `output`.
const service = (inputData.service || '').toLowerCase();
const age = inputData.roof_age || '';
let score = 20;
if (service.includes('storm')) score += 35;
else if (service.includes('replacement')) score += 30;
else if (service.includes('leak')) score += 25;
if (age === 'Over 20 years') score += 25;
else if (age === '10-20 years') score += 15;
// The owner asked for lead-ad leads to rank a little below form fills.
if ((inputData.source || '').toLowerCase().includes('facebook')) score -= 5;
score = Math.max(0, Math.min(100, score));
// Calls keep the same 8 AM to 8 PM hours as the texts.
const hour = Number(inputData.hour);
const afterHours = hour < 8 || hour >= 20;
output = {
lead_score: score,
call_within: afterHours ? 'first thing after 8 AM' : score >= 70 ? 'within 15 minutes' : 'within 1 hour',
};Properties are added in the step and read as inputData.<key>. The object assigned to output becomes the step output that later steps can map.
SMS consent checkboxes on the form
Box 1 (SMS consent, service):
Text me about my inspection, estimate and job: scheduling, reminders and updates from Harbor & Pine Roofing. Message frequency varies. Msg & data rates may apply. Reply HELP for help, STOP to opt out.
Box 2 (SMS consent, offers):
Also text me occasional offers and seasonal roof reminders. Reply STOP to opt out.
Under both: Consent is optional and not a condition of purchase. Privacy Policy · Terms of ServiceBoth boxes are unticked by default and neither is required to submit. The same wording goes in the A2P campaign registration.
GHL features in this build
Missed-call text-back
Every missed call gets a text within seconds, a new caller becomes a New Lead with an owner, and people we already work with go straight to their own rep.
The problem
Calls come in while the estimators are on roofs and the office is on the other line. People who reach voicemail rarely leave a message. They call the next roofer on the list, and nobody here even knows they called.
What I built
Every missed call on the main line gets a text within seconds, day or night, while the caller still has the phone in their hand. New callers get the booking link, a New Lead card, a rep and a call-back task; people who already have a deal with us get a short "your rep will call you back" text instead. Replies go to a person, and one follow-up goes out only if nobody has touched the card, never outside 8 AM to 8 PM.
GHL's built-in Missed Call Text Back "triggers an SMS notification for every missed call," even when the same caller tries several times in a short time. GHL's advice is to use a workflow instead, for example with a Wait step of about 20 minutes. This is that workflow, built out.
Loading the diagram, simulator and build notes…
Inspection booked
Every booked inspection gets a confirmation and two reminders, and whatever happens on the day moves the pipeline card and tells the right person.
The problem
Homeowners booked an inspection and forgot about it. Estimators drove out to empty driveways, nobody chased the no-shows, and cards sat in Inspection Booked long after the visit.
What I built
One workflow for every visit on the Roof Inspection calendar. A booking gets a confirmation and two reminders naming the estimator, and the card moves by itself. Showed starts the estimate task straight away; No-show and Cancelled each get a rebook text and a person to follow up. It finds the deal before it updates it, and it is built around the GHL rule that a cancellation ends the reminder run.
When an appointment moves from New, Confirmed or Showed to Cancelled, Invalid or No-show, GHL treats it as "Cancelled": "The customer will be pulled out of the workflow, and no further actions will occur."
Loading the diagram, simulator and build notes…
Estimate follow-up
Two weeks of useful follow-up after every estimate. One reply or one tag ends it, and the pipeline shows what actually happened.
The problem
Estimates went out and then nobody followed up. The estimators meant to, but by the next morning they were up on another roof. Homeowners comparing three quotes went with whoever stayed in touch, and the pipeline filled with cards stuck at Estimate Sent.
What I built
Moving the card to Estimate Sent starts two weeks of follow-up in the estimator's name: an offer to walk through the estimate, a financing email, a text that answers the usual questions, a call task, and a polite "should I close your file?". Texts and emails only go out Monday to Saturday, 9 to 6. Any reply hands the conversation to the estimator. One tag from the estimator, signed or declined, ends the sequence and marks the card Won or Lost. If nobody decides in two weeks, the card is marked Abandoned and tagged for a later reactivation campaign.
GHL's Goal Event guide says only one Goal Event action can be added per workflow, but "you may configure multiple criteria inside that one Goal Event". When the goal is met, the contact moves to it "regardless of where they were in the workflow."
Loading the diagram, simulator and build notes…
Won to job hand-off
The moment a deal is marked Won, the crew channel, the job sheet, the production manager and the homeowner all hear about it, and the card moves itself to Job Complete when the crew signs off.
The problem
A sold job reached production by text message, if it reached it at all. Sam heard about sales days late, materials went on order late, homeowners called to ask what happens next, and finished jobs sat in Job Scheduled, so nobody ever asked those customers for a review.
What I built
One workflow starts when a Roofing Sales deal is marked Won, whether an estimator does it in the app or 04 does it when the estimate is signed. It takes the contact out of 04's follow-up, checks that this card has not been handed off before, and moves it to Job Scheduled. It posts the job to the crew channel in Slack, adds a row to the Jobs 2026 sheet, gives Sam a task to order materials and book the install, and sends the homeowner a welcome email and a text from Sam. Then it waits for the crew to tag the job complete, stamps the date and moves the card to Job Complete, which starts 06 · Reviews & Referrals. A job with no sign-off after 45 days goes to Jordan instead of going quiet.
GHL's own Update Opportunity guide uses this trigger as its example, because it "ensures the workflow starts with an opportunity already in context" and so "no extra lookup is required". With a trigger that is not opportunity-based you need Find Opportunity first; with no opportunity in the workflow, the action is skipped.
Loading the diagram, simulator and build notes…
Reviews and referrals
Every finished roof gets the same review request, whatever the customer thinks. A low check-in score adds a call from the owner; it never takes the link away.
The problem
Reviews came in by luck. Nobody asked on purpose, and when someone did, it was an estimator texting the Google link to the customers they got on well with. Harbor & Pine had fewer reviews than roofers half its size, and the owner heard about problems when they showed up in public.
What I built
When a card reaches Job Complete, every customer gets the same review request the next day by text, and one email reminder if they have not clicked. A few days later a short check-in asks how the job went. A score below 4 puts Jordan on the phone within a business day. A 4 or 5 gets a referral email a week later, and so does anyone who has not answered in ten days. The review request never depends on the score: it has gone to everyone before the check-in is even sent.
Since October 21, 2024, the FTC's rule on consumer reviews bans giving anything in exchange for reviews that express a particular sentiment (§465.4). It also bans using threats or intimidation to keep reviews down, and presenting the reviews you show as most or all of the ones you received while negative ones are held back (§465.7). The FTC can seek civil penalties for each violation.
Loading the diagram, simulator and build notes…
Database reactivation
Old leads get one plain question, sent slowly and only where there is consent. Every reply is read and routed: back into the pipeline, a note, an opt-out or a person.
The problem
Years of old leads and undecided estimates sat in the CRM, and nobody had time to call through them. Texting the whole list at once would have risked the phone number, reached people who never agreed to offers, and missed opt-outs written as "please stop texting me" instead of STOP.
What I built
One tag on a cleaned-up Smart List starts it. A start wait lets the first text go out only Monday to Wednesday, so both texts land on weekdays. A Drip then releases 50 contacts every 15 minutes, and the Time Window keeps every send to weekdays, 10 to 6. Contacts who ticked the offers box get two short texts from the estimator they dealt with, and everyone else gets two emails. An AI Decision Maker routes every reply. Interested homeowners go back into the pipeline on a new card, and their estimator is alerted. "Not now" gets a note. An opt-out in plain words gets SMS DND the same minute. Anything unclear goes to a person. In the simulator, keyword rules stand in for the model.
Under the FCC consent-revocation rules in force since April 11, 2025, a consumer can revoke consent to robocalls and robotexts by any reasonable means, and the revocation must be honored within 10 business days. Replies such as "stop", "quit", "end", "revoke", "opt out", "cancel" or "unsubscribe" count as revocation by definition.
Loading the diagram, simulator and build notes…
Crewlo
Crewlo sells scheduling and dispatch software to field-service companies, with a 14-day free trial and a sales team for larger accounts. The growth lead needed demo requests routed to the right rep in seconds, trial emails driven by what people actually do in the product, a signal when a trial is worth a sales call, and a clean hand-off from closed deal to onboarding. The app tells GHL what each user does (over Inbound Webhooks), and GHL calls the app back to extend trials and set up new customer accounts.
- Workflows
- 6
- Steps
- 150
- Sample customers
- 32
- Where
- Remote team, customers in the US and Canada
The sample team
- Hana Ito Growth lead (owns GHL)
- Priya Shah Sales development rep
- Ben Carter Account executive, mid-market
- Aisha Rahman Account executive, enterprise
- Leo Park Customer success manager
Crewlo is a fictional software company. The people, phone numbers, prices, events and links are samples.
One pipeline, one customer journey
Each workflow does one job and hands the customer to the next. The orange text with the lightning bolt on each card is its trigger: the event that starts it. The grey chips are the stages of the sales board (GoHighLevel calls it a pipeline), where each customer’s card moves from left to right. Pick a card to open that workflow below.
New BusinessDemo RequestedDemo BookedTrial Sales-AssistDemo HeldProposalOnboarding
- 01Demo requestForm SubmittedDemo Requested → right rep, booked
- 02Trial onboardingInbound WebhookTrial signup → activated
- 03PQL alertInbound WebhookActive trial → Trial Sales-Assist
- 04Trial endingCustom Date ReminderTrial ending → paid or extended
- 05Closed-won to onboardingOpportunity Status ChangedWon → Onboarding
- 06NPS and healthSurvey SubmittedNPS → saved, heard or referred
The landing page, working
Fill in the form as if you were a customer and press Book my demo. Use any name and a made-up number if you like: nothing is sent or stored. Then press Watch the workflow run, which appears once you submit, to see each email, text and task you would get from workflow 01 · Demo request, and when. It runs at your local time. 01 answers by email, from the rep the routing picks, whatever the hour.
Loading the landing page…
In short: the form asks only what routing needs (team size and role), texting is opt-in, the thank-you page books the demo with the rep the workflow picked, and every lead carries the ad or link that brought them.
How the page is built in GoHighLevel’s funnel builder (6 notes for builders)
- Qualify with the form, not a callTeam size and role are the two questions routing needs, so the form asks exactly those. Company size ranges match the Custom Code thresholds, word for word.
- Work email, optional phoneB2B buyers expect email. The phone is optional and texting is opt-in with its own consent box, so nobody gets a text they did not ask for.
- Round-robin calendar on the thank-you stepThe Product Demo calendar is round robin across the reps, with Always Book with Assigned User on, the form first in the widget and Allow Staff Selection off, so the booking lands with the rep the routing chose. A Conditional Logic v2 rule (Redirect to URL) sends teams of 1 to 10 to a step with the Weekly Live Demo calendar, so one-to-one time goes to bigger teams. Booking straight after the form catches people while they still care.
- Fast, even on a site full of scriptsOptimize JavaScript defers the chat widget and analytics until the page is interactive, and the hero is a compressed screenshot, not a video.
- Source you can trustUTM hidden fields plus GHL’s own First and Latest Attribution. The Custom Webhook to Slack includes the source, so reps know whether they are talking to a Google ad click or a referral.
- One page per audiencePaid campaigns for HVAC, plumbing and cleaning companies each get a split-test variation of the headline and screenshot, measured by opt-in rate in the Stats tab.
Pick a workflow, pick a sample customer, press Run
Each tab below is one workflow. Read The problem and What I built for the short version. Then pick a sample customer and press Run workflow: the log lists every email, text and task in order, with the time it would happen, and the diagram ticks off each step as it runs.
For GoHighLevel builders: the diagram reads as it does in the workflow builder, and the simulator follows the builder’s rules: branches never rejoin, a goal pulls the contact forward, Stop on Response ends the run, DND skips the message and time windows hold it. New to the words? Open the decoder.
Demo request
Every demo request is scored, routed to the right rep and posted to Slack within seconds, and the pipeline card moves by itself when they book.
The problem
Demo requests landed in one shared inbox. Whoever looked first took them, a 400-person company could wait behind a two-van plumber, and the reps heard about new requests from each other instead of from the system.
What I built
The form asks the two questions routing needs. Custom Code scores the fit and picks the segment: enterprise goes to Aisha, mid-market to Ben, small teams and anything that scores low to the weekly live demo with Priya following up. The buyer gets an email from the rep who will run the demo, the rep gets an in-app alert, Slack gets the source and the score, and the rep owns both the contact and the card: a new one in Demo Requested, or the open card a trial already has. A booking moves it to Demo Booked. No booking within a day gives the rep a task and sends one personal follow-up, in business hours.
Loading the diagram, simulator and build notes…
Trial onboarding
Every new trial gets four short emails from the customer success manager, each with one job to do. When the app says the team is up and running, the nudges stop and the next email changes.
The problem
Everyone who started a trial got the same emails on the same days. Owners who had their whole crew on the board by lunchtime were still told to invite their team, and the trials that stalled were only noticed when they expired.
What I built
The app posts trial.started to GHL, which creates or updates the contact, clears the tags left by any earlier trial and starts four emails from Leo, the CSM: log in, invite the techs, connect QuickBooks and Google Calendar, then an offer to set it up together. When the app reports activation, a two-step helper workflow tags the contact, and the Goal Event pulls them out of the nudges and onto a what-next email. Anyone still stuck on day 5 becomes a task for Leo, and contacts GHL cannot email go to him on day 0.
Loading the diagram, simulator and build notes…
PQL alert
Once a day the app reports how each trial is being used. When a trial starts to look like a buyer, the right AE hears about it once, with the numbers, and a trial nobody at Crewlo is talking to yet gets one plain email from them. Trials that are close get one useful tip instead.
The problem
Sales could not tell which trials were being used for real. A 40-person HVAC company running its whole schedule in Crewlo looked the same in the CRM as someone who signed up and never came back, so the AEs either called every trial or waited for trials to call them.
What I built
The app posts one usage snapshot per trial workspace every morning. Custom Code turns people invited, jobs scheduled, integrations and active days into a product score from 0 to 100 and saves it on the contact. At 70 or more the trial goes to sales exactly once: the right AE by segment, a post in #pql with the numbers, and a deal on the New Business board. A trial that already has an open deal keeps that card, which moves to Trial Sales-Assist and to the AE along with the contact, and gets no automated email: someone in sales has already talked to them. A trial without one gets a new card in Trial Sales-Assist and a plain email from the AE. Between 40 and 69, Leo sends one tip aimed at the weakest signal. Below 40 nothing happens, and 02 · Product · Trial Onboarding keeps doing its job.
Loading the diagram, simulator and build notes…
Trial ending
Three days before a trial ends, teams that use Crewlo get the price for their seat count, and teams that have not got going get one 7-day extension with a single click. GHL calls the app to extend the workspace, and Leo calls whoever is left on the last day.
The problem
Trials ended on day 14 whether anyone was ready or not. Teams dispatching from Crewlo every day hit the end of the trial before anyone had talked price with them, and owners who wanted more time emailed support and waited a day or two for someone to extend it by hand.
What I built
Three days before Trial Ends, the workflow looks at one tag. Activated teams get the price for the users they have, a reminder the day before, and a call from Leo on the last day, and paying at any point pulls them out through the Goal Event. Teams that have not activated get an offer of 7 more days: one click on the trigger link and GHL calls Crewlo's API to extend the workspace, moves Trial Ends and confirms by email. No click means a last-chance call from Leo and a trial-expired tag. Every later step counts from Trial Ends itself, not from the hour the trigger happened to fire, and each trial can be extended once.
Loading the diagram, simulator and build notes…
Closed-won to onboarding
When an AE marks a deal Won, the app upgrades the workspace, #wins hears about it and the account moves to Leo with a kickoff invite. No booking in three days means a second email, a call task and, with consent, one text. Expansion deals provision without a second welcome.
The problem
When a deal closed, the AE posted in Slack, forwarded the order form to Leo and asked an engineer to upgrade the workspace. The upgrade could wait a day, customers who had signed still got trial emails and a "your trial is ending" notice, and Leo sometimes heard about a new customer from their first support ticket.
What I built
Marking a New Business deal Won is the trigger, and the AE's only job is to fill in Plan and Seats first. The workflow moves the card to Onboarding, calls Crewlo's API to put the workspace on the plan and seat count that were sold, and posts the win in #wins. A new customer is then tagged, taken out of the trial workflows and off the trial tag, and handed to Leo: an email with the details, a prep task, a welcome from him with the Kickoff Call calendar, and the contact reassigned to him while the deal stays with the AE. A booking gets a tag and a hand-off note. No booking in three days gets a second email and a call task on the next working day, and a text only if the contact agreed to texts. A deal for an existing customer, usually more seats, ends after the upgrade with an email to Leo and the contact back in his name, so nobody is welcomed twice.
Loading the diagram, simulator and build notes…
NPS and health
Every answer to the quarterly NPS survey gets its own response. A detractor puts a call on the customer success manager's list within seconds, a passive gets one question, and a promoter gets the referral link. Nobody is asked for a public review because of their score.
The problem
Crewlo sent an NPS survey every quarter and read the results in a spreadsheet weeks later. By then an unhappy customer had been unhappy for a month, the comments from the 7s and 8s had gone unanswered, and the customers who would gladly have recommended Crewlo were never asked.
What I built
The survey writes the score to the contact, and one If/Else sorts the answer. A 0 to 6 sets Account Health to At risk, emails Leo the comment, gives him a call task due now, posts to #cs-alerts and sends a short note from Leo saying he will call. A 7 or 8 gets one question from Leo, what would make it a 10, and a reply goes straight to him. A 9 or 10 gets the referral link, plus a case-study invite four days later if they have never been asked. Anything unexpected, a missing score included, takes the detractor path, so a person looks at it. Everything internal happens the moment the answer lands; emails to the customer wait for weekday business hours in their time zone.
Loading the diagram, simulator and build notes…
Trailhead Career Coaching
Trailhead helps mid-career professionals change fields. People find it through a free weekly workshop, buy a self-paced course, and the best fits apply for 1:1 coaching. The founder needed the workshop to fill and show up, abandoned checkouts recovered, new students actually started, failed payments chased politely, and applications routed to the enrollment advisor without anyone copying data between tools.
- Workflows
- 6
- Steps
- 185
- Sample customers
- 32
- Where
- Online, US and Canada
The sample team
- Morgan Hale Founder and head coach
- Devon Brooks Enrollment advisor
- Sasha Kim Operations and billing
- Jules Ortega Student success
Trailhead Career Coaching is a fictional business. The people, phone numbers, prices and links are samples.
One pipeline, one customer journey
Each workflow does one job and hands the customer to the next. The orange text with the lightning bolt on each card is its trigger: the event that starts it. The grey chips are the stages of the sales board (GoHighLevel calls it a pipeline), where each customer’s card moves from left to right. Pick a card to open that workflow below.
EnrollmentRegisteredAttendedCheckout StartedCustomerAppliedCall BookedCoaching Client
- 01Workshop registration and remindersForm SubmittedRegistered → attended, or the replay
- 02Checkout recoveryOrder Form SubmissionCheckout Started → Customer
- 03Course onboardingOrder SubmittedCustomer → started the course
- 04Failed payment recoveryPayment ReceivedFailed payment → recovered
- 05Coaching applicationSurvey SubmittedApplied → Call Booked
- 06Completion, testimonial and upgradeProduct CompletedCourse completed → testimonial, upgrade
The landing page, working
Fill in the form as if you were a customer and press Register free. Use any name and a made-up number if you like: nothing is sent or stored. Then press Watch the workflow run, which appears once you submit, to see each email, text and task you would get from workflow 01 · Workshop registration and reminders, and when. It runs at your local time, and every reminder counts back from the next Thursday at 7 PM, so the log jumps to that evening.
Loading the landing page…
In short: no income promises, a short form with an optional phone and opt-in texts, a confirmation page with add-to-calendar buttons, an order form that makes abandoned-checkout follow-up possible, and ad tracking that counts sales.
How the page is built in GoHighLevel’s funnel builder (6 notes for builders)
- One promise, no income claimsThe headline promises a plan, not a salary. The FTC treats earnings claims as claims that need proof, so the page and every follow-up avoid them.
- Two questions that earn their placeCurrent role and goal go on the contact record, so Devon sees them in every alert about this person, and the role feeds the readiness score if they apply for coaching later.
- Phone optional, texts opt-inEmail is required, the phone is not. The text box is unticked and optional and says what the texts cover, and ticking it without a number asks for one.
- A confirmation page that worksThe workshop time in the visitor’s time zone, add-to-calendar buttons and a request to reply to the welcome email, which helps the next emails reach the inbox.
- Order form on the offer stepThe page after the workshop uses a Two-Step Order form with an order bump. Order Form Submission fires on submit and Order Submitted only on payment, which is what makes cart recovery possible.
- Tracking that counts sales, not clicksThe Meta Pixel and Conversions API send registrations and purchases from both browser and server with deduplication, so ad reporting survives browsers that block pixels.
Pick a workflow, pick a sample customer, press Run
Each tab below is one workflow. Read The problem and What I built for the short version. Then pick a sample customer and press Run workflow: the log lists every email, text and task in order, with the time it would happen, and the diagram ticks off each step as it runs.
For GoHighLevel builders: the diagram reads as it does in the workflow builder, and the simulator follows the builder’s rules: branches never rejoin, a goal pulls the contact forward, Stop on Response ends the run, DND skips the message and time windows hold it. New to the words? Open the decoder.
Workshop registration and reminders
Every registrant gets a confirmation and reminders pinned to Thursday at 7 PM, and after the session the workflow sends the offer to people who joined and the replay to people who did not.
The problem
Workshop reminders went out by hand from Morgan’s inbox, when there was time. Show-up was thin, people who missed the session heard nothing until the next promo, and people who had sat through the whole hour got the same "sorry we missed you" email as everyone else.
What I built
One run per registration. Event Start Date pins every reminder to the Thursday session, and texts go only to people who ticked the reminders box. From the 1-hour text until 8:15 PM, one signal, a click on the Join trigger link, decides what comes next: the offer with the price and refund policy, or the replay for 48 hours with one text nudge. Replay viewers get the same offer, current students get their login instead, and anyone who never watches is invited to next week.
Loading the diagram, simulator and build notes…
Checkout recovery
Step 1 of the checkout starts it, paid or not. Buyers never hear from it. Everyone else gets two plain emails, one text only if they agreed to marketing texts, and a clean exit the moment they pay.
The problem
After each Thursday workshop, some people typed their name and email into the checkout and stopped at the card step. We had their details and did nothing with them. Some only had a question, usually about refunds or the payment plan, and nobody answered it.
What I built
Submitting step 1 of the two-step order form starts the workflow, whether or not payment follows. It moves their course card to Checkout Started, then waits an hour, so someone who is just typing in their card number never gets a nudge. After that: an FAQ email with the refund policy and the payment plan, a text only for people who ticked the offers box, and a last email with no countdown. A Payment Received goal pulls a buyer out at any point and marks the card Customer, Won, the same change 03 · Students · Course Onboarding makes on the purchase. Anyone who never pays ends tagged cart-abandoned.
GHL separates its two order triggers by payment: Order Submitted is “tied to an actual purchase or completed transaction”, while Order Form Submission “doesn’t care if there was payment or not.” Only the second one can see a checkout that never got paid.
Loading the diagram, simulator and build notes…
Course onboarding
Paying grants access, marks the sale Won and tells the team in Slack within the minute. Then the workflow watches for the first lesson, and brings in a person only for students who do not start or cannot be emailed.
The problem
People bought the course and then never opened it. Nobody noticed until the refund requests came in. The login email was the only thing a new student got, the team heard about sales from Square’s emails, and Jules had no list of who needed help getting started.
What I built
The purchase itself starts onboarding. In the same minute the workflow stops the workshop and cart messages, grants the course, hands the student to Jules, marks the course card Won and posts to #new-students. A student with Email DND gets a call from Jules instead of a welcome that GHL would skip. Then the workflow waits up to three days for the course to start. Students who start get a plan for week one and a check on the first real exercise. Students who do not get one text if they agreed to course texts, one email that asks for 12 minutes, and a personal video from Jules. A week in, anyone still not started gets a plain note that includes the refund option.
HighLevel’s article on the action says granting the same offer again “won’t duplicate the enrollment or reset their progress”, and that login details are not sent automatically: “you’ll need to add an email step in the workflow after the Course Grant Offer action.”
Loading the diagram, simulator and build notes…
Failed payment recovery
A failed installment gets a plain notice, two reminders and a personal check-in from Sasha. Access pauses only on day 10, on a date named in advance, and comes back on its own the moment they pay.
The problem
Students on the three-payment plan sometimes had an installment fail, usually an expired or replaced card. Nobody noticed until Sasha reconciled payments at month end, weeks later. The student had never been told, and the email that finally went out read like a collections letter to someone who had done nothing wrong.
What I built
A failed installment starts the workflow the moment the charge fails. The student gets a plain billing notice by email, and by text if they ticked the service box, with one link to fix it. Reminders follow on day 2 and day 5, and on day 5 Sasha gets a task to reach out as a person. If the installment is still open on day 10, course access pauses on the date the day-5 email named, with an email that says how to restore it. A student whose email is switched off never got that date, so for them a person decides instead. A successful payment at any point ends the recovery, and access comes back automatically if it was paused, even weeks later.
GHL’s help article on Payment Received answers “Can this trigger failed payments too?” with: “Use the ‘Payment Status = Failed’ filter to create follow-up workflows for retries or dunning emails.” For recurring charges it recommends the “Customer not present/subscription transaction” filter, because the Subscription trigger reacts to lifecycle events, not to individual charges.
Loading the diagram, simulator and build notes…
Coaching application
Every application is scored the moment it arrives. Ready applicants get Devon and a booking link within the minute, and everyone else gets a straight recommendation instead of a sales call.
The problem
Coaching applications landed in Morgan’s inbox and waited for her to forward them to Devon. Good applicants sometimes heard nothing for three days. People who were clearly not ready still got a sales call, which wasted their evening and Devon’s, and nobody could say who had booked a call and who had gone quiet.
What I built
The survey handles the one hard no itself, with a Disqualify Lead rule, and the trigger’s Disqualified filter keeps those submissions out. Everything else is scored 0 to 100 by a Custom Code step from four answers. At 70 or more a coaching card opens at Applied (the course card is left alone), the contact leaves checkout recovery if they were in it, Devon becomes the owner and gets the answers by email, and the applicant gets the booking link by email, and by text if they agreed to texts about offers. A booked Strategy Call moves the coaching card to Call Booked. No booking in two days gives Devon a task and sends a personal follow-up. Under 70, the applicant gets a kind email that recommends the course first, or tells a current student to keep going, and says how to apply again.
HighLevel’s article on the trigger lists two filters, Survey is and Disqualified (“is true or is false”), and answers “Can I use logic based on survey answers?” with: “While this trigger doesn’t directly evaluate answers, you can use custom fields or tags applied via survey to build logic.”
Loading the diagram, simulator and build notes…
Completion, testimonial and upgrade
A graduate gets congratulations the minute they finish, a request for their story two days later, and one invitation to coaching, and Devon hears about it the moment they click Apply.
The problem
Students who finished the course heard nothing. Nobody asked them how it went, so the sales page ran on three quotes from people Morgan already knew. The coaching offer went to workshop attendees but never to the people best placed to use it, students who had just done all the work, and when a graduate did click through to the application, Devon only found out if they submitted it.
What I built
Finishing the course starts one workflow. In the same minute it records the completion, clears Jules’s stalled tags and sends Morgan’s congratulations. Two days later, on a weekday, every graduate gets the same request for their story: no reward, a private box for what fell short, and nothing published without permission. Five days after that, graduates who are not already with Devon, not behind on a payment and still reachable by email get one invitation to apply for 1:1 coaching, including students 05 once told to finish the course first. A click on Apply emails Devon with the context; no click in four days makes them alumni. Anyone on Email DND is left alone, and Jules is told why.
HighLevel’s article on course auto-progression says its settings “are enabled by default”, that with them “Text lessons are marked complete when learners navigate forward to the next lesson”, and: “If your course uses certificates or completion-based workflow triggers, review the full learner flow to confirm completion happens as expected.”
Loading the diagram, simulator and build notes…
Compliance is part of the build, not a checkbox
A workflow that texts the wrong person at the wrong time costs more than it earns. These rules are built into the workflows in every case study. In plain words: no texts to anyone who didn’t agree to them, no sales texts at night, anyone who asks to stop is stopped, every customer gets the same review request, and emails are set up to reach the inbox.
A2P-ready opt-in
Every landing page has separate consent boxes for service texts and for offers, unticked and optional, and the roofing booking calendar carries the service box too. No consent on file means SMS DND, set by a workflow rather than left to memory. The same wording goes into the A2P 10DLC campaign registration, along with the missed-call text-back, where the caller starts the conversation. Every first text names the business and says how to opt out.
See Harbor & Pine Roofing 01 · Speed to lead, Harbor & Pine Roofing 02 · Missed-call text-back, Harbor & Pine Roofing 03 · Inspection booked, Crewlo 01 · Demo request, Trailhead Career Coaching 01 · Workshop registration and reminders
Quiet hours in the contact’s time zone
Federal rules stop solicitation texts at 9 PM, but Florida, Oklahoma and Maryland stop at 8. Follow-up and marketing texts wait for an 8 AM to 8 PM window in the contact’s time zone.
See Harbor & Pine Roofing 01 · Speed to lead, Harbor & Pine Roofing 02 · Missed-call text-back, Harbor & Pine Roofing 07 · Database reactivation, Trailhead Career Coaching 02 · Checkout recovery
Opt-outs by any reasonable means
STOP and the other standard keywords switch on SMS DND automatically. “Please stop texting me” does not, and since April 11, 2025 the FCC requires honoring it too, within 10 business days. The reactivation workflow catches it and switches DND on; where a person reads every reply, as with missed calls, the alert tells them to do it the same day.
See Harbor & Pine Roofing 02 · Missed-call text-back, Harbor & Pine Roofing 07 · Database reactivation
No review gating
Everyone gets the same public review link, whatever they think. Google prohibits selectively asking happy customers, and the FTC rule on reviews and testimonials (16 CFR Part 465) bans review suppression and incentives tied to sentiment.
See Harbor & Pine Roofing 06 · Reviews and referrals, Crewlo 06 · NPS and health, Trailhead Career Coaching 06 · Completion, testimonial and upgrade
Claims a coach can back up
No income promises on the page or in the follow-ups, testimonials that are real and not presented as typical results, and any incentive disclosed. The FTC treats all three as advertising.
See Trailhead Career Coaching 01 · Workshop registration and reminders, Trailhead Career Coaching 06 · Completion, testimonial and upgrade
Secrets stay out of messages
API keys live in webhook headers and stay out of custom values that templates can print. Payloads carry ids, not passwords, and every call back to the app is logged in Execution Logs.
See Crewlo 04 · Trial ending, Crewlo 05 · Closed-won to onboarding
Email that lands
A dedicated sending subdomain with SPF, DKIM and DMARC, one-click unsubscribe on marketing email as Google and Yahoo require of bulk senders, and a postal address in the footer for CAN-SPAM.
Texts that stay cheap
One curly apostrophe or dash turns an SMS from GSM-7 into UCS-2 and cuts each segment from 160 characters to 70. Every text on this page is checked automatically for both.
What I check first when I inherit an account
Most broken GHL setups fail in the same few ways. This is the order I look in, and what I do about each.
- LoopsA workflow triggered by a tag that adds the same tag, or two workflows that trigger each other. Fix with trigger filters, re-entry off and an explicit Remove from Workflow.
- Double textsGHL will not add a contact who is already active in a workflow, so the duplicates come later: re-entry on and a second form submit next week, or a trigger that fires more than once, like Call Details with no status filter, which fires for each call. Fix with trigger filters, a tag or field check at the top, or re-entry off where one pass is enough.
- Stop on Response surprisesIt ends the run on any response to the workflow’s messages, out-of-office auto-replies included. Keep it where any reply should reach a person; use a reply wait with timeout branches where the answer matters.
- The wrong clockWorkflows set to the account time zone while contacts span several, and imported contacts with no time zone at all. Quiet hours only work in the recipient’s time.
- Duplicate opportunitiesTwo cards per lead because duplicates are allowed. Fix the setting, then merge the pipeline so reporting can be trusted again.
- Hard-coded links and numbersA booking link typed into forty messages. Move it into a custom value so the next change is one edit.
- Silent trigger breaksA Facebook lead form duplicated in Meta gets a new form ID and the trigger filter stops matching. So does a renamed form, calendar or product. Trigger Statistics shows it; I check it after any change.
- Premium steps doing standard workCustom Code, Custom Webhook and Inbound Webhook are billed per execution. Worth it where they earn it, not for a job a standard action does.
From a brief to a workflow the team trusts
Scope
Who the lead is, what counts as success, who acts on what, and what must never happen. Written down before anything is built.
Data model
Custom fields, dropdown values, tags, pipeline stages and custom values first, named so the next person can guess them.
Build in draft
One workflow per job, named NN · Folder · Name, with the settings chosen on purpose rather than left at the defaults.
Test with test contacts
A test contact for every path, checked against Execution Logs and Enrollment History. Real phones and real inboxes for the copy.
Publish and hand off
Published in a quiet hour, then a short screen-recorded walkthrough (Loom) and a one-page how-to for the team (SOP): what it does, what to change, what never to touch.
Watch it
Trigger Statistics and Execution Logs checked in the first week, then monthly. Errors fixed before anyone notices them.
Naming, so the next person can find things
- Workflows
01 · Lead Intake · Speed to Leadin a Lead Intake folder- Tags
stl-no-response,pql-alerted: lowercase, prefixed by the workflow that sets them- Custom fields
lead_score,utm_source: snake_case keys, spelled exactly like the form- Custom values
{{custom_values.booking_link}}: every link and phone number lives in one place
Hiring for GoHighLevel, or need it built?
I build, fix and document GoHighLevel accounts: workflows, sales pipelines, landing pages, and the texting and email rules around them. If you’re hiring for a GoHighLevel role or need this for your business, I’d like to hear about it.