@elitedcs/ghl-mcp 3.83.9 → 3.84.0
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 +43 -0
- package/README.md +1 -1
- package/dist/index.js +21775 -20422
- 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": "generic",
|
|
3
|
-
"presetVersion": "2.
|
|
3
|
+
"presetVersion": "2.1.0",
|
|
4
4
|
"schemaVersion": "0.1",
|
|
5
5
|
"title": "Generic Client",
|
|
6
|
-
"description": "The neutral lead-to-customer fallback build at v2 depth (agency, \"other\", and any unmatched type; clinic / coach / ecommerce / local service now have their own presets). Sales pipeline, core fields, tag system, booking calendar, intake form + landing page, 15 email + 17 SMS send-ready templates, and
|
|
6
|
+
"description": "The neutral lead-to-customer fallback build at v2 depth (agency, \"other\", and any unmatched type; clinic / coach / ecommerce / local service now have their own presets). Sales pipeline, core fields, tag system, booking calendar, intake form + landing page, 15 email + 17 SMS send-ready templates, 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), Appointment Booked - Confirm & Move, Appointment Reminders, No-Show Rescue. Industry-neutral copy that still reads like a person wrote it; the build stage rewrites every template from the brief, plus Quote Follow-up and Review Request (v2.1.0).",
|
|
7
7
|
"default": false,
|
|
8
8
|
"selectors": {
|
|
9
9
|
"businessTypes": [
|
|
@@ -218,6 +218,26 @@
|
|
|
218
218
|
"ref": "tag.no_show",
|
|
219
219
|
"name": "no-show",
|
|
220
220
|
"conditionalOn": "goal.bookingNeeded == true"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"ref": "tag.review_ask",
|
|
224
|
+
"name": "review-ask"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"ref": "tag.review_asked",
|
|
228
|
+
"name": "review-asked"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"ref": "tag.quote_sent",
|
|
232
|
+
"name": "quote-sent"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"ref": "tag.quote_open",
|
|
236
|
+
"name": "quote-open"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"ref": "tag.quote_no_reply",
|
|
240
|
+
"name": "quote-no-reply"
|
|
221
241
|
}
|
|
222
242
|
],
|
|
223
243
|
"_tagNote": "The skill derives interest-<x> tags from offer.summary at fill time and adds them here, mirroring the What They Need field options. Not pre-declared because they are business-specific.",
|
|
@@ -247,6 +267,12 @@
|
|
|
247
267
|
"value": "",
|
|
248
268
|
"filledBy": "handoff.calendar_oauth",
|
|
249
269
|
"conditionalOn": "goal.bookingNeeded == true"
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"ref": "cv.review_link",
|
|
273
|
+
"name": "review_link",
|
|
274
|
+
"value": "",
|
|
275
|
+
"filledBy": "handoff.review_link"
|
|
250
276
|
}
|
|
251
277
|
],
|
|
252
278
|
"calendars": [
|
|
@@ -255,7 +281,7 @@
|
|
|
255
281
|
"conditionalOn": "goal.bookingNeeded == true",
|
|
256
282
|
"name": "{{business.name}} Consultation || Consultation",
|
|
257
283
|
"calendarType": "round_robin",
|
|
258
|
-
"_slotDuration": "Carry the appointment length from the brief (brief.calendars[].durationMinutes, or the words in the calendar answer: \"15 minutes\"
|
|
284
|
+
"_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).",
|
|
259
285
|
"slotDuration": 30,
|
|
260
286
|
"slotDurationUnit": "mins",
|
|
261
287
|
"teamMemberRefs": [
|
|
@@ -281,7 +307,6 @@
|
|
|
281
307
|
}
|
|
282
308
|
],
|
|
283
309
|
"availabilityType": 0,
|
|
284
|
-
"slotDuration": 30,
|
|
285
310
|
"slotBuffer": 10,
|
|
286
311
|
"requiresStaff": true,
|
|
287
312
|
"notes": "Default Mon-Fri 9-5; operator edits after build. teamMemberRefs points at the plan users who take appointments; with no staff in the brief it is emptied and handoff.assign_calendar_staff applies."
|
|
@@ -412,6 +437,24 @@
|
|
|
412
437
|
"name": "No-Show 2 - Still Want This?",
|
|
413
438
|
"subject": "Still want to do this?",
|
|
414
439
|
"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 sorted, the calendar is open.</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>"
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
"ref": "email_template.r_email_1",
|
|
443
|
+
"name": "Review Request - Email",
|
|
444
|
+
"subject": "A minute of your time, {{contact.first_name}}?",
|
|
445
|
+
"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>"
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"ref": "email_template.q_email_1",
|
|
449
|
+
"name": "Quote Follow-up - Email 1",
|
|
450
|
+
"subject": "Your quote from {{custom_values.business_name}}",
|
|
451
|
+
"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;\">A couple of days ago we sent over the quote for the work you asked about. I wanted to check it landed and that it made sense.</p><p style=\"margin:0 0 14px;\">Two things people usually ask at this point: what is included and what happens if something unexpected turns up. If either is on your mind, reply and I will answer plainly.</p><p style=\"margin:0 0 14px;\">If you are comparing options, that is fine too. Tell me what you are weighing and I will tell you honestly where we stand.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"ref": "email_template.q_email_2",
|
|
455
|
+
"name": "Quote Follow-up - Email 2",
|
|
456
|
+
"subject": "Last note on the quote, {{contact.first_name}}",
|
|
457
|
+
"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 note from me on the quote for the work you asked about. I would rather ask once more than assume.</p><p style=\"margin:0 0 14px;\">If the timing is off, tell me when would suit and I will hold the price. If it is a no, a one-word reply is welcome and I will stop here.</p><p style=\"margin:0 0 14px;\">Either way, thank you 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>"
|
|
415
458
|
}
|
|
416
459
|
],
|
|
417
460
|
"sms": [
|
|
@@ -499,6 +542,26 @@
|
|
|
499
542
|
"ref": "sms_template.ns_sms_2",
|
|
500
543
|
"name": "No-Show Text 2",
|
|
501
544
|
"body": "{{contact.first_name}}, {{custom_values.owner_first_name}} here. I kept a couple of times open for you this week. Want one? Reply with a day that works."
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
"ref": "sms_template.r_sms_1",
|
|
548
|
+
"name": "Review Request - Text 1",
|
|
549
|
+
"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."
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
"ref": "sms_template.r_sms_2",
|
|
553
|
+
"name": "Review Request - Text 2",
|
|
554
|
+
"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."
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
"ref": "sms_template.q_sms_1",
|
|
558
|
+
"name": "Quote Follow-up - Text 1",
|
|
559
|
+
"body": "Hi {{contact.first_name}}, it's {{custom_values.owner_first_name}} at {{custom_values.business_name}}. Did the quote come through okay? If anything in it needs explaining, reply here and I'll walk you through it. Reply STOP to opt out."
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
"ref": "sms_template.q_sms_2",
|
|
563
|
+
"name": "Quote Follow-up - Text 2",
|
|
564
|
+
"body": "Hi {{contact.first_name}}, {{custom_values.owner_first_name}} again. No pressure on the quote; I just don't want it to sit if you had a question. Is timing, price, or something else the sticking point? Reply STOP to opt out."
|
|
502
565
|
}
|
|
503
566
|
]
|
|
504
567
|
},
|
|
@@ -713,6 +776,46 @@
|
|
|
713
776
|
"custom_values.owner_first_name",
|
|
714
777
|
"custom_values.business_phone"
|
|
715
778
|
]
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
"ref": "email.r_email_1",
|
|
782
|
+
"name": "Review Request - Email",
|
|
783
|
+
"subject": "A minute of your time, {{contact.first_name}}?",
|
|
784
|
+
"templateRef": "email_template.r_email_1",
|
|
785
|
+
"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.",
|
|
786
|
+
"mergeTags": [
|
|
787
|
+
"contact.first_name",
|
|
788
|
+
"custom_values.business_name",
|
|
789
|
+
"custom_values.review_link",
|
|
790
|
+
"custom_values.owner_first_name",
|
|
791
|
+
"custom_values.business_phone"
|
|
792
|
+
]
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
"ref": "email.q_email_1",
|
|
796
|
+
"name": "Quote Follow-up - Email 1",
|
|
797
|
+
"subject": "Your quote from {{custom_values.business_name}}",
|
|
798
|
+
"templateRef": "email_template.q_email_1",
|
|
799
|
+
"copyDirection": "Day three. Check it landed, answer the two usual questions before they are asked, welcome comparison. Tone: brief.voice.threeWords.",
|
|
800
|
+
"mergeTags": [
|
|
801
|
+
"contact.first_name",
|
|
802
|
+
"custom_values.business_name",
|
|
803
|
+
"custom_values.owner_first_name",
|
|
804
|
+
"custom_values.business_phone"
|
|
805
|
+
]
|
|
806
|
+
},
|
|
807
|
+
{
|
|
808
|
+
"ref": "email.q_email_2",
|
|
809
|
+
"name": "Quote Follow-up - Email 2",
|
|
810
|
+
"subject": "Last note on the quote, {{contact.first_name}}",
|
|
811
|
+
"templateRef": "email_template.q_email_2",
|
|
812
|
+
"copyDirection": "Day ten, the last one. Say it is the last, offer to hold the price for a better time, make a no easy.",
|
|
813
|
+
"mergeTags": [
|
|
814
|
+
"contact.first_name",
|
|
815
|
+
"custom_values.business_name",
|
|
816
|
+
"custom_values.owner_first_name",
|
|
817
|
+
"custom_values.business_phone"
|
|
818
|
+
]
|
|
716
819
|
}
|
|
717
820
|
],
|
|
718
821
|
"sms": [
|
|
@@ -906,6 +1009,54 @@
|
|
|
906
1009
|
"custom_values.owner_first_name"
|
|
907
1010
|
],
|
|
908
1011
|
"conditionalOn": "channels.sms == true"
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
"ref": "sms.r_sms_1",
|
|
1015
|
+
"name": "Review Request - Text 1",
|
|
1016
|
+
"templateRef": "sms_template.r_sms_1",
|
|
1017
|
+
"copyDirection": "Two hours after the tag. Thank them, one plain ask, the link, STOP line. No pressure, no incentive (Google forbids it).",
|
|
1018
|
+
"mergeTags": [
|
|
1019
|
+
"contact.first_name",
|
|
1020
|
+
"custom_values.owner_first_name",
|
|
1021
|
+
"custom_values.business_name",
|
|
1022
|
+
"custom_values.review_link"
|
|
1023
|
+
],
|
|
1024
|
+
"conditionalOn": "channels.sms == true"
|
|
1025
|
+
},
|
|
1026
|
+
{
|
|
1027
|
+
"ref": "sms.r_sms_2",
|
|
1028
|
+
"name": "Review Request - Text 2",
|
|
1029
|
+
"templateRef": "sms_template.r_sms_2",
|
|
1030
|
+
"copyDirection": "A week later, the last nudge. Say it is the last one. Link, thanks either way, STOP line.",
|
|
1031
|
+
"mergeTags": [
|
|
1032
|
+
"contact.first_name",
|
|
1033
|
+
"custom_values.owner_first_name",
|
|
1034
|
+
"custom_values.review_link"
|
|
1035
|
+
],
|
|
1036
|
+
"conditionalOn": "channels.sms == true"
|
|
1037
|
+
},
|
|
1038
|
+
{
|
|
1039
|
+
"ref": "sms.q_sms_1",
|
|
1040
|
+
"name": "Quote Follow-up - Text 1",
|
|
1041
|
+
"templateRef": "sms_template.q_sms_1",
|
|
1042
|
+
"copyDirection": "One day after the tag. Did it arrive, does anything need explaining. Warm, short, STOP line.",
|
|
1043
|
+
"mergeTags": [
|
|
1044
|
+
"contact.first_name",
|
|
1045
|
+
"custom_values.owner_first_name",
|
|
1046
|
+
"custom_values.business_name"
|
|
1047
|
+
],
|
|
1048
|
+
"conditionalOn": "channels.sms == true"
|
|
1049
|
+
},
|
|
1050
|
+
{
|
|
1051
|
+
"ref": "sms.q_sms_2",
|
|
1052
|
+
"name": "Quote Follow-up - Text 2",
|
|
1053
|
+
"templateRef": "sms_template.q_sms_2",
|
|
1054
|
+
"copyDirection": "Day six. Name the three usual sticking points (timing, price, something else) and ask which. STOP line.",
|
|
1055
|
+
"mergeTags": [
|
|
1056
|
+
"contact.first_name",
|
|
1057
|
+
"custom_values.owner_first_name"
|
|
1058
|
+
],
|
|
1059
|
+
"conditionalOn": "channels.sms == true"
|
|
909
1060
|
}
|
|
910
1061
|
],
|
|
911
1062
|
"workflows": [
|
|
@@ -1503,6 +1654,132 @@
|
|
|
1503
1654
|
}
|
|
1504
1655
|
],
|
|
1505
1656
|
"conditionalOn": "goal.bookingNeeded == true"
|
|
1657
|
+
},
|
|
1658
|
+
{
|
|
1659
|
+
"ref": "workflow.review_request",
|
|
1660
|
+
"name": "Review Requests",
|
|
1661
|
+
"trigger": {
|
|
1662
|
+
"type": "contact_tag",
|
|
1663
|
+
"tagRef": "tag.review_ask"
|
|
1664
|
+
},
|
|
1665
|
+
"stopOnResponse": true,
|
|
1666
|
+
"_design": "Starts from the review-ask tag, applied when the work is done (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.",
|
|
1667
|
+
"actions": [
|
|
1668
|
+
{
|
|
1669
|
+
"type": "remove_contact_tag",
|
|
1670
|
+
"tagRef": "tag.review_ask"
|
|
1671
|
+
},
|
|
1672
|
+
{
|
|
1673
|
+
"type": "wait",
|
|
1674
|
+
"value": 2,
|
|
1675
|
+
"unit": "hours"
|
|
1676
|
+
},
|
|
1677
|
+
{
|
|
1678
|
+
"type": "send_sms",
|
|
1679
|
+
"smsRef": "sms.r_sms_1",
|
|
1680
|
+
"conditionalOn": "channels.sms == true"
|
|
1681
|
+
},
|
|
1682
|
+
{
|
|
1683
|
+
"type": "wait",
|
|
1684
|
+
"value": 3,
|
|
1685
|
+
"unit": "days"
|
|
1686
|
+
},
|
|
1687
|
+
{
|
|
1688
|
+
"type": "send_email",
|
|
1689
|
+
"emailRef": "email.r_email_1"
|
|
1690
|
+
},
|
|
1691
|
+
{
|
|
1692
|
+
"type": "wait",
|
|
1693
|
+
"value": 4,
|
|
1694
|
+
"unit": "days"
|
|
1695
|
+
},
|
|
1696
|
+
{
|
|
1697
|
+
"type": "send_sms",
|
|
1698
|
+
"smsRef": "sms.r_sms_2",
|
|
1699
|
+
"conditionalOn": "channels.sms == true"
|
|
1700
|
+
},
|
|
1701
|
+
{
|
|
1702
|
+
"type": "add_contact_tag",
|
|
1703
|
+
"tagRef": "tag.review_asked"
|
|
1704
|
+
}
|
|
1705
|
+
]
|
|
1706
|
+
},
|
|
1707
|
+
{
|
|
1708
|
+
"ref": "workflow.quote_follow_up",
|
|
1709
|
+
"name": "Quote Follow-up",
|
|
1710
|
+
"trigger": {
|
|
1711
|
+
"type": "contact_tag",
|
|
1712
|
+
"tagRef": "tag.quote_sent"
|
|
1713
|
+
},
|
|
1714
|
+
"stopOnResponse": true,
|
|
1715
|
+
"_design": "Starts from the quote-sent tag, applied when a quote goes out (by hand, from a quoting tool, or from a pipeline stage). Four touches over ten days plus one call task, each asking one thing. Any reply stops it. Ends by tagging quote-no-reply so the list of unanswered quotes is one filter away.",
|
|
1716
|
+
"actions": [
|
|
1717
|
+
{
|
|
1718
|
+
"type": "remove_contact_tag",
|
|
1719
|
+
"tagRef": "tag.quote_sent"
|
|
1720
|
+
},
|
|
1721
|
+
{
|
|
1722
|
+
"type": "add_contact_tag",
|
|
1723
|
+
"tagRef": "tag.quote_open"
|
|
1724
|
+
},
|
|
1725
|
+
{
|
|
1726
|
+
"type": "wait",
|
|
1727
|
+
"value": 1,
|
|
1728
|
+
"unit": "days"
|
|
1729
|
+
},
|
|
1730
|
+
{
|
|
1731
|
+
"type": "send_sms",
|
|
1732
|
+
"smsRef": "sms.q_sms_1",
|
|
1733
|
+
"conditionalOn": "channels.sms == true"
|
|
1734
|
+
},
|
|
1735
|
+
{
|
|
1736
|
+
"type": "wait",
|
|
1737
|
+
"value": 2,
|
|
1738
|
+
"unit": "days"
|
|
1739
|
+
},
|
|
1740
|
+
{
|
|
1741
|
+
"type": "send_email",
|
|
1742
|
+
"emailRef": "email.q_email_1"
|
|
1743
|
+
},
|
|
1744
|
+
{
|
|
1745
|
+
"type": "wait",
|
|
1746
|
+
"value": 3,
|
|
1747
|
+
"unit": "days"
|
|
1748
|
+
},
|
|
1749
|
+
{
|
|
1750
|
+
"type": "send_sms",
|
|
1751
|
+
"smsRef": "sms.q_sms_2",
|
|
1752
|
+
"conditionalOn": "channels.sms == true"
|
|
1753
|
+
},
|
|
1754
|
+
{
|
|
1755
|
+
"type": "task_notification",
|
|
1756
|
+
"userRef": "user.owner",
|
|
1757
|
+
"title": "Call {{contact.first_name}} about the quote",
|
|
1758
|
+
"body": "The quote went out six days ago with no reply to two texts and an email. One call now usually settles it.",
|
|
1759
|
+
"dueDate": "1"
|
|
1760
|
+
},
|
|
1761
|
+
{
|
|
1762
|
+
"type": "wait",
|
|
1763
|
+
"value": 4,
|
|
1764
|
+
"unit": "days"
|
|
1765
|
+
},
|
|
1766
|
+
{
|
|
1767
|
+
"type": "send_email",
|
|
1768
|
+
"emailRef": "email.q_email_2"
|
|
1769
|
+
},
|
|
1770
|
+
{
|
|
1771
|
+
"type": "add_notes",
|
|
1772
|
+
"body": "Quote follow-up finished with no reply: 4 touches and a call task over 10 days. Tagged quote-no-reply."
|
|
1773
|
+
},
|
|
1774
|
+
{
|
|
1775
|
+
"type": "remove_contact_tag",
|
|
1776
|
+
"tagRef": "tag.quote_open"
|
|
1777
|
+
},
|
|
1778
|
+
{
|
|
1779
|
+
"type": "add_contact_tag",
|
|
1780
|
+
"tagRef": "tag.quote_no_reply"
|
|
1781
|
+
}
|
|
1782
|
+
]
|
|
1506
1783
|
}
|
|
1507
1784
|
],
|
|
1508
1785
|
"handoffs": [
|
|
@@ -1520,7 +1797,8 @@
|
|
|
1520
1797
|
"workflow.reply_route",
|
|
1521
1798
|
"workflow.appointment_booked",
|
|
1522
1799
|
"workflow.no_show",
|
|
1523
|
-
"workflow.missed_call"
|
|
1800
|
+
"workflow.missed_call",
|
|
1801
|
+
"workflow.quote_follow_up"
|
|
1524
1802
|
],
|
|
1525
1803
|
"_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."
|
|
1526
1804
|
},
|
|
@@ -1614,7 +1892,13 @@
|
|
|
1614
1892
|
"sms.appt_24h_sms",
|
|
1615
1893
|
"sms.appt_2h_sms",
|
|
1616
1894
|
"sms.ns_sms_1",
|
|
1617
|
-
"sms.ns_sms_2"
|
|
1895
|
+
"sms.ns_sms_2",
|
|
1896
|
+
"workflow.review_request",
|
|
1897
|
+
"sms.r_sms_1",
|
|
1898
|
+
"sms.r_sms_2",
|
|
1899
|
+
"workflow.quote_follow_up",
|
|
1900
|
+
"sms.q_sms_1",
|
|
1901
|
+
"sms.q_sms_2"
|
|
1618
1902
|
],
|
|
1619
1903
|
"_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."
|
|
1620
1904
|
},
|
|
@@ -1655,6 +1939,28 @@
|
|
|
1655
1939
|
"email.ns_email_1",
|
|
1656
1940
|
"email.ns_email_2"
|
|
1657
1941
|
]
|
|
1942
|
+
},
|
|
1943
|
+
{
|
|
1944
|
+
"ref": "handoff.review_link",
|
|
1945
|
+
"owner": "OPERATOR-UI",
|
|
1946
|
+
"title": "Paste your Google review link, then tag finished work review-ask",
|
|
1947
|
+
"trigger": "always",
|
|
1948
|
+
"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 the work is done (or automate it from the stage you use for finished work); the requests start from the tag and stop the moment they reply.",
|
|
1949
|
+
"produces": "cv.review_link",
|
|
1950
|
+
"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",
|
|
1951
|
+
"blocks": [
|
|
1952
|
+
"cv.review_link"
|
|
1953
|
+
]
|
|
1954
|
+
},
|
|
1955
|
+
{
|
|
1956
|
+
"ref": "handoff.quote_tag",
|
|
1957
|
+
"owner": "OPERATOR-UI",
|
|
1958
|
+
"title": "Tag a contact quote-sent when a quote goes out (starts the follow-up)",
|
|
1959
|
+
"trigger": "always",
|
|
1960
|
+
"instruction": "When a quote goes out, add the tag quote-sent to the contact, by hand or automated from your quoting tool or a pipeline stage. The follow-up starts from the tag, asks one thing per touch, and stops the moment they reply.",
|
|
1961
|
+
"produces": null,
|
|
1962
|
+
"successCheck": "A test contact tagged quote-sent receives the first text one day later",
|
|
1963
|
+
"blocks": []
|
|
1658
1964
|
}
|
|
1659
1965
|
]
|
|
1660
1966
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Preset: Local Service
|
|
2
2
|
|
|
3
|
-
**File:** `local-service.preset.json` · **id:** `local_service` · **version:** 2.
|
|
3
|
+
**File:** `local-service.preset.json` · **id:** `local_service` · **version:** 2.1.0 · **default:** no
|
|
4
4
|
**Source:** Built from the intake industry pack "local-service" (service_area, estimate_flow, emergency_service) and the missed-call text-back pattern; v2 depth per the owner review of 2026-08-26.
|
|
5
5
|
|
|
6
6
|
## When it is selected
|
|
@@ -28,6 +28,8 @@ Routes from the "Local service" business type (and home services / contractor /
|
|
|
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
|
| Estimate Booked - Confirm & Move | appointment (confirmed) | 8 | 2 | instant | no |
|
|
32
34
|
| Estimate Reminders | appointment (confirmed) | 5 | 3 | instant | no |
|
|
33
35
|
| No-Show Rescue | appointment (noshow) | 14 | 4 | 7 days | yes |
|
|
@@ -39,6 +41,13 @@ Routes from the "Local service" business type (and home services / contractor /
|
|
|
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
|
- **Estimate Visit → 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
|
|
|
@@ -56,3 +65,7 @@ Every hand-off is `add_contact_tag` + a `contact_tag` trigger. Both halves are l
|
|
|
56
65
|
|
|
57
66
|
## Copy notes
|
|
58
67
|
Built for a lead who is comparing three quotes on their phone. The instant text asks the only question that matters first (is it urgent?), the second asks for a photo, and every email answers a comparison question: what a written quote from us includes, why the cheapest quote costs more, the three questions to ask any contractor, what a small problem turns into. Win-back is seasonal (maintenance before the season turns). No before/after claims unless the brief supplies real ones.
|
|
68
|
+
|
|
69
|
+
## v2.1.0 (2026-09-15)
|
|
70
|
+
|
|
71
|
+
Two workflows the Assessment prices and no preset built: **Quote Follow-up** (starts from the `quote-sent` tag; text next day, email day 3, last text day 5, then a call task for the owner and the `quote-stale` tag) and **Review Request** (starts from the `service-complete` tag, never from a consult or estimate; text at two hours with the `review_link` custom value, email three days later). Held DRAFT behind the A2P and phone-number handoffs like every other text-bearing workflow (Quote Follow-up also behind staff, for its call task); their emails wait on the sending-domain handoff.
|