@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.
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "presetId": "med_spa",
3
- "presetVersion": "2.0.0",
3
+ "presetVersion": "2.1.0",
4
4
  "schemaVersion": "0.1",
5
5
  "title": "Med Spa",
6
- "description": "The default GHL Command Blueprint reference preset, v2 depth. A med-spa lead-to-member system: Patient Journey pipeline, lead-source / service-interest / appointment fields, source + lifecycle + interest tags, a round-robin consult calendar, an A2P-compliant intake form, 15 email + 17 SMS send-ready templates, and 8 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), Consult Booked - Confirm & Move, Consult Reminders, No-Show Rescue. Staff alerts and call tasks on every workflow that needs a human. SMS-bearing workflows stay DRAFT behind the A2P handoff.",
6
+ "description": "The default GHL Command Blueprint reference preset, v2 depth. A med-spa lead-to-member system: Patient Journey pipeline, lead-source / service-interest / appointment fields, source + lifecycle + interest tags, a round-robin consult calendar, an A2P-compliant intake form, 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), Consult Booked - Confirm & Move, Consult Reminders, No-Show Rescue. Staff alerts and call tasks on every workflow that needs a human. SMS-bearing workflows stay DRAFT behind the A2P handoff, plus Quote Follow-up and Review Request (v2.1.0).",
7
7
  "default": true,
8
8
  "selectors": {
9
9
  "businessTypes": [
@@ -243,6 +243,26 @@
243
243
  {
244
244
  "ref": "tag.interest_membership",
245
245
  "name": "interest-membership"
246
+ },
247
+ {
248
+ "ref": "tag.quote_sent",
249
+ "name": "quote-sent",
250
+ "_note": "Added when a quote goes out. Starts Quote Follow-up; removed by it so a later quote can start it again."
251
+ },
252
+ {
253
+ "ref": "tag.quote_stale",
254
+ "name": "quote-stale",
255
+ "_note": "A quote that got no answer through the whole follow-up."
256
+ },
257
+ {
258
+ "ref": "tag.review_requested",
259
+ "name": "review-requested",
260
+ "_note": "A review was asked for after a completed appointment."
261
+ },
262
+ {
263
+ "ref": "tag.service_done",
264
+ "name": "service-complete",
265
+ "_note": "Added when the work is done and paid for. Starts Review Request; removed by it so the next job can start it again."
246
266
  }
247
267
  ],
248
268
  "_tagNote": "The skill derives interest-<x> tags from offer.summary at fill time (injectables / filler / facials / membership for a med spa) and mirrors them onto the Service Interest field options. Declared here so they are reviewable.",
@@ -272,6 +292,13 @@
272
292
  "value": "",
273
293
  "filledBy": "handoff.calendar_oauth",
274
294
  "conditionalOn": "goal.bookingNeeded == true"
295
+ },
296
+ {
297
+ "ref": "cv.review_link",
298
+ "name": "review_link",
299
+ "value": "",
300
+ "filledBy": "handoff.review_link",
301
+ "_fill": "the Google review link; blank until the operator pastes it"
275
302
  }
276
303
  ],
277
304
  "calendars": [
@@ -280,7 +307,7 @@
280
307
  "conditionalOn": "goal.bookingNeeded == true",
281
308
  "name": "{{business.name}} Consultation || Consultation",
282
309
  "calendarType": "round_robin",
283
- "_slotDuration": "Carry the appointment length from the brief (brief.calendars[].durationMinutes, or the words in the calendar answer: \"15 minutes\" \u2192 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).",
310
+ "_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).",
284
311
  "slotDuration": 30,
285
312
  "slotDurationUnit": "mins",
286
313
  "teamMemberRefs": [
@@ -306,7 +333,6 @@
306
333
  }
307
334
  ],
308
335
  "availabilityType": 0,
309
- "slotDuration": 30,
310
336
  "slotBuffer": 10,
311
337
  "requiresStaff": true,
312
338
  "notes": "Default Mon-Fri 9-5 from business.hours; operator edits after build. teamMemberRefs points at the plan users who take consults (user.owner by default); with no staff in the brief it is emptied and handoff.assign_calendar_staff applies."
