@elitedcs/ghl-mcp 3.83.9 → 3.84.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/README.md +1 -1
- package/dist/index.js +22592 -20538
- package/guide/guide.html +1 -1
- package/package.json +1 -1
- package/skills/blueprint/presets/clinic.md +14 -1
- package/skills/blueprint/presets/clinic.preset.json +250 -8
- package/skills/blueprint/presets/coach.md +14 -1
- package/skills/blueprint/presets/coach.preset.json +259 -8
- package/skills/blueprint/presets/ecommerce.md +8 -1
- package/skills/blueprint/presets/ecommerce.preset.json +136 -3
- package/skills/blueprint/presets/generic-client.md +10 -1
- package/skills/blueprint/presets/generic-client.preset.json +312 -6
- package/skills/blueprint/presets/local-service.md +14 -1
- package/skills/blueprint/presets/local-service.preset.json +259 -8
- package/skills/blueprint/presets/med-spa.md +14 -1
- package/skills/blueprint/presets/med-spa.preset.json +259 -8
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"presetId": "coach",
|
|
3
|
-
"presetVersion": "2.
|
|
3
|
+
"presetVersion": "2.1.0",
|
|
4
4
|
"schemaVersion": "0.1",
|
|
5
5
|
"title": "Coach / Consultant",
|
|
6
|
-
"description": "A coach / consultant client-acquisition system at v2 depth (1:1, group, course or hybrid programs sold from a discovery call or an application). Client Journey pipeline, program-interest / challenge / timeline fields, source + lifecycle + interest tags, a round-robin Discovery Call calendar, an A2P-compliant application form, 15 email + 17 SMS send-ready templates built on belief shifts rather than hype, and
|
|
6
|
+
"description": "A coach / consultant client-acquisition system at v2 depth (1:1, group, course or hybrid programs sold from a discovery call or an application). Client Journey pipeline, program-interest / challenge / timeline fields, source + lifecycle + interest tags, a round-robin Discovery Call calendar, an A2P-compliant application form, 15 email + 17 SMS send-ready templates built on belief shifts rather than hype, and 10 workflows: Speed to Lead (15 actions, 5 touches in 24 h, then a hand-off), Missed Call Text-Back, Lead Nurture (31 days, 11 touches), Replied - Stop & Route, Win-back (31 days, 5 touches), Call Booked - Confirm & Move, Call Reminders, No-Show Rescue. No income or result claims unless the brief supplies real ones, plus Quote Follow-up and Review Request (v2.1.0).",
|
|
7
7
|
"default": false,
|
|
8
8
|
"selectors": {
|
|
9
9
|
"businessTypes": [
|
|
@@ -247,6 +247,26 @@
|
|
|
247
247
|
{
|
|
248
248
|
"ref": "tag.interest_course",
|
|
249
249
|
"name": "interest-course"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"ref": "tag.quote_sent",
|
|
253
|
+
"name": "quote-sent",
|
|
254
|
+
"_note": "Added when a proposal goes out. Starts Quote Follow-up; removed by it so a later proposal can start it again."
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"ref": "tag.quote_stale",
|
|
258
|
+
"name": "quote-stale",
|
|
259
|
+
"_note": "A proposal that got no answer through the whole follow-up."
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"ref": "tag.review_requested",
|
|
263
|
+
"name": "review-requested",
|
|
264
|
+
"_note": "A review was asked for after a completed call."
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"ref": "tag.service_done",
|
|
268
|
+
"name": "service-complete",
|
|
269
|
+
"_note": "Added when the work is done and paid for. Starts Review Request; removed by it so the next job can start it again."
|
|
250
270
|
}
|
|
251
271
|
],
|
|
252
272
|
"_tagNote": "Interest tags mirror the Program Interest options; the skill renames them to the real program names from the offer at fill time.",
|
|
@@ -276,6 +296,13 @@
|
|
|
276
296
|
"value": "",
|
|
277
297
|
"filledBy": "handoff.calendar_oauth",
|
|
278
298
|
"conditionalOn": "goal.bookingNeeded == true"
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
"ref": "cv.review_link",
|
|
302
|
+
"name": "review_link",
|
|
303
|
+
"value": "",
|
|
304
|
+
"filledBy": "handoff.review_link",
|
|
305
|
+
"_fill": "the Google review link; blank until the operator pastes it"
|
|
279
306
|
}
|
|
280
307
|
],
|
|
281
308
|
"calendars": [
|
|
@@ -284,7 +311,7 @@
|
|
|
284
311
|
"conditionalOn": "goal.bookingNeeded == true",
|
|
285
312
|
"name": "{{business.name}} Discovery Call || Discovery Call",
|
|
286
313
|
"calendarType": "round_robin",
|
|
287
|
-
"_slotDuration": "Carry the appointment length from the brief (brief.calendars[].durationMinutes, or the words in the calendar answer: \"15 minutes\"
|
|
314
|
+
"_slotDuration": "Carry the appointment length from the brief (brief.calendars[].durationMinutes, or the words in the calendar answer: \"15 minutes\" → 15) onto slotDuration (minutes, slotDurationUnit \"mins\"). This preset value applies ONLY when the brief gives no length; without any slotDuration GoHighLevel builds 30-minute slots (finding 25).",
|
|
288
315
|
"slotDuration": 30,
|
|
289
316
|
"slotDurationUnit": "mins",
|
|
290
317
|
"teamMemberRefs": [
|
|
@@ -310,7 +337,6 @@
|
|
|
310
337
|
}
|
|
311
338
|
],
|
|
312
339
|
"availabilityType": 0,
|
|
313
|
-
"slotDuration": 30,
|
|
314
340
|
"slotBuffer": 15,
|
|
315
341
|
"requiresStaff": true,
|
|
316
342
|
"notes": "Default Mon-Fri 10-4, 30-minute calls with 15 minutes between; operator edits after build. teamMemberRefs points at whoever takes discovery calls in the plan users list."
|
|
@@ -451,6 +477,18 @@
|
|
|
451
477
|
"name": "No-Show 2 - Still Want This?",
|
|
452
478
|
"subject": "Still want to do this?",
|
|
453
479
|
"html": "<div style=\"font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.5;color:#1f2937;max-width:600px;\"><p style=\"margin:0 0 14px;\">Hi {{contact.first_name}},</p><p style=\"margin:0 0 14px;\">Quick and honest: if the timing is wrong, say so and I'll check back in a few months. If it's still something you want, the calendar is open and the call is the same as before.</p><p style=\"margin:0 0 14px;\"><a href=\"{{custom_values.booking_link}}\" style=\"display:inline-block;background:#1a56db;color:#ffffff;padding:12px 20px;border-radius:6px;text-decoration:none;font-weight:600;\">Pick a new time</a></p><p style=\"margin:0 0 14px;\">Either way, thanks for considering {{custom_values.business_name}}.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
"ref": "email_template.quote_email_1",
|
|
483
|
+
"name": "Quote Follow-up - Day 3 Email",
|
|
484
|
+
"subject": "Any questions on your proposal, {{contact.first_name}}?",
|
|
485
|
+
"html": "<div style=\"font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.5;color:#1f2937;max-width:600px;\"><p style=\"margin:0 0 14px;\">Hi {{contact.first_name}},</p><p style=\"margin:0 0 14px;\">You have had the proposal from {{custom_values.business_name}} for a few days, so this is a short check-in rather than a push.</p><p style=\"margin:0 0 14px;\">Three things people usually ask at this point: what is included, what can wait, and how payment works. Reply with any of those and I will answer plainly.</p><p style=\"margin:0 0 14px;\">If you would rather talk it through, pick a time here:</p><p style=\"margin:0 0 14px;\"><a href=\"{{custom_values.booking_link}}\" style=\"display:inline-block;background:#1a56db;color:#ffffff;padding:12px 20px;border-radius:6px;text-decoration:none;font-weight:600;\">Book a quick call</a></p><p style=\"margin:0 0 14px;\">No pressure either way. The numbers stand for 30 days.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"ref": "email_template.review_email_1",
|
|
489
|
+
"name": "Review Request - Day 3 Email",
|
|
490
|
+
"subject": "One minute for a review, {{contact.first_name}}?",
|
|
491
|
+
"html": "<div style=\"font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.5;color:#1f2937;max-width:600px;\"><p style=\"margin:0 0 14px;\">Hi {{contact.first_name}},</p><p style=\"margin:0 0 14px;\">Thank you again for your call with {{custom_values.business_name}} this week.</p><p style=\"margin:0 0 14px;\">If it went well, a short review is the most useful thing you could do for us. It takes about a minute and it is how the next person decides to trust us.</p><p style=\"margin:0 0 14px;\"><a href=\"{{custom_values.review_link}}\" style=\"display:inline-block;background:#1a56db;color:#ffffff;padding:12px 20px;border-radius:6px;text-decoration:none;font-weight:600;\">Leave a review</a></p><p style=\"margin:0 0 14px;\">If anything was not right, reply to this email instead and I will fix it personally.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
454
492
|
}
|
|
455
493
|
],
|
|
456
494
|
"sms": [
|
|
@@ -538,6 +576,21 @@
|
|
|
538
576
|
"ref": "sms_template.ns_sms_2",
|
|
539
577
|
"name": "No-Show Text 2",
|
|
540
578
|
"body": "{{contact.first_name}}, {{custom_values.owner_first_name}} here. I kept a couple of call slots open for you this week. Want one? Reply with a day that works."
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
"ref": "sms_template.quote_sms_1",
|
|
582
|
+
"name": "Quote Follow-up - Next Day Text",
|
|
583
|
+
"body": "Hi {{contact.first_name}}, {{custom_values.owner_first_name}} at {{custom_values.business_name}}. Did the proposal make sense? Happy to walk through any part of it. Reply here or call {{custom_values.business_phone}}. Reply STOP to opt out."
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
"ref": "sms_template.quote_sms_2",
|
|
587
|
+
"name": "Quote Follow-up - Last Text",
|
|
588
|
+
"body": "Hi {{contact.first_name}}, last note from {{custom_values.business_name}} about your proposal. If the timing is off, one word back and I will check in when it suits you. Reply STOP to opt out."
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
"ref": "sms_template.review_sms_1",
|
|
592
|
+
"name": "Review Request - Same Day Text",
|
|
593
|
+
"body": "Thanks for working with us, {{contact.first_name}}. If we did right by you, a quick review helps the next person find us: {{custom_values.review_link}} Reply STOP to opt out."
|
|
541
594
|
}
|
|
542
595
|
]
|
|
543
596
|
},
|
|
@@ -752,6 +805,34 @@
|
|
|
752
805
|
"custom_values.owner_first_name",
|
|
753
806
|
"custom_values.business_phone"
|
|
754
807
|
]
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
"ref": "email.quote_email_1",
|
|
811
|
+
"name": "Quote Follow-up - Day 3 Email",
|
|
812
|
+
"subject": "Any questions on your proposal, {{contact.first_name}}?",
|
|
813
|
+
"templateRef": "email_template.quote_email_1",
|
|
814
|
+
"copyDirection": "Day three after the proposal. Check-in, not a push. Name the three questions people ask (what is included, what can wait, how payment works), invite a reply, booking CTA for a quick call. Tone: brief.voice.threeWords.",
|
|
815
|
+
"mergeTags": [
|
|
816
|
+
"contact.first_name",
|
|
817
|
+
"custom_values.business_name",
|
|
818
|
+
"custom_values.booking_link",
|
|
819
|
+
"custom_values.owner_first_name",
|
|
820
|
+
"custom_values.business_phone"
|
|
821
|
+
]
|
|
822
|
+
},
|
|
823
|
+
{
|
|
824
|
+
"ref": "email.review_email_1",
|
|
825
|
+
"name": "Review Request - Day 3 Email",
|
|
826
|
+
"subject": "One minute for a review, {{contact.first_name}}?",
|
|
827
|
+
"templateRef": "email_template.review_email_1",
|
|
828
|
+
"copyDirection": "Three days after a completed call with no review yet. Thank them, why it matters, the review button, and an honest line: if anything was not right, reply instead. Tone: brief.voice.threeWords.",
|
|
829
|
+
"mergeTags": [
|
|
830
|
+
"contact.first_name",
|
|
831
|
+
"custom_values.business_name",
|
|
832
|
+
"custom_values.review_link",
|
|
833
|
+
"custom_values.owner_first_name",
|
|
834
|
+
"custom_values.business_phone"
|
|
835
|
+
]
|
|
755
836
|
}
|
|
756
837
|
],
|
|
757
838
|
"sms": [
|
|
@@ -944,6 +1025,41 @@
|
|
|
944
1025
|
"custom_values.owner_first_name"
|
|
945
1026
|
],
|
|
946
1027
|
"conditionalOn": "channels.sms == true"
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
"ref": "sms.quote_sms_1",
|
|
1031
|
+
"name": "Quote Follow-up - Next Day Text",
|
|
1032
|
+
"templateRef": "sms_template.quote_sms_1",
|
|
1033
|
+
"copyDirection": "One day after the proposal went out. Owner's first name and business, one question: did it make sense. Offer to walk through it, reply or call. STOP line.",
|
|
1034
|
+
"mergeTags": [
|
|
1035
|
+
"contact.first_name",
|
|
1036
|
+
"custom_values.owner_first_name",
|
|
1037
|
+
"custom_values.business_name",
|
|
1038
|
+
"custom_values.business_phone"
|
|
1039
|
+
],
|
|
1040
|
+
"conditionalOn": "channels.sms == true"
|
|
1041
|
+
},
|
|
1042
|
+
{
|
|
1043
|
+
"ref": "sms.quote_sms_2",
|
|
1044
|
+
"name": "Quote Follow-up - Last Text",
|
|
1045
|
+
"templateRef": "sms_template.quote_sms_2",
|
|
1046
|
+
"copyDirection": "Last text of the follow-up, five days in. No guilt: if the timing is off, one word back and we check in later. STOP line.",
|
|
1047
|
+
"mergeTags": [
|
|
1048
|
+
"contact.first_name",
|
|
1049
|
+
"custom_values.business_name"
|
|
1050
|
+
],
|
|
1051
|
+
"conditionalOn": "channels.sms == true"
|
|
1052
|
+
},
|
|
1053
|
+
{
|
|
1054
|
+
"ref": "sms.review_sms_1",
|
|
1055
|
+
"name": "Review Request - Same Day Text",
|
|
1056
|
+
"templateRef": "sms_template.review_sms_1",
|
|
1057
|
+
"copyDirection": "Two hours after the service-complete tag, i.e. a finished and paid call. Thank them, one sentence on why a review helps, the review link. STOP line.",
|
|
1058
|
+
"mergeTags": [
|
|
1059
|
+
"contact.first_name",
|
|
1060
|
+
"custom_values.review_link"
|
|
1061
|
+
],
|
|
1062
|
+
"conditionalOn": "channels.sms == true"
|
|
947
1063
|
}
|
|
948
1064
|
],
|
|
949
1065
|
"workflows": [
|
|
@@ -1541,6 +1657,106 @@
|
|
|
1541
1657
|
}
|
|
1542
1658
|
],
|
|
1543
1659
|
"conditionalOn": "goal.bookingNeeded == true"
|
|
1660
|
+
},
|
|
1661
|
+
{
|
|
1662
|
+
"ref": "workflow.quote_follow_up",
|
|
1663
|
+
"name": "Quote Follow-up",
|
|
1664
|
+
"trigger": {
|
|
1665
|
+
"type": "contact_tag",
|
|
1666
|
+
"tagRef": "tag.quote_sent"
|
|
1667
|
+
},
|
|
1668
|
+
"stopOnResponse": true,
|
|
1669
|
+
"_design": "Starts when the quote-sent tag is added (by hand, or by the estimate workflow the operator builds in the UI). Removes its own trigger tag first so the next proposal can start it again. Text next day, email on day 3, last text on day 5, then a call task for the owner and the quote-stale tag. Any reply stops it (stopOnResponse) and Replied - Stop & Route takes over. Closes the Layer 4 gap named on the hub: the assessment measured quote follow-up and nothing built it (2026-09-14).",
|
|
1670
|
+
"actions": [
|
|
1671
|
+
{
|
|
1672
|
+
"type": "remove_contact_tag",
|
|
1673
|
+
"tagRef": "tag.quote_sent"
|
|
1674
|
+
},
|
|
1675
|
+
{
|
|
1676
|
+
"type": "wait",
|
|
1677
|
+
"value": 1,
|
|
1678
|
+
"unit": "days"
|
|
1679
|
+
},
|
|
1680
|
+
{
|
|
1681
|
+
"type": "send_sms",
|
|
1682
|
+
"smsRef": "sms.quote_sms_1",
|
|
1683
|
+
"conditionalOn": "channels.sms == true"
|
|
1684
|
+
},
|
|
1685
|
+
{
|
|
1686
|
+
"type": "wait",
|
|
1687
|
+
"value": 2,
|
|
1688
|
+
"unit": "days"
|
|
1689
|
+
},
|
|
1690
|
+
{
|
|
1691
|
+
"type": "send_email",
|
|
1692
|
+
"emailRef": "email.quote_email_1"
|
|
1693
|
+
},
|
|
1694
|
+
{
|
|
1695
|
+
"type": "wait",
|
|
1696
|
+
"value": 2,
|
|
1697
|
+
"unit": "days"
|
|
1698
|
+
},
|
|
1699
|
+
{
|
|
1700
|
+
"type": "send_sms",
|
|
1701
|
+
"smsRef": "sms.quote_sms_2",
|
|
1702
|
+
"conditionalOn": "channels.sms == true"
|
|
1703
|
+
},
|
|
1704
|
+
{
|
|
1705
|
+
"type": "wait",
|
|
1706
|
+
"value": 2,
|
|
1707
|
+
"unit": "days"
|
|
1708
|
+
},
|
|
1709
|
+
{
|
|
1710
|
+
"type": "task_notification",
|
|
1711
|
+
"userRef": "user.owner",
|
|
1712
|
+
"title": "Call {{contact.first_name}} about their proposal",
|
|
1713
|
+
"body": "No reply to the proposal in a week. One call, no pressure: what would make this a yes, or when should we check back.",
|
|
1714
|
+
"dueDate": "1"
|
|
1715
|
+
},
|
|
1716
|
+
{
|
|
1717
|
+
"type": "add_contact_tag",
|
|
1718
|
+
"tagRef": "tag.quote_stale"
|
|
1719
|
+
}
|
|
1720
|
+
]
|
|
1721
|
+
},
|
|
1722
|
+
{
|
|
1723
|
+
"ref": "workflow.review_request",
|
|
1724
|
+
"name": "Review Request",
|
|
1725
|
+
"trigger": {
|
|
1726
|
+
"type": "contact_tag",
|
|
1727
|
+
"tagRef": "tag.service_done"
|
|
1728
|
+
},
|
|
1729
|
+
"stopOnResponse": true,
|
|
1730
|
+
"_design": "Starts from the service-complete tag, added when the work is done and paid for (by hand, or from the won stage of the pipeline). Never from a consult, estimate or discovery call: a prospect who did not buy is not asked for a review. On a completed call (status showed): tag, wait two hours, text the review link, then an email three days later if nothing came back. Any reply stops it. The review link is a custom value the operator pastes once (handoff.review_link). Closes the Layer 4 gap named on the hub: review requests had no build feature (2026-09-14).",
|
|
1731
|
+
"actions": [
|
|
1732
|
+
{
|
|
1733
|
+
"type": "remove_contact_tag",
|
|
1734
|
+
"tagRef": "tag.service_done"
|
|
1735
|
+
},
|
|
1736
|
+
{
|
|
1737
|
+
"type": "add_contact_tag",
|
|
1738
|
+
"tagRef": "tag.review_requested"
|
|
1739
|
+
},
|
|
1740
|
+
{
|
|
1741
|
+
"type": "wait",
|
|
1742
|
+
"value": 2,
|
|
1743
|
+
"unit": "hours"
|
|
1744
|
+
},
|
|
1745
|
+
{
|
|
1746
|
+
"type": "send_sms",
|
|
1747
|
+
"smsRef": "sms.review_sms_1",
|
|
1748
|
+
"conditionalOn": "channels.sms == true"
|
|
1749
|
+
},
|
|
1750
|
+
{
|
|
1751
|
+
"type": "wait",
|
|
1752
|
+
"value": 3,
|
|
1753
|
+
"unit": "days"
|
|
1754
|
+
},
|
|
1755
|
+
{
|
|
1756
|
+
"type": "send_email",
|
|
1757
|
+
"emailRef": "email.review_email_1"
|
|
1758
|
+
}
|
|
1759
|
+
]
|
|
1544
1760
|
}
|
|
1545
1761
|
],
|
|
1546
1762
|
"handoffs": [
|
|
@@ -1558,7 +1774,8 @@
|
|
|
1558
1774
|
"workflow.reply_route",
|
|
1559
1775
|
"workflow.appointment_booked",
|
|
1560
1776
|
"workflow.no_show",
|
|
1561
|
-
"workflow.missed_call"
|
|
1777
|
+
"workflow.missed_call",
|
|
1778
|
+
"workflow.quote_follow_up"
|
|
1562
1779
|
],
|
|
1563
1780
|
"_blocksNote": "Workflows with a notification or task pointed at user.__pending__ stay DRAFT until a real user is assigned. Prune entries whose workflow was dropped by conditional pruning."
|
|
1564
1781
|
},
|
|
@@ -1578,7 +1795,9 @@
|
|
|
1578
1795
|
"workflow.win_back",
|
|
1579
1796
|
"workflow.appointment_booked",
|
|
1580
1797
|
"workflow.appointment_reminders",
|
|
1581
|
-
"workflow.no_show"
|
|
1798
|
+
"workflow.no_show",
|
|
1799
|
+
"workflow.quote_follow_up",
|
|
1800
|
+
"workflow.review_request"
|
|
1582
1801
|
]
|
|
1583
1802
|
},
|
|
1584
1803
|
{
|
|
@@ -1652,7 +1871,9 @@
|
|
|
1652
1871
|
"sms.appt_24h_sms",
|
|
1653
1872
|
"sms.appt_2h_sms",
|
|
1654
1873
|
"sms.ns_sms_1",
|
|
1655
|
-
"sms.ns_sms_2"
|
|
1874
|
+
"sms.ns_sms_2",
|
|
1875
|
+
"workflow.quote_follow_up",
|
|
1876
|
+
"workflow.review_request"
|
|
1656
1877
|
],
|
|
1657
1878
|
"_blocksNote": "Lists every SMS-bearing WORKFLOW ref (so they stay DRAFT) plus the sms.* asset refs. After conditional pruning, drop any entry whose workflow/asset was removed."
|
|
1658
1879
|
},
|
|
@@ -1691,8 +1912,38 @@
|
|
|
1691
1912
|
"email.appt_confirm_email",
|
|
1692
1913
|
"email.appt_prep_email",
|
|
1693
1914
|
"email.ns_email_1",
|
|
1694
|
-
"email.ns_email_2"
|
|
1915
|
+
"email.ns_email_2",
|
|
1916
|
+
"email.quote_email_1",
|
|
1917
|
+
"email.review_email_1"
|
|
1695
1918
|
]
|
|
1919
|
+
},
|
|
1920
|
+
{
|
|
1921
|
+
"ref": "handoff.review_link",
|
|
1922
|
+
"owner": "OPERATOR-UI",
|
|
1923
|
+
"title": "Paste the Google review link so review requests point somewhere",
|
|
1924
|
+
"trigger": "always (2 minutes)",
|
|
1925
|
+
"instruction": "In Google Business Profile, open the profile, choose Ask for reviews and copy the short link. Then in the sub-account: Settings > Custom Values: set review_link to that link. Until it is set, the Review Request workflow sends a text with no link, so do this before the first call is marked showed.",
|
|
1926
|
+
"produces": "cv.review_link",
|
|
1927
|
+
"successCheck": "review_link shows a real https link, not a blank",
|
|
1928
|
+
"blocks": [
|
|
1929
|
+
"cv.review_link"
|
|
1930
|
+
]
|
|
1931
|
+
},
|
|
1932
|
+
{
|
|
1933
|
+
"ref": "handoff.quote_tag",
|
|
1934
|
+
"owner": "OPERATOR-UI",
|
|
1935
|
+
"title": "Start Quote Follow-up by tagging quote-sent when a proposal goes out",
|
|
1936
|
+
"trigger": "always (1 minute to read)",
|
|
1937
|
+
"instruction": "Quote Follow-up starts from the tag quote-sent. Add that tag to the contact whenever a proposal goes out: by hand on the contact, or, if the proposals are sent as GoHighLevel estimates, build one workflow in the UI with the Estimate trigger (status sent) whose only step adds the tag quote-sent. The follow-up removes the tag itself, so the next proposal starts it again.",
|
|
1938
|
+
"successCheck": "A contact tagged quote-sent receives the next-day text"
|
|
1939
|
+
},
|
|
1940
|
+
{
|
|
1941
|
+
"ref": "handoff.review_tag",
|
|
1942
|
+
"owner": "OPERATOR-UI",
|
|
1943
|
+
"title": "Start Review Request by tagging service-complete when the work is done",
|
|
1944
|
+
"trigger": "always (1 minute to read)",
|
|
1945
|
+
"instruction": "Review Request starts from the tag service-complete. Add that tag when the job is finished and paid for: by hand on the contact, or from the pipeline's won stage with one small workflow whose only step adds the tag. It never starts from a consult, estimate or discovery call, so nobody who did not buy is asked for a review.",
|
|
1946
|
+
"successCheck": "A contact tagged service-complete receives the review text two hours later"
|
|
1696
1947
|
}
|
|
1697
1948
|
]
|
|
1698
1949
|
}
|
|
@@ -15,7 +15,7 @@ Routes from the "Ecommerce" business type (online store, Shopify store, DTC bran
|
|
|
15
15
|
- **No calendar** — this preset does not book appointments; the Speed to Lead and nurture sequences drive replies and orders instead.
|
|
16
16
|
- **1 intake form + 1 funnel** — "VIP List Signup" (first name, email, phone, what they are shopping for) and a Join the VIP List landing page (the welcome code, what the list gets, A2P consent block) plus a Thank You page that shows the code and links to the store.
|
|
17
17
|
- **11 email + 12 SMS templates** — complete, send-ready copy written to `references/copy-guide.md`. The build stage rewrites every one from the real brief (offer, pain points, objections, prices, lead magnet) and keeps the cadence, the single CTA and the merge fields.
|
|
18
|
-
- **
|
|
18
|
+
- **6 workflows, 23 customer touches** — see the table.
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
## Workflows
|
|
@@ -27,6 +27,7 @@ Routes from the "Ecommerce" business type (online store, Shopify store, DTC bran
|
|
|
27
27
|
| Lead Nurture (30 days) | contact_tag (tag.nurture_start) | 28 | 11 | 31 days | yes |
|
|
28
28
|
| Replied - Stop & Route | customer_reply | 8 | 0 | instant | no |
|
|
29
29
|
| Win-back (30 days) | contact_tag (tag.winback_start) | 13 | 5 | 31 days | yes |
|
|
30
|
+
| Review Requests | contact_tag (tag.review_ask) | 8 | 3 | 7 days | yes |
|
|
30
31
|
|
|
31
32
|
- **Speed to Lead** (15 actions): instant text + email, opportunity card, the contact assigned to whoever takes calls, alert to a real person, a call task due today, a 2nd touch at 20 minutes, a 3rd at 3 hours, a 4th and 5th by the next day, then the hand-off tag `nurture-start` as the last action.
|
|
32
33
|
- **Lead Nurture** (28 actions, 11 touches, 31 days of waits): give, give, ask. Ends with `lifecycle-lapsed` + the `winback-start` hand-off.
|
|
@@ -34,6 +35,12 @@ Routes from the "Ecommerce" business type (online store, Shopify store, DTC bran
|
|
|
34
35
|
- **Replied - Stop & Route**: the exit workflow. Pulls the contact out of every sequence, notes it, marks contacted, alerts a person and creates a 15-minute reply task.
|
|
35
36
|
- **Missed Call Text-Back**: `call_status` trigger scoped to no-answer / busy / voicemail, inbound. Text within seconds, tag, alert, call-back task, one more text an hour later.
|
|
36
37
|
|
|
38
|
+
### Added in v2.1.0 (2026-09-06): the two features the Assessment prices
|
|
39
|
+
|
|
40
|
+
- **Review Requests** (feature `review_requests`): starts from the `review-ask` tag applied when the work is done. Text two hours later with the Google link from the `review_link` custom value, email on day 3, last text on day 7; any reply stops it (a complaint reaches a person, not a second nudge); ends by tagging `review-asked`. Hand-off `handoff.review_link` collects the link.
|
|
41
|
+
|
|
42
|
+
Every workflow now belongs to a feature (`src/intake-to-build/features.ts`) so a client's Blueprint builds what they bought; the reply router is the foundation every messaging feature stands on.
|
|
43
|
+
|
|
37
44
|
### Why sequences hand off with a tag, not add_to_workflow
|
|
38
45
|
Every hand-off is `add_contact_tag` + a `contact_tag` trigger. Both halves are live-proven shapes captured from working GHL workflows (`templates/action-schemas.json`). `add_to_workflow` has no captured native shape there and has not been proven at runtime, so a preset may not use it. Each sequence removes its own trigger tag as its first action so a later hand-off can start it again.
|
|
39
46
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"presetId": "ecom",
|
|
3
|
-
"presetVersion": "2.
|
|
3
|
+
"presetVersion": "2.1.0",
|
|
4
4
|
"schemaVersion": "0.1",
|
|
5
5
|
"title": "Ecommerce",
|
|
6
|
-
"description": "An ecommerce list-to-first-order system at v2 depth (Shopify, WooCommerce, BigCommerce or any store). Store Leads pipeline (subscriber to VIP), product-interest / order fields, source + lifecycle + interest tags, a VIP-list signup form + landing page with the welcome code, 11 email + 12 SMS send-ready templates, and
|
|
6
|
+
"description": "An ecommerce list-to-first-order system at v2 depth (Shopify, WooCommerce, BigCommerce or any store). Store Leads pipeline (subscriber to VIP), product-interest / order fields, source + lifecycle + interest tags, a VIP-list signup form + landing page with the welcome code, 11 email + 12 SMS send-ready templates, and 6 workflows: Speed to Lead (15 actions, 5 touches in 24 h with the welcome code, a personal-welcome task for a real person, then a hand-off), Missed Call Text-Back (the support line), Lead Nurture (31 days, 11 touches: how to choose, why we make it, best sellers, shipping and returns, the code expiring), Replied - Stop & Route, Win-back (31 days, 5 touches). No calendar. Order events come from the store (handoff), never from GHL, plus Review Request (v2.1.0).",
|
|
7
7
|
"default": false,
|
|
8
8
|
"selectors": {
|
|
9
9
|
"businessTypes": [
|
|
@@ -224,6 +224,14 @@
|
|
|
224
224
|
{
|
|
225
225
|
"ref": "tag.interest_gift",
|
|
226
226
|
"name": "interest-gift"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"ref": "tag.review_ask",
|
|
230
|
+
"name": "review-ask"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"ref": "tag.review_asked",
|
|
234
|
+
"name": "review-asked"
|
|
227
235
|
}
|
|
228
236
|
],
|
|
229
237
|
"_tagNote": "Interest tags mirror the Shopping For options; the skill renames them to the real categories from the offer at fill time.",
|
|
@@ -264,6 +272,12 @@
|
|
|
264
272
|
"name": "code_expiry_days",
|
|
265
273
|
"value": "14",
|
|
266
274
|
"_note": "The welcome code is valid this many days; copy says \"14 days\" by default and the store discount must match."
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"ref": "cv.review_link",
|
|
278
|
+
"name": "review_link",
|
|
279
|
+
"value": "",
|
|
280
|
+
"filledBy": "handoff.review_link"
|
|
267
281
|
}
|
|
268
282
|
],
|
|
269
283
|
"calendars": [],
|
|
@@ -363,6 +377,12 @@
|
|
|
363
377
|
"name": "Win-back 3 - We'll Quiet Down",
|
|
364
378
|
"subject": "We'll quiet down now",
|
|
365
379
|
"html": "<div style=\"font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.5;color:#1f2937;max-width:600px;\"><p style=\"margin:0 0 14px;\">Hi {{contact.first_name}},</p><p style=\"margin:0 0 14px;\">This is the last automatic email in this series. From here you'll only hear from {{custom_values.business_name}} about new pieces and real restocks, which is what most people on the list want anyway.</p><p style=\"margin:0 0 14px;\">The store is always open, and so is the reply button on any email from us.</p><p style=\"margin:0 0 14px;\"><a href=\"{{custom_values.store_link}}\" style=\"display:inline-block;background:#1a56db;color:#ffffff;padding:12px 20px;border-radius:6px;text-decoration:none;font-weight:600;\">Visit {{custom_values.business_name}}</a></p><p style=\"margin:0 0 14px;\">Thanks for giving us a look.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"ref": "email_template.r_email_1",
|
|
383
|
+
"name": "Review Request - Email",
|
|
384
|
+
"subject": "A minute of your time, {{contact.first_name}}?",
|
|
385
|
+
"html": "<div style=\"font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.5;color:#1f2937;max-width:600px;\"><p style=\"margin:0 0 14px;\">Hi {{contact.first_name}},</p><p style=\"margin:0 0 14px;\">Thank you for choosing {{custom_values.business_name}}. I hope everything went the way you wanted; if it did not, reply to this and I will make it right before anything else.</p><p style=\"margin:0 0 14px;\">If it did, would you leave us a short Google review? A line or two about what we did and how it went is all it takes, and it is genuinely how the next person decides to call.</p><p style=\"margin:0 0 14px;\"><a href=\"{{custom_values.review_link}}\">Leave a review here</a></p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
366
386
|
}
|
|
367
387
|
],
|
|
368
388
|
"sms": [
|
|
@@ -425,6 +445,16 @@
|
|
|
425
445
|
"ref": "sms_template.w_sms_2",
|
|
426
446
|
"name": "Win-back Text 2",
|
|
427
447
|
"body": "{{contact.first_name}}, fresh first-order code for you at {{custom_values.business_name}}: {{custom_values.welcome_code}}, {{custom_values.code_expiry_days}} days, one use. {{custom_values.store_link}}"
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
"ref": "sms_template.r_sms_1",
|
|
451
|
+
"name": "Review Request - Text 1",
|
|
452
|
+
"body": "Hi {{contact.first_name}}, it's {{custom_values.owner_first_name}} at {{custom_values.business_name}}. Thank you for choosing us. If we did right by you, a quick Google review helps more than you'd think: {{custom_values.review_link}} Reply STOP to opt out."
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
"ref": "sms_template.r_sms_2",
|
|
456
|
+
"name": "Review Request - Text 2",
|
|
457
|
+
"body": "Hi {{contact.first_name}}, last nudge from {{custom_values.owner_first_name}}: a one-line Google review takes about a minute and it's how the next person finds us. {{custom_values.review_link}} Thank you either way. Reply STOP to opt out."
|
|
428
458
|
}
|
|
429
459
|
]
|
|
430
460
|
},
|
|
@@ -592,6 +622,20 @@
|
|
|
592
622
|
"custom_values.owner_first_name",
|
|
593
623
|
"custom_values.business_phone"
|
|
594
624
|
]
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
"ref": "email.r_email_1",
|
|
628
|
+
"name": "Review Request - Email",
|
|
629
|
+
"subject": "A minute of your time, {{contact.first_name}}?",
|
|
630
|
+
"templateRef": "email_template.r_email_1",
|
|
631
|
+
"copyDirection": "Three days after the tag. Thank them, invite the complaint first (reply and I will fix it), then the ask with the link. Tone: brief.voice.threeWords.",
|
|
632
|
+
"mergeTags": [
|
|
633
|
+
"contact.first_name",
|
|
634
|
+
"custom_values.business_name",
|
|
635
|
+
"custom_values.review_link",
|
|
636
|
+
"custom_values.owner_first_name",
|
|
637
|
+
"custom_values.business_phone"
|
|
638
|
+
]
|
|
595
639
|
}
|
|
596
640
|
],
|
|
597
641
|
"sms": [
|
|
@@ -734,6 +778,31 @@
|
|
|
734
778
|
"custom_values.store_link"
|
|
735
779
|
],
|
|
736
780
|
"conditionalOn": "channels.sms == true"
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
"ref": "sms.r_sms_1",
|
|
784
|
+
"name": "Review Request - Text 1",
|
|
785
|
+
"templateRef": "sms_template.r_sms_1",
|
|
786
|
+
"copyDirection": "Two hours after the tag. Thank them, one plain ask, the link, STOP line. No pressure, no incentive (Google forbids it).",
|
|
787
|
+
"mergeTags": [
|
|
788
|
+
"contact.first_name",
|
|
789
|
+
"custom_values.owner_first_name",
|
|
790
|
+
"custom_values.business_name",
|
|
791
|
+
"custom_values.review_link"
|
|
792
|
+
],
|
|
793
|
+
"conditionalOn": "channels.sms == true"
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
"ref": "sms.r_sms_2",
|
|
797
|
+
"name": "Review Request - Text 2",
|
|
798
|
+
"templateRef": "sms_template.r_sms_2",
|
|
799
|
+
"copyDirection": "A week later, the last nudge. Say it is the last one. Link, thanks either way, STOP line.",
|
|
800
|
+
"mergeTags": [
|
|
801
|
+
"contact.first_name",
|
|
802
|
+
"custom_values.owner_first_name",
|
|
803
|
+
"custom_values.review_link"
|
|
804
|
+
],
|
|
805
|
+
"conditionalOn": "channels.sms == true"
|
|
737
806
|
}
|
|
738
807
|
],
|
|
739
808
|
"workflows": [
|
|
@@ -1136,6 +1205,55 @@
|
|
|
1136
1205
|
"tagRef": "tag.lc_lost"
|
|
1137
1206
|
}
|
|
1138
1207
|
]
|
|
1208
|
+
},
|
|
1209
|
+
{
|
|
1210
|
+
"ref": "workflow.review_request",
|
|
1211
|
+
"name": "Review Requests",
|
|
1212
|
+
"trigger": {
|
|
1213
|
+
"type": "contact_tag",
|
|
1214
|
+
"tagRef": "tag.review_ask"
|
|
1215
|
+
},
|
|
1216
|
+
"stopOnResponse": true,
|
|
1217
|
+
"_design": "Starts from the review-ask tag, applied when an order has arrived (by hand or from the stage the operator uses for finished work). Three touches over a week with the Google review link from the review_link custom value. Any reply stops it, so a complaint reaches a person instead of a second nudge. Ends by tagging review-asked so nobody is asked twice.",
|
|
1218
|
+
"actions": [
|
|
1219
|
+
{
|
|
1220
|
+
"type": "remove_contact_tag",
|
|
1221
|
+
"tagRef": "tag.review_ask"
|
|
1222
|
+
},
|
|
1223
|
+
{
|
|
1224
|
+
"type": "wait",
|
|
1225
|
+
"value": 2,
|
|
1226
|
+
"unit": "hours"
|
|
1227
|
+
},
|
|
1228
|
+
{
|
|
1229
|
+
"type": "send_sms",
|
|
1230
|
+
"smsRef": "sms.r_sms_1",
|
|
1231
|
+
"conditionalOn": "channels.sms == true"
|
|
1232
|
+
},
|
|
1233
|
+
{
|
|
1234
|
+
"type": "wait",
|
|
1235
|
+
"value": 3,
|
|
1236
|
+
"unit": "days"
|
|
1237
|
+
},
|
|
1238
|
+
{
|
|
1239
|
+
"type": "send_email",
|
|
1240
|
+
"emailRef": "email.r_email_1"
|
|
1241
|
+
},
|
|
1242
|
+
{
|
|
1243
|
+
"type": "wait",
|
|
1244
|
+
"value": 4,
|
|
1245
|
+
"unit": "days"
|
|
1246
|
+
},
|
|
1247
|
+
{
|
|
1248
|
+
"type": "send_sms",
|
|
1249
|
+
"smsRef": "sms.r_sms_2",
|
|
1250
|
+
"conditionalOn": "channels.sms == true"
|
|
1251
|
+
},
|
|
1252
|
+
{
|
|
1253
|
+
"type": "add_contact_tag",
|
|
1254
|
+
"tagRef": "tag.review_asked"
|
|
1255
|
+
}
|
|
1256
|
+
]
|
|
1139
1257
|
}
|
|
1140
1258
|
],
|
|
1141
1259
|
"handoffs": [
|
|
@@ -1208,7 +1326,10 @@
|
|
|
1208
1326
|
"sms.n_sms_4",
|
|
1209
1327
|
"sms.n_sms_5",
|
|
1210
1328
|
"sms.w_sms_1",
|
|
1211
|
-
"sms.w_sms_2"
|
|
1329
|
+
"sms.w_sms_2",
|
|
1330
|
+
"workflow.review_request",
|
|
1331
|
+
"sms.r_sms_1",
|
|
1332
|
+
"sms.r_sms_2"
|
|
1212
1333
|
],
|
|
1213
1334
|
"_blocksNote": "Lists every SMS-bearing WORKFLOW ref (so they stay DRAFT) plus the sms.* asset refs. After conditional pruning, drop any entry whose workflow/asset was removed."
|
|
1214
1335
|
},
|
|
@@ -1259,6 +1380,18 @@
|
|
|
1259
1380
|
"email.w_email_2",
|
|
1260
1381
|
"email.w_email_3"
|
|
1261
1382
|
]
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
"ref": "handoff.review_link",
|
|
1386
|
+
"owner": "OPERATOR-UI",
|
|
1387
|
+
"title": "Paste your Google review link, then tag finished work review-ask",
|
|
1388
|
+
"trigger": "always",
|
|
1389
|
+
"instruction": "In your Google Business Profile, open Ask for reviews and copy the short link. Paste it into the review_link custom value. From then on, add the tag review-ask to a contact when an order has arrived (or automate it from the stage you use for finished work); the requests start from the tag and stop the moment they reply.",
|
|
1390
|
+
"produces": "cv.review_link",
|
|
1391
|
+
"successCheck": "The review_link custom value opens your Google review form, and a test contact tagged review-ask receives the first text two hours later",
|
|
1392
|
+
"blocks": [
|
|
1393
|
+
"cv.review_link"
|
|
1394
|
+
]
|
|
1262
1395
|
}
|
|
1263
1396
|
]
|
|
1264
1397
|
}
|
|
@@ -15,7 +15,7 @@ The fallback for every `business_type` without a dedicated preset: agencies, "ot
|
|
|
15
15
|
- **1 calendar** — Consultation (round_robin, Mon-Fri 9-17 default, 30-minute slots, `teamMemberRefs` → the plan users).*
|
|
16
16
|
- **1 intake form + 1 funnel** — "New Inquiry" (first/last/email/phone + what they need) and a Landing page (offer promise, three outcome-led points, one CTA to the form, A2P consent block) plus a Thank You page with the booking widget.
|
|
17
17
|
- **15 email + 17 SMS templates** — complete, send-ready copy written to `references/copy-guide.md`. The build stage rewrites every one from the real brief (offer, pain points, objections, prices, lead magnet) and keeps the cadence, the single CTA and the merge fields.
|
|
18
|
-
- **
|
|
18
|
+
- **10 workflows, 32 customer touches** — see the table.
|
|
19
19
|
|
|
20
20
|
\* conditional on `goal.bookingNeeded == true`.
|
|
21
21
|
|
|
@@ -28,6 +28,8 @@ The fallback for every `business_type` without a dedicated preset: agencies, "ot
|
|
|
28
28
|
| Lead Nurture (30 days) | contact_tag (tag.nurture_start) | 28 | 11 | 31 days | yes |
|
|
29
29
|
| Replied - Stop & Route | customer_reply | 9 | 0 | instant | no |
|
|
30
30
|
| Win-back (30 days) | contact_tag (tag.winback_start) | 13 | 5 | 31 days | yes |
|
|
31
|
+
| Quote Follow-up | contact_tag (tag.quote_sent) | 14 | 4 + a call task | 10 days | yes |
|
|
32
|
+
| Review Requests | contact_tag (tag.review_ask) | 8 | 3 | 7 days | yes |
|
|
31
33
|
| Appointment Booked - Confirm & Move | appointment (confirmed) | 8 | 2 | instant | no |
|
|
32
34
|
| Appointment Reminders | appointment (confirmed) | 5 | 3 | instant | no |
|
|
33
35
|
| No-Show Rescue | appointment (noshow) | 14 | 4 | 7 days | yes |
|
|
@@ -39,6 +41,13 @@ The fallback for every `business_type` without a dedicated preset: agencies, "ot
|
|
|
39
41
|
- **Missed Call Text-Back**: `call_status` trigger scoped to no-answer / busy / voicemail, inbound. Text within seconds, tag, alert, call-back task, one more text an hour later.
|
|
40
42
|
- **Consultation → Confirm & Move, Reminders, No-Show Rescue**: booking stops every sequence and moves (or creates) the opportunity; reminders at 24 h and 2 h; a no-show gets a same-day call task, text and email, two more touches, then hands off to Win-back and moves the card back to Contacted.
|
|
41
43
|
|
|
44
|
+
### Added in v2.1.0 (2026-09-06): the two features the Assessment prices
|
|
45
|
+
|
|
46
|
+
- **Quote Follow-up** (feature `quote_followup`): starts from the `quote-sent` tag the operator applies when a quote goes out (by hand, from a quoting tool, or from a stage). Text on day 1, email on day 3, text on day 6 plus a call task, last email on day 10; any reply stops it; ends by tagging `quote-no-reply`. Hand-off `handoff.quote_tag` explains the tag.
|
|
47
|
+
- **Review Requests** (feature `review_requests`): starts from the `review-ask` tag applied when the work is done. Text two hours later with the Google link from the `review_link` custom value, email on day 3, last text on day 7; any reply stops it (a complaint reaches a person, not a second nudge); ends by tagging `review-asked`. Hand-off `handoff.review_link` collects the link.
|
|
48
|
+
|
|
49
|
+
Every workflow now belongs to a feature (`src/intake-to-build/features.ts`) so a client's Blueprint builds what they bought; the reply router is the foundation every messaging feature stands on.
|
|
50
|
+
|
|
42
51
|
### Why sequences hand off with a tag, not add_to_workflow
|
|
43
52
|
Every hand-off is `add_contact_tag` + a `contact_tag` trigger. Both halves are live-proven shapes captured from working GHL workflows (`templates/action-schemas.json`). `add_to_workflow` has no captured native shape there and has not been proven at runtime, so a preset may not use it. Each sequence removes its own trigger tag as its first action so a later hand-off can start it again.
|
|
44
53
|
|