One connected system for the Stormline demo account: 15 workflows that carry a homeowner from their first inquiry to a signed job, a finished roof, and a standing referral - plus the two standalone responders (Review Engine and Missed Call Text-Back) and the pipelines, tags, triggers, custom values, and email templates that hold it together. Foundation first, so a build team can execute it in order.
As Stormline grows past a handful of workflows, naming discipline is the difference between a clean library and a maze nobody can navigate.
PATTERN WF[N] - [NNN] [Stage Name] WF1 - 001 New Lead WF4 - 004 Estimate Sent NSR - No-Show Recovery D3 - Delivery 003 Project Complete
PATTERN P[Phase]_[WF#]_[Purpose] P1_003_ThankYou (email) P1_005_SMS_Urgency (sms) P1_004_Notify_RepTakeOver (internal)
PATTERN snake_case tags: new_lead, no_show_lost, sales_to_delivery fields: follow_up_count (number)
Roofing is sold by inspection and estimate, not online checkout. Nothing fires off ORDER_SUBMITTED here - entry is a form opt-in and a booked consultation.
Sites & Funnels (lead form) + Calendars (Roofing Consultation)
| Entry Point | Type | Fires | Into Stage |
|---|---|---|---|
| Stormline Lead Form | Form | Form Submitted | New Lead |
| Roofing Consultation | Calendar | Appointment confirmed | Inspection Booked |
| Roofing Consultation | Calendar | Appointment no-show | (stays Inspection Booked, NSR runs) |
Sales tracking and crew/fulfillment tracking serve different teams. Splitting them keeps each board readable and reporting clean.
WF6 (Project Won) moves the opportunity out of Sales and into the Delivery pipeline at Project Scheduled - that's where D1 picks it up.
flowchart TD
A0(["New Lead"]):::trigger
A1["Inspection Booked"]:::action
A2["Inspection Complete"]:::action
A3["Estimate Sent"]:::action
A4{"Decision Pending"}:::decision
A5(["Project Won"]):::grant
A6(["Project Lost"]):::end_
A0 --> A1 --> A2 --> A3 --> A4
A4 -->|Signs| A5
A4 -->|Declines| A6
A5 -.->|Handoff to Delivery| B0
B0(["Project Scheduled"]):::trigger
B1["In Progress"]:::action
B2["Project Complete"]:::action
B3["Review Requested"]:::action
B4["Warranty Follow Up"]:::action
B5(["Client Retained"]):::grant
B0 --> B1 --> B2 --> B3 --> B4 --> B5
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Identity tags persist across cycles (new_lead, returning_lead, won). Transactional flags are stripped at the top of WF1 so a returning lead doesn't trigger the wrong branch.
| Tag | Set By | Purpose |
|---|---|---|
new_lead / returning_lead | WF1 | Identity - kept across cycles |
inspection_booked | WF2 | Consultation confirmed |
no_show / no_show_lost | NSR | Missed appt / lost after no rebook |
inspection_complete | WF3 | Inspection done, awaiting estimate |
estimate_sent | WF4 | Quote delivered |
decision_pending | WF5 | Quote out, awaiting answer |
won + sales_to_delivery | WF6 | Signed - handing to crew |
lost / re_engagement_journey | WF7 | Lost / in long-term win-back |
in_progress / project_complete | D2 / D3 | Delivery stage flags |
build_scheduled | Helper | Build booked (set outside WF6 to dodge instant-goal) |
review_sent / review_clicked | Helper / D4 | Review submitted / link clicked |
project_concern | Helper (inbound reply) | Homeowner flagged a problem - stop auto-advance |
client_retained | D5 | Long-term retained customer |
flowchart LR
F["Form Submitted"]:::trigger -->|capture| W1["WF1 New Lead"]:::action
C1["Appt confirmed"]:::trigger -->|book| W2["WF2 Inspection Booked"]:::action
C2["Appt no-show"]:::trigger -->|recover| NS["NSR No-Show"]:::action
S1["Stage: Inspection Complete"]:::trigger --> W3["WF3"]:::action
S2["Stage: Estimate Sent"]:::trigger --> W4["WF4"]:::action
S3["Stage: Decision Pending"]:::trigger --> W5["WF5"]:::action
S4["Stage: Project Won"]:::trigger --> W6["WF6 + Delivery handoff"]:::grant
S5["Status: Lost"]:::trigger --> W7["WF7 Win-Back"]:::action
S6["Stage: Project Scheduled"]:::trigger --> D["D1..D5 Delivery"]:::action
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
Captures new vs returning leads, sends a welcome + booking link, runs email/SMS nudges, and marks Lost if they never book.
flowchart TD
T(["Form Submitted: Stormline Lead Form"]):::trigger
R["Remove stale transactional tags"]:::action
F{"Find Opportunity"}:::decision
UF["Found: Update opp -> New Lead, Open"]:::action
TF["Tag: returning_lead"]:::action
CN["Not Found: Create opp -> New Lead"]:::action
TN["Tag: new_lead"]:::action
E1["Email: Welcome + Booking link"]:::action
S1["SMS 1: Speed-to-lead"]:::action
N["Notify team: New Lead Alert"]:::action
W1["Wait 1 day"]:::wait
E2["Email 2: Nudge"]:::action
S2["SMS 2: Nudge"]:::action
W2["Wait 2 days"]:::wait
E3["Email 3: Last Call"]:::action
EB["Email: Lost Breakup"]:::action
UL["Update opp -> Project Lost, Lost"]:::action
G{"Goal: appt confirmed?"}:::decision
Z(["End"]):::end_
T --> R --> F
F -->|Found| UF --> TF --> E1
F -->|Not Found| CN --> TN --> E1
E1 --> S1 --> N --> W1 --> E2 --> S2 --> W2 --> E3 --> EB --> UL --> G
G -->|Books -> WF2| Z
G -->|Never books| Z
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Confirms the inspection immediately, sends anchored day-before and hour-before reminders, and alerts the team to schedule the inspector.
flowchart TD
T(["Appt confirmed: Roofing Consultation"]):::trigger
F{"Find Opportunity"}:::decision
UF["Found: Update opp -> Inspection Booked, Open"]:::action
TG["Tag: inspection_booked"]:::action
EC["Email: WF2_Confirmation"]:::action
N["Notify team: inspection booked"]:::action
WA["Wait until 1 day before appt"]:::wait
ED["Email: WF2_DayBefore"]:::action
SD["SMS: WF2_SMS_DayBefore"]:::action
WH["Wait until 1 hour before appt"]:::wait
EH["Email: WF2_HeadsUp"]:::action
SH["SMS: WF2_SMS_HeadsUp"]:::action
G{"Goal: cancelled / no-show?"}:::decision
CN["Not Found: Create opp -> Inspection Booked"]:::action
Z(["End (helper marks Complete on show)"]):::end_
T --> F
F -->|Found| UF --> TG --> EC
F -->|Not Found| CN --> TG
EC --> N --> WA --> ED --> SD --> WH --> EH --> SH --> G
G -->|Cancel/No-show -> NSR| Z
G -->|Shows| Z
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
When an inspection is marked no-show, it chases a rebook over several days, then marks Lost only if they never return. Without it, no-shows dead-end at Inspection Booked forever.
flowchart TD
T(["Appt no-show: Roofing Consultation"]):::trigger
FO["Find Opportunity (Latest)"]:::action
U["Update opp -> Status Open (keep Inspection Booked)"]:::action
TG["Tag: no_show"]:::action
E1["Email: NSR_Rebook1 (immediate)"]:::action
S1["SMS: NSR_SMS_Rebook"]:::action
N["Notify team: they ghosted"]:::action
W1["Wait 2 days"]:::wait
E2["Email: NSR_Rebook2"]:::action
W2["Wait 3 days"]:::wait
UL["Update opp -> Project Lost, Lost"]:::action
TL["Tag: no_show_lost"]:::action
G{"Goal: appt confirmed (rebook)?"}:::decision
Z(["End"]):::end_
T --> FO --> U --> TG --> E1 --> S1 --> N --> W1 --> E2 --> W2 --> UL --> TL --> G
G -->|Rebooks -> WF2| Z
G -->|Vanishes| Z
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
After the inspection: same-day thank-you, an estimate-timing email/SMS, then a team notification to actually build the quote - then it advances the stage to fire WF4.
flowchart TD
T(["Stage = Inspection Complete"]):::trigger
FO["Find Opportunity"]:::action
U["Update opp -> Inspection Complete"]:::action
TG["Tag: inspection_complete"]:::action
E1["Email: P1_003_ThankYou (same-day)"]:::action
W1["Wait 4 hours"]:::wait
E2["Email: P1_003_EstimateTimeline"]:::action
S1["SMS: P1_003_SMS_Timeline"]:::action
W2["Wait 1 day"]:::wait
N["Notify team: estimate due"]:::action
ES(["Update opp -> Estimate Sent -> WF4"]):::end_
T --> FO --> U --> TG --> E1 --> W1 --> E2 --> S1 --> W2 --> N --> ES
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Sends the estimate, then loops one follow-up template up to 3 times (follow_up_count +1 each pass), and advances to Decision Pending so nothing dead-ends.
flowchart TD
T(["Stage = Estimate Sent"]):::trigger
FO["Find Opportunity"]:::action
U["Update opp -> Estimate Sent, Open"]:::action
TG["Tag: estimate_sent"]:::action
RC["Reset follow_up_count = 0"]:::action
E1["Email: P1_004_Estimate"]:::action
N1["Notify team: estimate out"]:::action
WL["Wait 2 days (loop top)"]:::wait
EF["Email: P1_004_FollowUp"]:::action
SF["SMS: P1_004_SMS_FollowUp"]:::action
INC["follow_up_count + 1"]:::action
D{"3+ nudges sent?"}:::decision
NR["Notify team: rep take over"]:::action
DP(["Update opp -> Decision Pending -> WF5"]):::end_
T --> FO --> U --> TG --> RC --> E1 --> N1 --> WL --> EF --> SF --> INC --> D
D -->|No| WL
D -->|Yes| NR --> DP
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Chases a decision with an email/SMS nudge looped up to twice via the counter, then alerts the rep. The rep moving the opp to Won/Lost is what fires WF6 or WF7.
flowchart TD
T(["Stage = Decision Pending"]):::trigger
F{"Find Opportunity"}:::decision
U["Found: Update opp -> Decision Pending, Open"]:::action
TG["Tag: decision_pending"]:::action
RC["Reset follow_up_count = 0"]:::action
E1["Email: P1_005_CheckIn"]:::action
N1["Notify team: pending"]:::action
WL["Wait 3 days (loop top)"]:::wait
EU["Email: P1_005_Urgency"]:::action
SU["SMS: P1_005_SMS_Urgency"]:::action
INC["follow_up_count + 1"]:::action
D{"2+ nudges sent?"}:::decision
NR["Notify team: rep decides"]:::action
CN["Not Found: Create opp -> Decision Pending"]:::action
Z(["End - rep moves Won/Lost -> WF6/WF7"]):::end_
T --> F
F -->|Found| U --> TG --> RC --> E1 --> N1 --> WL --> EU --> SU --> INC --> D
F -->|Not Found| CN --> TG
D -->|No| WL
D -->|Yes| NR --> Z
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Welcomes the signed homeowner, alerts the crew, drives scheduling, then hands the deal to the Delivery pipeline at Project Scheduled (where D1 picks up).
flowchart TD
T(["Stage = Project Won"]):::trigger
F{"Find Opportunity"}:::decision
U["Found: Update opp -> Won"]:::action
RT["Remove stale Sales tags"]:::action
TG["Tag: won + sales_to_delivery"]:::action
E1["Email: P1_006_Welcome"]:::action
W1["Wait 1 hour"]:::wait
N["Notify crew: schedule + materials"]:::action
E2["Email: P1_006_Scheduling (booking link)"]:::action
S2["SMS: P1_006_SMS_Schedule"]:::action
W2["Wait 2 days"]:::wait
D{"Has build_scheduled tag?"}:::decision
SR["SMS: P1_006_SMS_ScheduleReminder"]:::action
CN["Not Found: Create opp -> Won"]:::action
H(["Handoff: Delivery pipeline, Project Scheduled -> D1"]):::grant
T --> F
F -->|Found| U --> RT --> TG --> E1 --> W1 --> N --> E2 --> S2 --> W2 --> D
F -->|Not Found| CN --> TG
D -->|Scheduled| H
D -->|Not yet| SR --> H
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Sends a gracious goodbye, waits a month, then a storm-season nudge, and tags them into a long-term campaign - with a Goal that re-welcomes anyone who rebooks.
flowchart TD
T(["Status = Lost / Project Lost"]):::trigger
F{"Find Opportunity"}:::decision
U["Found: Update opp -> Lost"]:::action
TG["Tag: lost"]:::action
E1["Email: P1_007_ReEngage (goodbye)"]:::action
N1["Notify team: log why lost"]:::action
W1["Wait 30 days"]:::wait
E2["Email: P1_007_SeasonalCheckIn"]:::action
S2["SMS: P1_007_SMS_StormSeason"]:::action
TR["Tag: re_engagement_journey"]:::action
G{"Goal: appt confirmed (rebook)?"}:::decision
TB["Tag: reengaged_rebooked"]:::action
NB["Notify team: won back"]:::action
CN["Not Found: Create opp -> Lost"]:::action
WB(["Won back -> WF2"]):::grant
Z(["End"]):::end_
T --> F
F -->|Found| U --> TG --> E1 --> N1 --> W1 --> E2 --> S2 --> TR --> G
F -->|Not Found| CN --> TG
G -->|Rebooks| TB --> NB --> WB
G -->|Never returns| Z
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Onboards a signed customer into the build phase with welcome, prep, and timeline messages, plus a start reminder anchored to the build date.
flowchart TD
T(["Delivery: Project Scheduled"]):::trigger
F{"Find Opportunity"}:::decision
U["Found: Update opp -> Project Scheduled, Open"]:::action
TG["Tag: sales_to_delivery"]:::action
E1["Email: P2_001_Welcome"]:::action
N["Notify crew: onto calendar"]:::action
W1["Wait 1 day"]:::wait
E2["Email: P2_001_Preparation"]:::action
S1["SMS: P2_001_SMS_Prep"]:::action
W2["Wait 1 day"]:::wait
E3["Email: P2_001_Timeline"]:::action
W3["Wait until 1 day before start"]:::wait
S2["SMS: P2_001_SMS_StartReminder"]:::action
CN["Not Found: Create opp -> Project Scheduled"]:::action
Z(["End - helper advances to In Progress"]):::end_
T --> F
F -->|Found| U --> TG --> E1 --> N --> W1 --> E2 --> S1 --> W2 --> E3 --> W3 --> S2 --> Z
F -->|Not Found| CN --> TG
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Reassures the customer during the build, preps them for wrap-up, then advances to Project Complete - but stops and calls a human if a concern was raised.
flowchart TD
T(["Delivery: In Progress"]):::trigger
F{"Find Opportunity"}:::decision
U["Found: Update opp -> In Progress, Open"]:::action
TG["Tag: in_progress"]:::action
E1["Email: P2_002_ProgressUpdate"]:::action
S1["SMS: P2_002_SMS_Started"]:::action
N["Notify crew: dispatch"]:::action
E2["Email: P2_002_CompletionPrep"]:::action
W1["Wait 3 days"]:::wait
D{"project_concern raised?"}:::decision
NC["Notify team: concern - human steps in"]:::action
ZC(["End - hold for human"]):::end_
E3["Email: P2_002_StatusUpdate"]:::action
S2["SMS: P2_002_SMS_Wrapup"]:::action
PC(["Update opp -> Project Complete -> D3"]):::end_
CN["Not Found: Create opp -> In Progress"]:::action
T --> F
F -->|Found| U --> TG --> E1 --> S1 --> N --> E2 --> W1 --> D
F -->|Not Found| CN --> TG
D -->|Concern| NC --> ZC
D -->|All good| E3 --> S2 --> PC
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Sends the completion + warranty email, waits a day, asks for a review, and nudges once more if they don't review - then advances to Review Requested.
flowchart TD
T(["Delivery: Project Complete"]):::trigger
F{"Find Opportunity"}:::decision
U["Found: Update opp -> Project Complete, Open"]:::action
TG["Tag: project_complete"]:::action
E1["Email: P2_003_Completion (warranty)"]:::action
N["Notify team: complete"]:::action
W1["Wait 1 day"]:::wait
E2["Email: P2_003_Review_Request"]:::action
S1["SMS: P2_003_SMS_Review"]:::action
W2["Wait 2 days"]:::wait
D{"review_sent?"}:::decision
E3["Email: P2_003_Email_Reminder"]:::action
S2["SMS: P2_003_SMS_Reminder"]:::action
RR(["Update opp -> Review Requested -> D4"]):::end_
Z(["End - they reviewed"]):::end_
CN["Not Found: Create opp -> Project Complete"]:::action
T --> F
F -->|Found| U --> TG --> E1 --> N --> W1 --> E2 --> S1 --> W2 --> D
F -->|Not Found| CN --> TG
D -->|Reviewed| Z
D -->|No review| E3 --> S2 --> RR
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Thanks the happy customer (no ask), alerts the team to reply publicly, then asks for a referral at peak goodwill before moving them to Warranty Follow Up.
flowchart TD
T(["Review link clicked"]):::trigger
F{"Find Opportunity"}:::decision
U["Found: Update opp -> Review Requested, Open"]:::action
TG["Tag: review_clicked"]:::action
E1["Email: P2_004_ThankYou (no ask)"]:::action
N["Notify team: reply publicly"]:::action
W1["Wait 2 days"]:::wait
D{"Already referred?"}:::decision
E2["Email: P2_004_Referral"]:::action
S1["SMS: P2_004_SMS_Referral"]:::action
TR["Tag: referral_requested"]:::action
WF(["Update opp -> Warranty Follow Up -> D5"]):::end_
CN["Not Found: Create opp -> Review Requested"]:::action
T --> F
F -->|Found| U --> TG --> E1 --> N --> W1 --> D
F -->|Not Found| CN --> TG
D -->|Yes| WF
D -->|Not yet| E2 --> S1 --> TR --> WF
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Hands over the warranty, teaches seasonal roof care, keeps a referral incentive in front of them, then advances to Client Retained - the completion signal.
flowchart TD
T(["Delivery: Warranty Follow Up"]):::trigger
F{"Find Opportunity"}:::decision
U["Found: Update opp -> Warranty Follow Up, Open"]:::action
TG["Tag: warranty_followup"]:::action
E1["Email: P2_005_Warranty"]:::action
N["Notify team: retention"]:::action
W1["Wait 4 days"]:::wait
E2["Email: P2_005_MaintenanceTips"]:::action
W2["Wait 7 days"]:::wait
E3["Email: P2_005_ReferralOffer"]:::action
S1["SMS: P2_005_SMS_Referral"]:::action
W3["Wait 3 days"]:::wait
CR(["Update opp -> Client Retained + tag"]):::grant
CN["Not Found: Create opp -> Warranty Follow Up"]:::action
T --> F
F -->|Found| U --> TG --> E1 --> N --> W1 --> E2 --> W2 --> E3 --> S1 --> W3 --> CR
F -->|Not Found| CN --> TG
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
Fires when the job is marked done (tag review_requested), sends the review ask by SMS and email, waits 2 days, then sends one reminder only if they have not reviewed yet - and a tiny helper stops the nudge the moment a review lands.
flowchart TD
T(["Tag added: review_requested"]):::trigger
S1["SMS: Review ask + Google link"]:::action
E1["Email: Review ask (backup)"]:::action
W1["Wait 2 days"]:::wait
G{"Has tag review_sent?"}:::decision
Z1(["Yes: already reviewed -> End"]):::end_
S2["No: one reminder SMS"]:::action
Z2(["End"]):::end_
H(["Helper: New Review / link clicked -> tag review_sent + thank"]):::grant
T --> S1 --> E1 --> W1 --> G
G -->|Yes| Z1
G -->|No| S2 --> Z2
H -.stops the nudge.-> G
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
When an inbound call is missed, it tags the caller, texts them back within seconds, alerts the team to call back, waits an hour, then sends one follow-up only if they stayed silent - and can optionally park them as a real lead.
flowchart TD
T(["Call Status Missed: No Answer/Voicemail + Inbound"]):::trigger
TG["Tag: missed_call"]:::action
S1["SMS: Instant text-back (seconds)"]:::action
N["Notify team: call them back"]:::action
W1["Wait 1 hour"]:::wait
S2["SMS: One follow-up (Stop on Response ON)"]:::action
O["Optional: Create opp -> parks at New Lead"]:::action
Z(["End"]):::end_
T --> TG --> S1 --> N --> W1 --> S2 --> O --> Z
classDef trigger fill:#14213D,stroke:#14213D,color:#ffffff,font-weight:bold
classDef action fill:#ffffff,stroke:#CBD5E1,color:#14213D
classDef wait fill:#EEF2F8,stroke:#9DB2CC,color:#475569
classDef decision fill:#FEF3C7,stroke:#F59E0B,color:#78350F
classDef grant fill:#2E5E96,stroke:#1E3A5F,color:#ffffff,font-weight:bold
classDef end_ fill:#0C1730,stroke:#14213D,color:#ffffff
is -> demo StormLine Lead Formfollow_up_count = 0 -> 1follow_up_count to 0 any time a new estimate is issued.
follow_up_count increments each cycle. After 2-3 check-ins with no reply, the loop exits and the rep is notified (P1_005_Notify_Pending). Contact stays in Decision Pending.
P1_006_Internal_CrewScheduling fires for scheduling, and the opp advances to Project Won. The 2 SMS below chase the build-date booking if they haven't picked a slot.
P1_007_Notify_Lost) and the opp moves to Project Lost. The storm-season SMS below is the long-game re-engage; if they bite, P1_007_Notify_WonBack pings the rep.
| Field | Merge tag | Sample value | Used in |
|---|---|---|---|
| Booking Link | {{custom_values.booking_link}} | https://gokai.pro/roofing-calendar | WF1 Welcome, Nudge1, Nudge2 + both WF1 SMS - the booking link |
| calendar_link | {{custom_values.calendar_link}} | https://gokai.pro/roofing-calendar | WF2 Confirmation - embedded calendar URL |
| google_review_link | {{custom_values.google_review_link}} | https://google.com | Review Engine Ask + Reminder - Google review CTA |
| company_name | {{custom_values.business_name}} | Stormline Roofing | All email headers & signatures + both WF1 SMS |
| from_name | {{custom_values.from_name}} | Stormline Roofing | Email "From" display name in all WFs |
| Company Phone | {{custom_values.company_phone}} | (305) 555-7842 | Email footers, WF2 HeadsUp, NSR LastTry, WF4 FU Loop |
| Company Address | {{custom_values.company_address}} | 2450 NW 79th Ave, Miami, Florida 33122 | Email footers / business address - NOT the inspection address (that's {{contact.full_address}}) |
| From Email | {{custom_values.from_email}} | support@stormlineroofing.com | Email footers / reply-to reference |
| offer_name | {{custom_values.offer_name}} | Free Roof Inspection | WF1 Nudge2 value prop, NSR re-engagement |
| signature | {{custom_values.signature}} | (empty - add your sign-off) | All email footers - reusable signature block |
| sms_output | {{custom_values.sms_output}} | Reply STOP to opt out | Live in WF1_SMS_Welcome + WF1_SMS_Nudge - compliance footer |
{{contact.first_name}}, {{contact.full_address}}, {{appointment.start_time}}) come from GHL directly and don't need setup here.A tag a workflow checks for must be set OUTSIDE that workflow - if the same flow sets and reads it, the goal fires too early or never. These helpers hold that boundary.
| Helper | Listens For | Does | Used By |
|---|---|---|---|
| Showed -> Complete | Appt status = showed (Roofing Consultation) | Update opp -> Inspection Complete | WF2 -> WF3 |
| Build Booked | Appt booked on Build calendar | Tag build_scheduled | WF6 |
| Concern Flag | Inbound reply (problem) | Tag project_concern | D2 |
| Review Signal | Review submitted | Tag review_sent | D3 |
| Referral Flag | Referral submitted | Tag referral_submitted | D4 |