@@ -437,6 +463,18 @@
437
463
  "name": "No-Show 2 - Still Want This?",
438
464
  "subject": "Still want to do this?",
439
465
  "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 visit is still free.</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>"
466
+ },
467
+ {
468
+ "ref": "email_template.quote_email_1",
469
+ "name": "Quote Follow-up - Day 3 Email",
470
+ "subject": "Any questions on your quote, {{contact.first_name}}?",
471
+ "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 quote 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>"
472
+ },
473
+ {
474
+ "ref": "email_template.review_email_1",
475
+ "name": "Review Request - Day 3 Email",
476
+ "subject": "One minute for a review, {{contact.first_name}}?",
477
+ "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 appointment 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>"
440
478
  }
441
479
  ],
442
480
  "sms": [
@@ -524,6 +562,21 @@
524
562
  "ref": "sms_template.ns_sms_2",
525
563
  "name": "No-Show Text 2",
526
564
  "body": "{{contact.first_name}}, {{custom_values.owner_first_name}} here. I kept a couple of consult times open for you this week. Want one? Reply with a day that works."
565
+ },
566
+ {
567
+ "ref": "sms_template.quote_sms_1",
568
+ "name": "Quote Follow-up - Next Day Text",
569
+ "body": "Hi {{contact.first_name}}, {{custom_values.owner_first_name}} at {{custom_values.business_name}}. Did the quote make sense? Happy to walk through any part of it. Reply here or call {{custom_values.business_phone}}. Reply STOP to opt out."
570
+ },
571
+ {
572
+ "ref": "sms_template.quote_sms_2",
573
+ "name": "Quote Follow-up - Last Text",
574
+ "body": "Hi {{contact.first_name}}, last note from {{custom_values.business_name}} about your quote. If the timing is off, one word back and I will check in when it suits you. Reply STOP to opt out."
575
+ },
576
+ {
577
+ "ref": "sms_template.review_sms_1",
578
+ "name": "Review Request - Same Day Text",
579
+ "body": "Thanks for coming in today, {{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."
527
580
  }
528
581
  ]
529
582
  },
@@ -738,6 +791,34 @@
738
791
  "custom_values.owner_first_name",
739
792
  "custom_values.business_phone"
740
793
  ]
794
+ },
795
+ {
796
+ "ref": "email.quote_email_1",
797
+ "name": "Quote Follow-up - Day 3 Email",
798
+ "subject": "Any questions on your quote, {{contact.first_name}}?",
799
+ "templateRef": "email_template.quote_email_1",
800
+ "copyDirection": "Day three after the quote. 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.",
801
+ "mergeTags": [
802
+ "contact.first_name",
803
+ "custom_values.business_name",
804
+ "custom_values.booking_link",
805
+ "custom_values.owner_first_name",
806
+ "custom_values.business_phone"
807
+ ]
808
+ },
809
+ {
810
+ "ref": "email.review_email_1",
811
+ "name": "Review Request - Day 3 Email",
812
+ "subject": "One minute for a review, {{contact.first_name}}?",
813
+ "templateRef": "email_template.review_email_1",
814
+ "copyDirection": "Three days after a completed appointment 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.",
815
+ "mergeTags": [
816
+ "contact.first_name",
817
+ "custom_values.business_name",
818
+ "custom_values.review_link",
819
+ "custom_values.owner_first_name",
820
+ "custom_values.business_phone"
821
+ ]
741
822
  }
742
823
  ],
743
824
  "sms": [
@@ -931,6 +1012,41 @@
931
1012
  "custom_values.owner_first_name"
932
1013
  ],
933
1014
  "conditionalOn": "channels.sms == true"
1015
+ },
1016
+ {
1017
+ "ref": "sms.quote_sms_1",
1018
+ "name": "Quote Follow-up - Next Day Text",
1019
+ "templateRef": "sms_template.quote_sms_1",
1020
+ "copyDirection": "One day after the quote went out. Owner's first name and business, one question: did it make sense. Offer to walk through it, reply or call. STOP line.",
1021
+ "mergeTags": [
1022
+ "contact.first_name",
1023
+ "custom_values.owner_first_name",
1024
+ "custom_values.business_name",
1025
+ "custom_values.business_phone"
1026
+ ],
1027
+ "conditionalOn": "channels.sms == true"
1028
+ },
1029
+ {
1030
+ "ref": "sms.quote_sms_2",
1031
+ "name": "Quote Follow-up - Last Text",
1032
+ "templateRef": "sms_template.quote_sms_2",
1033
+ "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.",
1034
+ "mergeTags": [
1035
+ "contact.first_name",
1036
+ "custom_values.business_name"
1037
+ ],
1038
+ "conditionalOn": "channels.sms == true"
1039
+ },
1040
+ {
1041
+ "ref": "sms.review_sms_1",
1042
+ "name": "Review Request - Same Day Text",
1043
+ "templateRef": "sms_template.review_sms_1",
1044
+ "copyDirection": "Two hours after the service-complete tag, i.e. a finished and paid appointment. Thank them, one sentence on why a review helps, the review link. STOP line.",
1045
+ "mergeTags": [
1046
+ "contact.first_name",
1047
+ "custom_values.review_link"
1048
+ ],
1049
+ "conditionalOn": "channels.sms == true"
934
1050
  }
935
1051
  ],
936
1052
  "workflows": [
@@ -1528,6 +1644,106 @@
1528
1644
  }
1529
1645
  ],
1530
1646
  "conditionalOn": "goal.bookingNeeded == true"
1647
+ },
1648
+ {
1649
+ "ref": "workflow.quote_follow_up",
1650
+ "name": "Quote Follow-up",
1651
+ "trigger": {
1652
+ "type": "contact_tag",
1653
+ "tagRef": "tag.quote_sent"
1654
+ },
1655
+ "stopOnResponse": true,
1656
+ "_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 quote 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).",
1657
+ "actions": [
1658
+ {
1659
+ "type": "remove_contact_tag",
1660
+ "tagRef": "tag.quote_sent"
1661
+ },
1662
+ {
1663
+ "type": "wait",
1664
+ "value": 1,
1665
+ "unit": "days"
1666
+ },
1667
+ {
1668
+ "type": "send_sms",
1669
+ "smsRef": "sms.quote_sms_1",
1670
+ "conditionalOn": "channels.sms == true"
1671
+ },
1672
+ {
1673
+ "type": "wait",
1674
+ "value": 2,
1675
+ "unit": "days"
1676
+ },
1677
+ {
1678
+ "type": "send_email",
1679
+ "emailRef": "email.quote_email_1"
1680
+ },
1681
+ {
1682
+ "type": "wait",
1683
+ "value": 2,
1684
+ "unit": "days"
1685
+ },
1686
+ {
1687
+ "type": "send_sms",
1688
+ "smsRef": "sms.quote_sms_2",
1689
+ "conditionalOn": "channels.sms == true"
1690
+ },
1691
+ {
1692
+ "type": "wait",
1693
+ "value": 2,
1694
+ "unit": "days"
1695
+ },
1696
+ {
1697
+ "type": "task_notification",
1698
+ "userRef": "user.owner",
1699
+ "title": "Call {{contact.first_name}} about their quote",
1700
+ "body": "No reply to the quote in a week. One call, no pressure: what would make this a yes, or when should we check back.",
1701
+ "dueDate": "1"
1702
+ },
1703
+ {
1704
+ "type": "add_contact_tag",
1705
+ "tagRef": "tag.quote_stale"
1706
+ }
1707
+ ]
1708
+ },
1709
+ {
1710
+ "ref": "workflow.review_request",
1711
+ "name": "Review Request",
1712
+ "trigger": {
1713
+ "type": "contact_tag",
1714
+ "tagRef": "tag.service_done"
1715
+ },
1716
+ "stopOnResponse": true,
1717
+ "_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 appointment (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).",
1718
+ "actions": [
1719
+ {
1720
+ "type": "remove_contact_tag",
1721
+ "tagRef": "tag.service_done"
1722
+ },
1723
+ {
1724
+ "type": "add_contact_tag",
1725
+ "tagRef": "tag.review_requested"
1726
+ },
1727
+ {
1728
+ "type": "wait",
1729
+ "value": 2,
1730
+ "unit": "hours"
1731
+ },
1732
+ {
1733
+ "type": "send_sms",
1734
+ "smsRef": "sms.review_sms_1",
1735
+ "conditionalOn": "channels.sms == true"
1736
+ },
1737
+ {
1738
+ "type": "wait",
1739
+ "value": 3,
1740
+ "unit": "days"
1741
+ },
1742
+ {
1743
+ "type": "send_email",
1744
+ "emailRef": "email.review_email_1"
1745
+ }
1746
+ ]
1531
1747
  }
1532
1748
  ],
1533
1749
  "handoffs": [
@@ -1545,7 +1761,8 @@
1545
1761
  "workflow.reply_route",
1546
1762
  "workflow.appointment_booked",
1547
1763
  "workflow.no_show",
1548
- "workflow.missed_call"
1764
+ "workflow.missed_call",
1765
+ "workflow.quote_follow_up"
1549
1766
  ],
1550
1767
  "_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."
1551
1768
  },
@@ -1565,7 +1782,9 @@
1565
1782
  "workflow.win_back",
1566
1783
  "workflow.appointment_booked",
1567
1784
  "workflow.appointment_reminders",
1568
- "workflow.no_show"
1785
+ "workflow.no_show",
1786
+ "workflow.quote_follow_up",
1787
+ "workflow.review_request"
1569
1788
  ]
1570
1789
  },
1571
1790
  {
@@ -1639,7 +1858,9 @@
1639
1858
  "sms.appt_24h_sms",
1640
1859
  "sms.appt_2h_sms",
1641
1860
  "sms.ns_sms_1",
1642
- "sms.ns_sms_2"
1861
+ "sms.ns_sms_2",
1862
+ "workflow.quote_follow_up",
1863
+ "workflow.review_request"
1643
1864
  ],
1644
1865
  "_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."
1645
1866
  },
@@ -1678,8 +1899,38 @@
1678
1899
  "email.appt_confirm_email",
1679
1900
  "email.appt_prep_email",
1680
1901
  "email.ns_email_1",
1681
- "email.ns_email_2"
1902
+ "email.ns_email_2",
1903
+ "email.quote_email_1",
1904
+ "email.review_email_1"
1682
1905
  ]
1906
+ },
1907
+ {
1908
+ "ref": "handoff.review_link",
1909
+ "owner": "OPERATOR-UI",
1910
+ "title": "Paste the Google review link so review requests point somewhere",
1911
+ "trigger": "always (2 minutes)",
1912
+ "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 appointment is marked showed.",
1913
+ "produces": "cv.review_link",
1914
+ "successCheck": "review_link shows a real https link, not a blank",
1915
+ "blocks": [
1916
+ "cv.review_link"
1917
+ ]
1918
+ },
1919
+ {
1920
+ "ref": "handoff.quote_tag",
1921
+ "owner": "OPERATOR-UI",
1922
+ "title": "Start Quote Follow-up by tagging quote-sent when a quote goes out",
1923
+ "trigger": "always (1 minute to read)",
1924
+ "instruction": "Quote Follow-up starts from the tag quote-sent. Add that tag to the contact whenever a quote goes out: by hand on the contact, or, if the quotes 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 quote starts it again.",
1925
+ "successCheck": "A contact tagged quote-sent receives the next-day text"
1926
+ },
1927
+ {
1928
+ "ref": "handoff.review_tag",
1929
+ "owner": "OPERATOR-UI",
1930
+ "title": "Start Review Request by tagging service-complete when the work is done",
1931
+ "trigger": "always (1 minute to read)",
1932
+ "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.",
1933
+ "successCheck": "A contact tagged service-complete receives the review text two hours later"
1683
1934
  }
1684
1935
  ]
1685
1936
  }