@elitedcs/ghl-mcp 3.71.0 → 3.72.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 +70 -2
- package/README.md +4 -4
- package/dist/capture-helper.js +10 -1
- package/dist/index.js +8052 -2156
- package/guide/guide.html +2 -1
- package/package.json +5 -8
- package/skills/blueprint/SKILL.md +2 -0
- package/skills/blueprint/examples/medspa-approval-view.md +58 -53
- package/skills/blueprint/examples/medspa-brief.json +70 -8
- package/skills/blueprint/examples/medspa-build-plan.json +1435 -123
- package/skills/blueprint/examples/medspa-dry-run-report.md +3 -1
- package/skills/blueprint/examples/sample-approval-view.md +20 -61
- package/skills/blueprint/examples/sample-brief.json +95 -7
- package/skills/blueprint/examples/sample-build-plan.json +1448 -119
- package/skills/blueprint/examples/validate-plan.cjs +195 -13
- package/skills/blueprint/presets/clinic.md +60 -0
- package/skills/blueprint/presets/clinic.preset.json +1737 -0
- package/skills/blueprint/presets/coach.md +58 -0
- package/skills/blueprint/presets/coach.preset.json +1723 -0
- package/skills/blueprint/presets/ecommerce.md +54 -0
- package/skills/blueprint/presets/ecommerce.preset.json +1287 -0
- package/skills/blueprint/presets/generic-client.md +49 -27
- package/skills/blueprint/presets/generic-client.preset.json +1552 -122
- package/skills/blueprint/presets/local-service.md +58 -0
- package/skills/blueprint/presets/local-service.preset.json +1733 -0
- package/skills/blueprint/presets/med-spa.md +47 -48
- package/skills/blueprint/presets/med-spa.preset.json +1557 -111
- package/skills/blueprint/references/agency-os-detection.md +1 -1
- package/skills/blueprint/references/brief-schema.md +48 -1
- package/skills/blueprint/references/build-plan-schema.md +66 -5
- package/skills/blueprint/references/copy-guide.md +167 -0
- package/skills/blueprint/references/intake-question-set.md +64 -3
- package/skills/blueprint/references/preset-format.md +97 -51
- package/templates/action-schemas.json +12 -0
- package/templates/clinic-medspa.json +1 -1
- package/skills/blueprint/presets/clinic-launch-a2p.md +0 -39
- package/skills/blueprint/presets/clinic-launch-a2p.preset.json +0 -337
|
@@ -0,0 +1,1287 @@
|
|
|
1
|
+
{
|
|
2
|
+
"presetId": "ecom",
|
|
3
|
+
"presetVersion": "2.0.0",
|
|
4
|
+
"schemaVersion": "0.1",
|
|
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 5 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.",
|
|
7
|
+
"default": false,
|
|
8
|
+
"selectors": {
|
|
9
|
+
"businessTypes": [
|
|
10
|
+
"Ecommerce",
|
|
11
|
+
"E-commerce",
|
|
12
|
+
"Online store",
|
|
13
|
+
"Shopify store",
|
|
14
|
+
"DTC brand"
|
|
15
|
+
],
|
|
16
|
+
"aliases": [
|
|
17
|
+
"ecom",
|
|
18
|
+
"ecommerce",
|
|
19
|
+
"e-commerce",
|
|
20
|
+
"online_store",
|
|
21
|
+
"shopify",
|
|
22
|
+
"dtc"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"source": "Built from the intake industry pack \"ecommerce\" (store_platform, aov, abandoned_cart) and the welcome-series pattern; v2 depth per the owner review of 2026-08-26.",
|
|
26
|
+
"conventions": {
|
|
27
|
+
"triggerTokens": "Use ONLY the executor's native trigger types so triggers auto-build: contact_tag (tagRef), form_submission (formRef), appointment (appointmentStatus: confirmed|noshow|...; calendarRef optional), customer_reply, pipeline_stage_updated (pipelineRef+stageRef), call_status (callStatuses + callDirection; the missed-call text-back), inbound_webhook, payment_received. Never tag_added / form_submitted / appointment_status / appointment_booked / contact_replied.",
|
|
28
|
+
"handoffTag": "Sequences hand off with add_contact_tag + a contact_tag trigger (nurture-start, winback-start), NOT add_to_workflow. Both halves of the tag hand-off are live-proven action shapes (the add-tag node and the tag trigger are captured from working GHL UI-built workflows in templates/action-schemas.json); add_to_workflow has no captured native shape in action-schemas.json 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 fire it again.",
|
|
29
|
+
"nurtureSpan": "Lead Nurture waits sum to 31 days (owner rule: nothing under 30 days). Win-back waits sum to 31 days. Speed to Lead must end with the nurture-start hand-off tag. The validator rejects a /nurture/i workflow under 30 days of waits and a /speed/i workflow without a hand-off.",
|
|
30
|
+
"staff": "Every internal_notification, task_notification and assign_user carries userRef. In the skeleton the ref is the ROLE PLACEHOLDER user.owner; the fill step maps it per step from brief.team (notifyName for notifications, callsName for tasks and assignment, each calendar's staffNames for teamMemberRefs; \"the owner\" = the first admin). No staff in the brief → userRef: \"user.__pending__\" on every such step, the step is KEPT, the build reports it as waiting, and handoff.add_staff holds that workflow DRAFT. Never write a literal user id (the legacy `to` / `assignedTo`).",
|
|
31
|
+
"publishDefault": "Workflows build DRAFT. The skill PROMPTS the operator (publish now or leave DRAFT for review?) and only passes publishWorkflows:true on an explicit yes. Workflows gated by an unmet handoff never auto-publish.",
|
|
32
|
+
"a2pGating": "handoff.a2p.blocks MUST list each SMS-bearing WORKFLOW ref (not just sms.* assets); only an explicit workflow.* ref keeps a workflow DRAFT.",
|
|
33
|
+
"copy": "All copy lives in templates.* (email_template.* / sms_template.*) and is COMPLETE. The build stage rewrites every template from the real brief per references/copy-guide.md (five tests: Jab, Value equation, Says-who, Lock-screen, Thumb), in the tone of brief.voice.threeWords, with brief.voice.signatureLine verbatim in the instant email and text, keeps merge fields and the single CTA, and writes the result to the template AND the matching email/sms asset body. An email/sms asset with only copyDirection and no body reports needsContent and will not build.",
|
|
34
|
+
"fortyCap": "Max 40 actions per workflow (a find_opportunity branch counts head + 2 transitions + children). The longest workflow here is Lead Nurture at 28 actions, so no split is needed; if a rewrite adds touches past 40, split into \"(days 1-14)\" and \"(days 15-30)\" with a hand-off tag between them."
|
|
35
|
+
},
|
|
36
|
+
"skeleton": {
|
|
37
|
+
"users": {
|
|
38
|
+
"fillFrom": "team.staff",
|
|
39
|
+
"transform": "userList",
|
|
40
|
+
"default": [],
|
|
41
|
+
"_note": "One plan user per brief.team.staff[] entry: ref user.<slug of name>, firstName/lastName split from name, email verbatim, role admin for the owner / whoever runs the account, else user, phone from mobile. In this skeleton \"user.owner\" is a ROLE PLACEHOLDER, never a real user: the fill step resolves it per step — internal_notification → the user named by brief.team.notifyName; task_notification and assign_user → brief.team.callsName; calendars[].teamMemberRefs → that calendar's staffNames; \"the owner\" / \"me\" → the first admin. If the brief lists nobody, every userRef becomes the sentinel \"user.__pending__\" and the step is KEPT (the build reports it as waiting for a staff member; handoff.add_staff holds that workflow DRAFT)."
|
|
42
|
+
},
|
|
43
|
+
"pipelines": [
|
|
44
|
+
{
|
|
45
|
+
"ref": "pipeline.store_leads",
|
|
46
|
+
"name": "{{business.name}} Store Leads || Store Leads",
|
|
47
|
+
"stages": {
|
|
48
|
+
"fillFrom": "goal.salesStages",
|
|
49
|
+
"transform": "stageList",
|
|
50
|
+
"default": [
|
|
51
|
+
{
|
|
52
|
+
"ref": "stage.new_subscriber",
|
|
53
|
+
"name": "New Subscriber"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"ref": "stage.engaged",
|
|
57
|
+
"name": "Engaged"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"ref": "stage.first_order",
|
|
61
|
+
"name": "First Order"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"ref": "stage.repeat",
|
|
65
|
+
"name": "Repeat Customer"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"ref": "stage.vip",
|
|
69
|
+
"name": "VIP"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"ref": "stage.lapsed",
|
|
73
|
+
"name": "Lapsed"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
"customFields": [
|
|
80
|
+
{
|
|
81
|
+
"ref": "field.lead_source",
|
|
82
|
+
"name": "Lead Source",
|
|
83
|
+
"dataType": "SINGLE_OPTIONS",
|
|
84
|
+
"model": "contact",
|
|
85
|
+
"options": [
|
|
86
|
+
"Website popup",
|
|
87
|
+
"Instagram",
|
|
88
|
+
"TikTok",
|
|
89
|
+
"Facebook",
|
|
90
|
+
"Google",
|
|
91
|
+
"Marketplace",
|
|
92
|
+
"Referral",
|
|
93
|
+
"Other"
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"ref": "field.product_interest",
|
|
98
|
+
"name": "Shopping For",
|
|
99
|
+
"dataType": "MULTIPLE_OPTIONS",
|
|
100
|
+
"model": "contact",
|
|
101
|
+
"options": [
|
|
102
|
+
"Best sellers",
|
|
103
|
+
"New arrivals",
|
|
104
|
+
"A gift",
|
|
105
|
+
"Something specific",
|
|
106
|
+
"Just browsing"
|
|
107
|
+
],
|
|
108
|
+
"_optionsNote": "The skill replaces these with the real categories from offer.summary and mirrors them with interest-* tags."
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"ref": "field.welcome_code_used",
|
|
112
|
+
"name": "Welcome Code Used",
|
|
113
|
+
"dataType": "CHECKBOX",
|
|
114
|
+
"model": "contact",
|
|
115
|
+
"options": [
|
|
116
|
+
"Used"
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"ref": "field.last_order_value",
|
|
121
|
+
"name": "Last Order Value",
|
|
122
|
+
"dataType": "MONETORY",
|
|
123
|
+
"model": "contact"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"ref": "field.last_order_date",
|
|
127
|
+
"name": "Last Order Date",
|
|
128
|
+
"dataType": "DATE",
|
|
129
|
+
"model": "contact"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"ref": "field.ltv",
|
|
133
|
+
"name": "Lifetime Value",
|
|
134
|
+
"dataType": "MONETORY",
|
|
135
|
+
"model": "contact"
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
"tags": [
|
|
139
|
+
{
|
|
140
|
+
"ref": "tag.source_website",
|
|
141
|
+
"name": "source-website"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"ref": "tag.source_instagram",
|
|
145
|
+
"name": "source-instagram"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"ref": "tag.source_facebook",
|
|
149
|
+
"name": "source-facebook"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"ref": "tag.source_google",
|
|
153
|
+
"name": "source-google"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"ref": "tag.source_referral",
|
|
157
|
+
"name": "source-referral"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"ref": "tag.source_phone",
|
|
161
|
+
"name": "source-phone"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"ref": "tag.source_other",
|
|
165
|
+
"name": "source-other"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"ref": "tag.lc_new_lead",
|
|
169
|
+
"name": "lifecycle-new-lead"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"ref": "tag.lc_contacted",
|
|
173
|
+
"name": "lifecycle-contacted"
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"ref": "tag.lc_nurturing",
|
|
177
|
+
"name": "lifecycle-nurturing"
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"ref": "tag.lc_engaged",
|
|
181
|
+
"name": "lifecycle-engaged"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"ref": "tag.lc_first_order",
|
|
185
|
+
"name": "lifecycle-first-order"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"ref": "tag.lc_repeat",
|
|
189
|
+
"name": "lifecycle-repeat"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"ref": "tag.lc_vip",
|
|
193
|
+
"name": "lifecycle-vip"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"ref": "tag.lc_lapsed",
|
|
197
|
+
"name": "lifecycle-lapsed"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"ref": "tag.lc_lost",
|
|
201
|
+
"name": "lifecycle-lost"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"ref": "tag.nurture_start",
|
|
205
|
+
"name": "nurture-start"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"ref": "tag.winback_start",
|
|
209
|
+
"name": "winback-start"
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"ref": "tag.missed_call",
|
|
213
|
+
"name": "missed-call",
|
|
214
|
+
"conditionalOn": "channels.sms == true"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"ref": "tag.interest_best_sellers",
|
|
218
|
+
"name": "interest-best-sellers"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"ref": "tag.interest_new_arrivals",
|
|
222
|
+
"name": "interest-new-arrivals"
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"ref": "tag.interest_gift",
|
|
226
|
+
"name": "interest-gift"
|
|
227
|
+
}
|
|
228
|
+
],
|
|
229
|
+
"_tagNote": "Interest tags mirror the Shopping For options; the skill renames them to the real categories from the offer at fill time.",
|
|
230
|
+
"customValues": [
|
|
231
|
+
{
|
|
232
|
+
"ref": "cv.business_name",
|
|
233
|
+
"name": "business_name",
|
|
234
|
+
"value": "{{business.name}}"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"ref": "cv.business_phone",
|
|
238
|
+
"name": "business_phone",
|
|
239
|
+
"value": "",
|
|
240
|
+
"filledBy": "handoff.business_details",
|
|
241
|
+
"_fill": "the GHL number once one exists (handoff.phone_number), else blank until the operator fills it"
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"ref": "cv.owner_first_name",
|
|
245
|
+
"name": "owner_first_name",
|
|
246
|
+
"value": "",
|
|
247
|
+
"filledBy": "handoff.business_details",
|
|
248
|
+
"_fill": "first name of the user resolved for team.notifyName (the person every message is signed by)"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"ref": "cv.store_link",
|
|
252
|
+
"name": "store_link",
|
|
253
|
+
"value": "{{business.website || }}",
|
|
254
|
+
"filledBy": "handoff.business_details"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"ref": "cv.welcome_code",
|
|
258
|
+
"name": "welcome_code",
|
|
259
|
+
"value": "",
|
|
260
|
+
"filledBy": "handoff.welcome_code"
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"ref": "cv.code_expiry_days",
|
|
264
|
+
"name": "code_expiry_days",
|
|
265
|
+
"value": "14",
|
|
266
|
+
"_note": "The welcome code is valid this many days; copy says \"14 days\" by default and the store discount must match."
|
|
267
|
+
}
|
|
268
|
+
],
|
|
269
|
+
"calendars": [],
|
|
270
|
+
"_calendarsNote": "This preset books nothing; if the brief lists calendars anyway, append them as calendar.<slug> with teamMemberRefs and note that no workflow uses them.",
|
|
271
|
+
"forms": [
|
|
272
|
+
{
|
|
273
|
+
"ref": "form.vip_signup",
|
|
274
|
+
"name": "{{business.name}} VIP List || VIP List Signup",
|
|
275
|
+
"fields": [
|
|
276
|
+
{
|
|
277
|
+
"type": "standard",
|
|
278
|
+
"key": "first_name",
|
|
279
|
+
"required": true
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"type": "standard",
|
|
283
|
+
"key": "email",
|
|
284
|
+
"required": true
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"type": "standard",
|
|
288
|
+
"key": "phone",
|
|
289
|
+
"required": false
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"type": "custom",
|
|
293
|
+
"fieldRef": "field.product_interest",
|
|
294
|
+
"required": false
|
|
295
|
+
}
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
],
|
|
299
|
+
"funnels": [
|
|
300
|
+
{
|
|
301
|
+
"ref": "funnel.main",
|
|
302
|
+
"name": "{{business.name}} VIP Funnel || VIP List Funnel",
|
|
303
|
+
"target": "ghl",
|
|
304
|
+
"pages": [
|
|
305
|
+
{
|
|
306
|
+
"ref": "page.optin",
|
|
307
|
+
"name": "{{offer.leadMagnet}} || Join the VIP List",
|
|
308
|
+
"role": "optin",
|
|
309
|
+
"formRef": "form.vip_signup",
|
|
310
|
+
"copyDirection": "OPTIN page per templates/funnel-page-content-template.md: Hero (H1 = the welcome offer, e.g. \"Your first order, {{custom_values.welcome_code}}\") + what the list gets (first look, real restock alerts, no daily blasts) + GEO quotable summary + 3 outcome-led points about the products + the A2P-compliant capture form with a NOT-pre-checked SMS consent checkbox, legal name + address, Privacy/Terms links + a 4-8 Q FAQ (shipping, returns, code rules) with FAQPage JSON-LD. Reviews only if real."
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"ref": "page.thankyou",
|
|
314
|
+
"name": "Thank You",
|
|
315
|
+
"role": "confirmation",
|
|
316
|
+
"copyDirection": "CONFIRMATION page: show the welcome code big, say it is also on its way by text and email, one button to the store (cv.store_link), the expiry in plain words."
|
|
317
|
+
}
|
|
318
|
+
]
|
|
319
|
+
}
|
|
320
|
+
],
|
|
321
|
+
"templates": {
|
|
322
|
+
"emails": [
|
|
323
|
+
{
|
|
324
|
+
"ref": "email_template.stl_email_1",
|
|
325
|
+
"name": "Speed to Lead - Welcome Code Email",
|
|
326
|
+
"subject": "Your code is inside, {{contact.first_name}}",
|
|
327
|
+
"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;\">Welcome to {{custom_values.business_name}}. Here's your code for your first order:</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;\">{{custom_values.welcome_code}}</a></p><p style=\"margin:0 0 14px;\">It's good for {{custom_values.code_expiry_days}} days, one use, on anything in the store. Tap the code to shop, and paste it at checkout.</p><p style=\"margin:0 0 14px;\">I'm {{custom_values.owner_first_name}}. Being on this list means you hear first about new pieces and real restocks, and it does not mean a daily blast. If it ever feels like too much, reply and say so.</p><p style=\"margin:0 0 14px;\">One question so I send you the right things: what are you shopping for right now? Reply to this email or the text that's on its way, and I'll point you to the exact page.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"ref": "email_template.stl_email_2",
|
|
331
|
+
"name": "Speed to Lead - 3 Hour Email",
|
|
332
|
+
"subject": "How to pick the right one",
|
|
333
|
+
"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;\">The question we get most from new subscribers is \"which one should I start with?\" Here's the honest short version:</p><ul style=\"margin:0 0 14px 20px;padding:0;\"><li style=\"margin:0 0 6px;\">If it's your first time with {{offer.summary || what we make}}: start with the one most people buy first. It's the safest way to find out if you like what we do.</li><li style=\"margin:0 0 6px;\">If you already know what you like: go straight to the category you know; the fit and sizing notes on each page are written by us, not copied from a supplier.</li><li style=\"margin:0 0 6px;\">If it's a gift: the gift note at checkout is free, and we ship without a price on the slip.</li></ul><p style=\"margin:0 0 14px;\">Your code {{custom_values.welcome_code}} works on any of them for the next {{custom_values.code_expiry_days}} days.</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;\">Shop with my code</a></p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"ref": "email_template.n_email_1",
|
|
337
|
+
"name": "Nurture 1 - Why We Make It",
|
|
338
|
+
"subject": "Why we make it this way",
|
|
339
|
+
"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;\">Most people never hear why a brand makes what it makes, so here's ours in a paragraph.</p><p style=\"margin:0 0 14px;\">{{custom_values.business_name}} started because we couldn't find {{offer.summary || what we make}} that did the simple things right: made properly, priced honestly, and backed by someone you can actually reach. That's still the standard. Every product page tells you what it's made of, where, and what to expect, in plain words.</p><p style=\"margin:0 0 14px;\">If that's the kind of brand you like buying from, you're in the right place. If not, no hard feelings; the unsubscribe link works.</p><p style=\"margin:0 0 14px;\">Your code {{custom_values.welcome_code}} is still good. <a href=\"{{custom_values.store_link}}\" style=\"color:#1a56db;text-decoration:underline;\">Take a look when you're ready</a>.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"ref": "email_template.n_email_2",
|
|
343
|
+
"name": "Nurture 2 - What People Buy First",
|
|
344
|
+
"subject": "What people buy first (and why)",
|
|
345
|
+
"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;\">If you're deciding what to try first, here's what most first orders at {{custom_values.business_name}} are, and who each one suits:</p><ul style=\"margin:0 0 14px 20px;padding:0;\"><li style=\"margin:0 0 6px;\">The one most first orders start with: the safe bet if you want to find out what we're about.</li><li style=\"margin:0 0 6px;\">The one people come back for: usually the second order, once they trust the fit and quality.</li><li style=\"margin:0 0 6px;\">The gift pick: the one with the fewest \"will they like it?\" risks.</li></ul><p style=\"margin:0 0 14px;\">The worry we hear most is {{audience.objections[0] || \"what if it doesn't work out?\"}}. Simple answer: shipping and returns are in plain words on every page, and a real person answers the email address if anything goes wrong.</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;\">See the first-order picks</a></p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"ref": "email_template.n_email_3",
|
|
349
|
+
"name": "Nurture 3 - Shipping and Returns, Plainly",
|
|
350
|
+
"subject": "Shipping and returns, in plain words",
|
|
351
|
+
"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;\">Before you order from any small brand, you should know three things. Here are ours:</p><ul style=\"margin:0 0 14px 20px;padding:0;\"><li style=\"margin:0 0 6px;\">Shipping: orders go out on the schedule and at the cost shown at checkout, no surprise fees on the last page.</li><li style=\"margin:0 0 6px;\">Returns: if it isn't right, you can return it within the window on our returns page; the instructions are two steps, not a form.</li><li style=\"margin:0 0 6px;\">Who answers: a person. Reply to any email from us and it lands with someone who can actually fix things.</li></ul><p style=\"margin:0 0 14px;\">That's the whole policy. Nothing hidden in a footer.</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;\">Shop with {{custom_values.welcome_code}}</a></p><p style=\"margin:0 0 14px;\">Have a question about sizing, materials or a specific piece? Reply to this email. I answer these myself.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"ref": "email_template.n_email_4",
|
|
355
|
+
"name": "Nurture 4 - Three Questions Before You Buy",
|
|
356
|
+
"subject": "Three questions to ask any small brand",
|
|
357
|
+
"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;\">Whether you buy from us or someone else, ask these three before you check out anywhere:</p><ul style=\"margin:0 0 14px 20px;padding:0;\"><li style=\"margin:0 0 6px;\">What's it made of, and where? (A specific answer. \"Premium materials\" is not one.)</li><li style=\"margin:0 0 6px;\">What happens if it arrives damaged? (Replacement, no argument, is the right answer.)</li><li style=\"margin:0 0 6px;\">Can I reach a human? (Try it before you buy. Send a question and see who replies.)</li></ul><p style=\"margin:0 0 14px;\">Our answers are on every product page, and the third one you can test right now by replying to this email.</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;\">Browse the store</a></p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
"ref": "email_template.n_email_5",
|
|
361
|
+
"name": "Nurture 5 - Your Code Ends Soon",
|
|
362
|
+
"subject": "Your code ends soon",
|
|
363
|
+
"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: your welcome code {{custom_values.welcome_code}} was set to last {{custom_values.code_expiry_days}} days from the day you joined, and that window is closing.</p><p style=\"margin:0 0 14px;\">Not a marketing trick; the store simply turns it off. After that you're welcome to shop at full price, and you'll still get first look at new pieces, but the first-order code is a one-time thing.</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;\">Use {{custom_values.welcome_code}} before it ends</a></p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"ref": "email_template.n_email_6",
|
|
367
|
+
"name": "Nurture 6 - Everything in One Place",
|
|
368
|
+
"subject": "Everything you need to decide, in one place",
|
|
369
|
+
"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;\">If you're still deciding, here is everything in one place:</p><ul style=\"margin:0 0 14px 20px;padding:0;\"><li style=\"margin:0 0 6px;\">What we make: {{offer.summary || what we make}}, made properly and described honestly.</li><li style=\"margin:0 0 6px;\">Where to start: the first-order picks on the front page.</li><li style=\"margin:0 0 6px;\">Shipping and returns: plain words on every page, no surprise fees, a person who answers.</li><li style=\"margin:0 0 6px;\">The store: <a href=\"{{custom_values.store_link}}\" style=\"color:#1a56db;text-decoration:underline;\">{{custom_values.business_name}}</a>.</li></ul><p style=\"margin:0 0 14px;\">If you'd rather hear from us less, reply with the word less and I'll move you to the new-arrivals-only list.</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 the store</a></p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"ref": "email_template.w_email_1",
|
|
373
|
+
"name": "Win-back 1 - One Question",
|
|
374
|
+
"subject": "One question, {{contact.first_name}}",
|
|
375
|
+
"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 joined the {{custom_values.business_name}} list a while back and haven't ordered. That's fine; plenty of people are on the list for the new-arrivals emails.</p><p style=\"margin:0 0 14px;\">One question, and an honest answer is all I need: what stopped you? Price, couldn't find the right thing, timing, or something we said?</p><p style=\"margin:0 0 14px;\">Reply with a word or two. If it's something I can fix, I'll fix it. If you'd rather just hear about new pieces, say so and that's all you'll get.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"ref": "email_template.w_email_2",
|
|
379
|
+
"name": "Win-back 2 - A Fresh Code",
|
|
380
|
+
"subject": "A fresh code, one more time",
|
|
381
|
+
"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;\">Two things since you last looked at {{custom_values.business_name}}: new pieces on the front page, and a fresh first-order code for people who never used theirs:</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;\">{{custom_values.welcome_code}}</a></p><p style=\"margin:0 0 14px;\">Same rules as before: {{custom_values.code_expiry_days}} days, one use, anything in the store.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
"ref": "email_template.w_email_3",
|
|
385
|
+
"name": "Win-back 3 - We'll Quiet Down",
|
|
386
|
+
"subject": "We'll quiet down now",
|
|
387
|
+
"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>"
|
|
388
|
+
}
|
|
389
|
+
],
|
|
390
|
+
"sms": [
|
|
391
|
+
{
|
|
392
|
+
"ref": "sms_template.stl_sms_1",
|
|
393
|
+
"name": "Speed to Lead - Welcome Code Text",
|
|
394
|
+
"body": "Hi {{contact.first_name}}, it's {{custom_values.business_name}}. Your welcome code is {{custom_values.welcome_code}}, good for {{custom_values.code_expiry_days}} days. What are you shopping for? Reply and I'll point you to the right page. Reply STOP to opt out."
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
"ref": "sms_template.stl_sms_2",
|
|
398
|
+
"name": "Speed to Lead - 20 Minute Text",
|
|
399
|
+
"body": "{{contact.first_name}}, quick one so I send the right things: is this for you or a gift? Store is here when you're ready: {{custom_values.store_link}}"
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"ref": "sms_template.stl_sms_3",
|
|
403
|
+
"name": "Speed to Lead - Next Day Text",
|
|
404
|
+
"body": "Hi {{contact.first_name}}, {{custom_values.owner_first_name}} at {{custom_values.business_name}}. Not chasing, just checking: did you find what you were looking for? If not, tell me what you had in mind and I'll find it."
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
"ref": "sms_template.mc_sms_1",
|
|
408
|
+
"name": "Missed Call - Instant Text-Back",
|
|
409
|
+
"body": "Hi, it's {{custom_values.business_name}}. Sorry we missed your call. Is it about an order, a product, or a return? Reply here and a real person will answer. Reply STOP to opt out."
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"ref": "sms_template.mc_sms_2",
|
|
413
|
+
"name": "Missed Call - 1 Hour Text",
|
|
414
|
+
"body": "Still need us? Reply with your order number or a good time to call you back. {{custom_values.business_name}}, {{custom_values.business_phone}}"
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
"ref": "sms_template.n_sms_1",
|
|
418
|
+
"name": "Nurture Text 1 - One Word",
|
|
419
|
+
"body": "{{contact.first_name}}, quick one from {{custom_values.owner_first_name}} at {{custom_values.business_name}}: best sellers, new arrivals, or a gift? One word and I'll send you the right page. Reply STOP to opt out."
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
"ref": "sms_template.n_sms_2",
|
|
423
|
+
"name": "Nurture Text 2 - Free Tip",
|
|
424
|
+
"body": "Tip from {{custom_values.business_name}}: before you buy {{offer.summary || what we make}} anywhere, read the materials line, not the headline. If it doesn't say what it's made of, that's the answer. Want our short buying checklist? Reply YES."
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
"ref": "sms_template.n_sms_3",
|
|
428
|
+
"name": "Nurture Text 3 - Midpoint",
|
|
429
|
+
"body": "{{contact.first_name}}, it's {{custom_values.owner_first_name}}. Still deciding? I can send you the link to the two things most people start with, or leave you alone for a while. Which?"
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
"ref": "sms_template.n_sms_4",
|
|
433
|
+
"name": "Nurture Text 4 - Any Question",
|
|
434
|
+
"body": "Hi {{contact.first_name}}, {{custom_values.owner_first_name}} here. No pitch, just checking: any question about sizing, materials or shipping I can answer? Ask it here and I'll reply personally."
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"ref": "sms_template.n_sms_5",
|
|
438
|
+
"name": "Nurture Text 5 - Code Ending",
|
|
439
|
+
"body": "{{contact.first_name}}, last one from me at {{custom_values.business_name}}. Your code {{custom_values.welcome_code}} is about to switch off. Use it here if you want it: {{custom_values.store_link}}. Reply STOP to opt out."
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
"ref": "sms_template.w_sms_1",
|
|
443
|
+
"name": "Win-back Text 1",
|
|
444
|
+
"body": "Hi {{contact.first_name}}, it's {{custom_values.owner_first_name}} at {{custom_values.business_name}}. Still interested, or would you rather only hear about new arrivals? Reply 1 for still interested, 2 for new arrivals only. Reply STOP to opt out."
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
"ref": "sms_template.w_sms_2",
|
|
448
|
+
"name": "Win-back Text 2",
|
|
449
|
+
"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}}"
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
},
|
|
453
|
+
"_templatesNote": "Every message is a send-ready template (emails: subject + html; sms: body) written to references/copy-guide.md from this preset's placeholder brief fields. The build stage REWRITES each one from the real brief (offer, audience pain points and objections, price points, lead magnet, follow-up style, voice.threeWords for tone, voice.signatureLine verbatim in the first email and text) keeping the cadence, the single CTA and the merge fields, then writes the result to BOTH the template and the matching email/sms asset body. Never ship an outline-only body. {{contact.*}}, {{custom_values.*}} and {{appointment.*}} are GHL merge fields and pass through the fill untouched; {{offer.*}} / {{audience.*}} / {{business.*}} are preset tokens filled from the brief.",
|
|
454
|
+
"emails": [
|
|
455
|
+
{
|
|
456
|
+
"ref": "email.stl_email_1",
|
|
457
|
+
"name": "Speed to Lead - Welcome Code Email",
|
|
458
|
+
"subject": "Your code is inside, {{contact.first_name}}",
|
|
459
|
+
"templateRef": "email_template.stl_email_1",
|
|
460
|
+
"copyDirection": "Instant. Deliver the code big, say how long it lasts (cv.code_expiry_days), who I am, what the list gets (and does not get), the one-question ask, one CTA to the store. Tone: brief.voice.threeWords. If brief.voice.signatureLine exists, insert it verbatim as its own paragraph right after the greeting.",
|
|
461
|
+
"mergeTags": [
|
|
462
|
+
"contact.first_name",
|
|
463
|
+
"custom_values.business_name",
|
|
464
|
+
"custom_values.store_link",
|
|
465
|
+
"custom_values.welcome_code",
|
|
466
|
+
"custom_values.code_expiry_days",
|
|
467
|
+
"custom_values.owner_first_name",
|
|
468
|
+
"custom_values.business_phone"
|
|
469
|
+
]
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
"ref": "email.stl_email_2",
|
|
473
|
+
"name": "Speed to Lead - 3 Hour Email",
|
|
474
|
+
"subject": "How to pick the right one",
|
|
475
|
+
"templateRef": "email_template.stl_email_2",
|
|
476
|
+
"copyDirection": "Second touch, 3 hours in. A short honest guide to choosing between the main products (from offer.summary / pricePoints), who each is for, the code reminder, one CTA.",
|
|
477
|
+
"mergeTags": [
|
|
478
|
+
"contact.first_name",
|
|
479
|
+
"custom_values.welcome_code",
|
|
480
|
+
"custom_values.code_expiry_days",
|
|
481
|
+
"custom_values.store_link",
|
|
482
|
+
"custom_values.owner_first_name",
|
|
483
|
+
"custom_values.business_name",
|
|
484
|
+
"custom_values.business_phone"
|
|
485
|
+
]
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"ref": "email.n_email_1",
|
|
489
|
+
"name": "Nurture 1 - Why We Make It",
|
|
490
|
+
"subject": "Why we make it this way",
|
|
491
|
+
"templateRef": "email_template.n_email_1",
|
|
492
|
+
"copyDirection": "Day 1 of nurture. The origin and the standard behind the product, from the brief (extended brand DNA if present). If the brief has no story, keep the standard and drop the story paragraph. No fabricated anecdotes. Give, do not pitch.",
|
|
493
|
+
"mergeTags": [
|
|
494
|
+
"contact.first_name",
|
|
495
|
+
"custom_values.business_name",
|
|
496
|
+
"custom_values.welcome_code",
|
|
497
|
+
"custom_values.store_link",
|
|
498
|
+
"custom_values.owner_first_name",
|
|
499
|
+
"custom_values.business_phone"
|
|
500
|
+
]
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"ref": "email.n_email_2",
|
|
504
|
+
"name": "Nurture 2 - What People Buy First",
|
|
505
|
+
"subject": "What people buy first (and why)",
|
|
506
|
+
"templateRef": "email_template.n_email_2",
|
|
507
|
+
"copyDirection": "Day 5. The first-order guide: the two or three products most first orders start with and who each suits, from real store data supplied by the brief. Placeholders if none. Then shipping and returns objection. One CTA.",
|
|
508
|
+
"mergeTags": [
|
|
509
|
+
"contact.first_name",
|
|
510
|
+
"custom_values.business_name",
|
|
511
|
+
"custom_values.store_link",
|
|
512
|
+
"custom_values.owner_first_name",
|
|
513
|
+
"custom_values.business_phone"
|
|
514
|
+
]
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
"ref": "email.n_email_3",
|
|
518
|
+
"name": "Nurture 3 - Shipping and Returns, Plainly",
|
|
519
|
+
"subject": "Shipping and returns, in plain words",
|
|
520
|
+
"templateRef": "email_template.n_email_3",
|
|
521
|
+
"copyDirection": "Day 10. Remove the last unknown: how fast it ships, what it costs, how returns work, who answers. Use the brief facts only; placeholders where the brief is silent. CTA + reply invite.",
|
|
522
|
+
"mergeTags": [
|
|
523
|
+
"contact.first_name",
|
|
524
|
+
"custom_values.store_link",
|
|
525
|
+
"custom_values.welcome_code",
|
|
526
|
+
"custom_values.owner_first_name",
|
|
527
|
+
"custom_values.business_name",
|
|
528
|
+
"custom_values.business_phone"
|
|
529
|
+
]
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
"ref": "email.n_email_4",
|
|
533
|
+
"name": "Nurture 4 - Three Questions Before You Buy",
|
|
534
|
+
"subject": "Three questions to ask any small brand",
|
|
535
|
+
"templateRef": "email_template.n_email_4",
|
|
536
|
+
"copyDirection": "Day 14. Pure value: three questions to ask before buying from any small brand (what is it made of and where, what happens if it arrives damaged, can I reach a human), and our answers. Soft CTA.",
|
|
537
|
+
"mergeTags": [
|
|
538
|
+
"contact.first_name",
|
|
539
|
+
"custom_values.store_link",
|
|
540
|
+
"custom_values.owner_first_name",
|
|
541
|
+
"custom_values.business_name",
|
|
542
|
+
"custom_values.business_phone"
|
|
543
|
+
]
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
"ref": "email.n_email_5",
|
|
547
|
+
"name": "Nurture 5 - Your Code Ends Soon",
|
|
548
|
+
"subject": "Your code ends soon",
|
|
549
|
+
"templateRef": "email_template.n_email_5",
|
|
550
|
+
"copyDirection": "Day 20. Honest urgency: the welcome code expires on the real schedule (cv.code_expiry_days); say when, say what it is worth, one CTA. No fake countdowns.",
|
|
551
|
+
"mergeTags": [
|
|
552
|
+
"contact.first_name",
|
|
553
|
+
"custom_values.welcome_code",
|
|
554
|
+
"custom_values.code_expiry_days",
|
|
555
|
+
"custom_values.store_link",
|
|
556
|
+
"custom_values.owner_first_name",
|
|
557
|
+
"custom_values.business_name",
|
|
558
|
+
"custom_values.business_phone"
|
|
559
|
+
]
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
"ref": "email.n_email_6",
|
|
563
|
+
"name": "Nurture 6 - Everything in One Place",
|
|
564
|
+
"subject": "Everything you need to decide, in one place",
|
|
565
|
+
"templateRef": "email_template.n_email_6",
|
|
566
|
+
"copyDirection": "Day 27. The decision sheet: what we make, what to start with, shipping, returns, who answers, the store link. Offer the \"fewer emails\" out. One CTA.",
|
|
567
|
+
"mergeTags": [
|
|
568
|
+
"contact.first_name",
|
|
569
|
+
"custom_values.store_link",
|
|
570
|
+
"custom_values.business_name",
|
|
571
|
+
"custom_values.owner_first_name",
|
|
572
|
+
"custom_values.business_phone"
|
|
573
|
+
]
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
"ref": "email.w_email_1",
|
|
577
|
+
"name": "Win-back 1 - One Question",
|
|
578
|
+
"subject": "One question, {{contact.first_name}}",
|
|
579
|
+
"templateRef": "email_template.w_email_1",
|
|
580
|
+
"copyDirection": "Win-back day 0. Acknowledge no order without guilt; ask the one diagnostic question (price, the right product, timing, something we said); promise to fix it or quiet down. A reply is the CTA.",
|
|
581
|
+
"mergeTags": [
|
|
582
|
+
"contact.first_name",
|
|
583
|
+
"custom_values.business_name",
|
|
584
|
+
"custom_values.owner_first_name",
|
|
585
|
+
"custom_values.business_phone"
|
|
586
|
+
]
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
"ref": "email.w_email_2",
|
|
590
|
+
"name": "Win-back 2 - A Fresh Code",
|
|
591
|
+
"subject": "A fresh code, one more time",
|
|
592
|
+
"templateRef": "email_template.w_email_2",
|
|
593
|
+
"copyDirection": "Win-back day 14. One real reason to come back (new arrivals or a restock from the brief) and a fresh code with a real expiry. One CTA.",
|
|
594
|
+
"mergeTags": [
|
|
595
|
+
"contact.first_name",
|
|
596
|
+
"custom_values.business_name",
|
|
597
|
+
"custom_values.store_link",
|
|
598
|
+
"custom_values.welcome_code",
|
|
599
|
+
"custom_values.code_expiry_days",
|
|
600
|
+
"custom_values.owner_first_name",
|
|
601
|
+
"custom_values.business_phone"
|
|
602
|
+
]
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
"ref": "email.w_email_3",
|
|
606
|
+
"name": "Win-back 3 - We'll Quiet Down",
|
|
607
|
+
"subject": "We'll quiet down now",
|
|
608
|
+
"templateRef": "email_template.w_email_3",
|
|
609
|
+
"copyDirection": "Win-back day 30, the last automatic message. Say so, keep them on new-arrivals only, one CTA to the store, gracious close.",
|
|
610
|
+
"mergeTags": [
|
|
611
|
+
"contact.first_name",
|
|
612
|
+
"custom_values.business_name",
|
|
613
|
+
"custom_values.store_link",
|
|
614
|
+
"custom_values.owner_first_name",
|
|
615
|
+
"custom_values.business_phone"
|
|
616
|
+
]
|
|
617
|
+
}
|
|
618
|
+
],
|
|
619
|
+
"sms": [
|
|
620
|
+
{
|
|
621
|
+
"ref": "sms.stl_sms_1",
|
|
622
|
+
"name": "Speed to Lead - Welcome Code Text",
|
|
623
|
+
"templateRef": "sms_template.stl_sms_1",
|
|
624
|
+
"copyDirection": "Instant. Business name, the code, the expiry, the one-question ask, STOP line. No link in the first text. If brief.voice.signatureLine is short enough, use it verbatim as the second sentence.",
|
|
625
|
+
"mergeTags": [
|
|
626
|
+
"contact.first_name",
|
|
627
|
+
"custom_values.business_name",
|
|
628
|
+
"custom_values.welcome_code",
|
|
629
|
+
"custom_values.code_expiry_days"
|
|
630
|
+
],
|
|
631
|
+
"conditionalOn": "channels.sms == true"
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
"ref": "sms.stl_sms_2",
|
|
635
|
+
"name": "Speed to Lead - 20 Minute Text",
|
|
636
|
+
"templateRef": "sms_template.stl_sms_2",
|
|
637
|
+
"copyDirection": "20 minutes in. Binary question (a gift or for you?) and the store link.",
|
|
638
|
+
"mergeTags": [
|
|
639
|
+
"contact.first_name",
|
|
640
|
+
"custom_values.store_link"
|
|
641
|
+
],
|
|
642
|
+
"conditionalOn": "channels.sms == true"
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
"ref": "sms.stl_sms_3",
|
|
646
|
+
"name": "Speed to Lead - Next Day Text",
|
|
647
|
+
"templateRef": "sms_template.stl_sms_3",
|
|
648
|
+
"copyDirection": "Day 1. Not chasing; ask if they found what they were looking for; offer to help. No link.",
|
|
649
|
+
"mergeTags": [
|
|
650
|
+
"contact.first_name",
|
|
651
|
+
"custom_values.owner_first_name",
|
|
652
|
+
"custom_values.business_name"
|
|
653
|
+
],
|
|
654
|
+
"conditionalOn": "channels.sms == true"
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
"ref": "sms.mc_sms_1",
|
|
658
|
+
"name": "Missed Call - Instant Text-Back",
|
|
659
|
+
"templateRef": "sms_template.mc_sms_1",
|
|
660
|
+
"copyDirection": "Seconds after a missed inbound call to the support line. Apologize, ask what they need (order / product / return), promise a real person, STOP line.",
|
|
661
|
+
"mergeTags": [
|
|
662
|
+
"custom_values.business_name"
|
|
663
|
+
],
|
|
664
|
+
"conditionalOn": "channels.sms == true"
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
"ref": "sms.mc_sms_2",
|
|
668
|
+
"name": "Missed Call - 1 Hour Text",
|
|
669
|
+
"templateRef": "sms_template.mc_sms_2",
|
|
670
|
+
"copyDirection": "One hour later. Ask for an order number or a good time to call back; include the number.",
|
|
671
|
+
"mergeTags": [
|
|
672
|
+
"custom_values.business_name",
|
|
673
|
+
"custom_values.business_phone"
|
|
674
|
+
],
|
|
675
|
+
"conditionalOn": "channels.sms == true"
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
"ref": "sms.n_sms_1",
|
|
679
|
+
"name": "Nurture Text 1 - One Word",
|
|
680
|
+
"templateRef": "sms_template.n_sms_1",
|
|
681
|
+
"copyDirection": "Day 3. A one-word segmenting question (best sellers / new / gift). STOP line.",
|
|
682
|
+
"mergeTags": [
|
|
683
|
+
"contact.first_name",
|
|
684
|
+
"custom_values.owner_first_name",
|
|
685
|
+
"custom_values.business_name"
|
|
686
|
+
],
|
|
687
|
+
"conditionalOn": "channels.sms == true"
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
"ref": "sms.n_sms_2",
|
|
691
|
+
"name": "Nurture Text 2 - Free Tip",
|
|
692
|
+
"templateRef": "sms_template.n_sms_2",
|
|
693
|
+
"copyDirection": "Day 8. A genuinely useful tip about choosing / caring for the product (from the brief), offer more on YES. No link.",
|
|
694
|
+
"mergeTags": [
|
|
695
|
+
"custom_values.business_name"
|
|
696
|
+
],
|
|
697
|
+
"conditionalOn": "channels.sms == true"
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
"ref": "sms.n_sms_3",
|
|
701
|
+
"name": "Nurture Text 3 - Midpoint",
|
|
702
|
+
"templateRef": "sms_template.n_sms_3",
|
|
703
|
+
"copyDirection": "Day 15. Personal; binary: want the link to the first-order picks, or fewer texts.",
|
|
704
|
+
"mergeTags": [
|
|
705
|
+
"contact.first_name",
|
|
706
|
+
"custom_values.owner_first_name"
|
|
707
|
+
],
|
|
708
|
+
"conditionalOn": "channels.sms == true"
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
"ref": "sms.n_sms_4",
|
|
712
|
+
"name": "Nurture Text 4 - Any Question",
|
|
713
|
+
"templateRef": "sms_template.n_sms_4",
|
|
714
|
+
"copyDirection": "Day 23. No pitch: did they get their question answered (sizing, materials, shipping)? Invite it.",
|
|
715
|
+
"mergeTags": [
|
|
716
|
+
"contact.first_name",
|
|
717
|
+
"custom_values.owner_first_name"
|
|
718
|
+
],
|
|
719
|
+
"conditionalOn": "channels.sms == true"
|
|
720
|
+
},
|
|
721
|
+
{
|
|
722
|
+
"ref": "sms.n_sms_5",
|
|
723
|
+
"name": "Nurture Text 5 - Code Ending",
|
|
724
|
+
"templateRef": "sms_template.n_sms_5",
|
|
725
|
+
"copyDirection": "Day 30. Last one; the code is ending (real); the store link; STOP line.",
|
|
726
|
+
"mergeTags": [
|
|
727
|
+
"contact.first_name",
|
|
728
|
+
"custom_values.business_name",
|
|
729
|
+
"custom_values.welcome_code",
|
|
730
|
+
"custom_values.store_link"
|
|
731
|
+
],
|
|
732
|
+
"conditionalOn": "channels.sms == true"
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
"ref": "sms.w_sms_1",
|
|
736
|
+
"name": "Win-back Text 1",
|
|
737
|
+
"templateRef": "sms_template.w_sms_1",
|
|
738
|
+
"copyDirection": "Win-back day 7. Binary: still interested, or new-arrivals only. STOP line.",
|
|
739
|
+
"mergeTags": [
|
|
740
|
+
"contact.first_name",
|
|
741
|
+
"custom_values.owner_first_name",
|
|
742
|
+
"custom_values.business_name"
|
|
743
|
+
],
|
|
744
|
+
"conditionalOn": "channels.sms == true"
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
"ref": "sms.w_sms_2",
|
|
748
|
+
"name": "Win-back Text 2",
|
|
749
|
+
"templateRef": "sms_template.w_sms_2",
|
|
750
|
+
"copyDirection": "Win-back day 22. A fresh code with the store link.",
|
|
751
|
+
"mergeTags": [
|
|
752
|
+
"contact.first_name",
|
|
753
|
+
"custom_values.business_name",
|
|
754
|
+
"custom_values.welcome_code",
|
|
755
|
+
"custom_values.code_expiry_days",
|
|
756
|
+
"custom_values.store_link"
|
|
757
|
+
],
|
|
758
|
+
"conditionalOn": "channels.sms == true"
|
|
759
|
+
}
|
|
760
|
+
],
|
|
761
|
+
"workflows": [
|
|
762
|
+
{
|
|
763
|
+
"ref": "workflow.speed_to_lead",
|
|
764
|
+
"name": "Speed to Lead",
|
|
765
|
+
"trigger": {
|
|
766
|
+
"type": "form_submission",
|
|
767
|
+
"formRef": "form.vip_signup"
|
|
768
|
+
},
|
|
769
|
+
"stopOnResponse": true,
|
|
770
|
+
"_design": "Five touches in the first 24 hours (text + email instantly, the contact assigned to the person who takes calls, a call task and an alert to a real person, an opportunity card, then a 2nd and 3rd touch), then the hand-off tag that starts the 30-day nurture as the LAST action (E_NO_HANDOFF). Ends early only if they reply (stopOnResponse) or book (the booking workflow pulls them out).",
|
|
771
|
+
"actions": [
|
|
772
|
+
{
|
|
773
|
+
"type": "add_contact_tag",
|
|
774
|
+
"tagRef": "tag.lc_new_lead"
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
"type": "create_opportunity",
|
|
778
|
+
"pipelineRef": "pipeline.store_leads",
|
|
779
|
+
"stageRef": "stage.new_subscriber",
|
|
780
|
+
"name": "{{contact.name}} - New Subscriber"
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
"type": "assign_user",
|
|
784
|
+
"userRef": "user.owner"
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
"type": "send_sms",
|
|
788
|
+
"smsRef": "sms.stl_sms_1",
|
|
789
|
+
"conditionalOn": "channels.sms == true"
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
"type": "send_email",
|
|
793
|
+
"emailRef": "email.stl_email_1"
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
"type": "internal_notification",
|
|
797
|
+
"userRef": "user.owner",
|
|
798
|
+
"title": "New subscriber: {{contact.first_name}} {{contact.last_name}}",
|
|
799
|
+
"body": "{{contact.first_name}} just joined the VIP list. The welcome code text and email already went out. Send a personal one-line welcome within the hour; it is the cheapest first order you will ever get."
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
"type": "task_notification",
|
|
803
|
+
"userRef": "user.owner",
|
|
804
|
+
"title": "Personal welcome for {{contact.first_name}} (new subscriber)",
|
|
805
|
+
"body": "New VIP subscriber {{contact.first_name}} {{contact.last_name}}, {{contact.email}}, {{contact.phone}}. Reply personally in the conversation: one line, ask what they are shopping for, point them to the right product. No script.",
|
|
806
|
+
"dueDate": "1"
|
|
807
|
+
},
|
|
808
|
+
{
|
|
809
|
+
"type": "wait",
|
|
810
|
+
"value": 20,
|
|
811
|
+
"unit": "minutes"
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
"type": "send_sms",
|
|
815
|
+
"smsRef": "sms.stl_sms_2",
|
|
816
|
+
"conditionalOn": "channels.sms == true"
|
|
817
|
+
},
|
|
818
|
+
{
|
|
819
|
+
"type": "wait",
|
|
820
|
+
"value": 3,
|
|
821
|
+
"unit": "hours"
|
|
822
|
+
},
|
|
823
|
+
{
|
|
824
|
+
"type": "send_email",
|
|
825
|
+
"emailRef": "email.stl_email_2"
|
|
826
|
+
},
|
|
827
|
+
{
|
|
828
|
+
"type": "wait",
|
|
829
|
+
"value": 1,
|
|
830
|
+
"unit": "days"
|
|
831
|
+
},
|
|
832
|
+
{
|
|
833
|
+
"type": "send_sms",
|
|
834
|
+
"smsRef": "sms.stl_sms_3",
|
|
835
|
+
"conditionalOn": "channels.sms == true"
|
|
836
|
+
},
|
|
837
|
+
{
|
|
838
|
+
"type": "add_notes",
|
|
839
|
+
"body": "Speed to Lead finished with no reply (5 touches over 24 hours). Handed off to Lead Nurture (30 days) by the nurture-start tag."
|
|
840
|
+
},
|
|
841
|
+
{
|
|
842
|
+
"type": "add_contact_tag",
|
|
843
|
+
"tagRef": "tag.nurture_start"
|
|
844
|
+
}
|
|
845
|
+
]
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
"ref": "workflow.missed_call",
|
|
849
|
+
"name": "Missed Call Text-Back",
|
|
850
|
+
"conditionalOn": "channels.sms == true",
|
|
851
|
+
"trigger": {
|
|
852
|
+
"type": "call_status",
|
|
853
|
+
"callStatuses": [
|
|
854
|
+
"no-answer",
|
|
855
|
+
"busy",
|
|
856
|
+
"voicemail"
|
|
857
|
+
],
|
|
858
|
+
"callDirection": "inbound"
|
|
859
|
+
},
|
|
860
|
+
"stopOnResponse": true,
|
|
861
|
+
"_design": "Fires on an inbound call that was not answered (no-answer / busy / voicemail). Texts back within seconds, tags the contact, alerts a real person and creates a call-back task, then one more text an hour later. Stops the moment they reply.",
|
|
862
|
+
"actions": [
|
|
863
|
+
{
|
|
864
|
+
"type": "send_sms",
|
|
865
|
+
"smsRef": "sms.mc_sms_1",
|
|
866
|
+
"conditionalOn": "channels.sms == true"
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
"type": "add_contact_tag",
|
|
870
|
+
"tagRef": "tag.missed_call"
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
"type": "add_contact_tag",
|
|
874
|
+
"tagRef": "tag.source_phone"
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
"type": "internal_notification",
|
|
878
|
+
"userRef": "user.owner",
|
|
879
|
+
"title": "Missed call: {{contact.first_name}} {{contact.phone}}",
|
|
880
|
+
"body": "An inbound call from {{contact.phone}} was not answered. A text-back already went out. Call back as soon as you can."
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
"type": "task_notification",
|
|
884
|
+
"userRef": "user.owner",
|
|
885
|
+
"title": "Call back {{contact.first_name}} (missed call)",
|
|
886
|
+
"body": "Missed inbound call from {{contact.phone}}. The text-back asked what they need; check the conversation first, then call.",
|
|
887
|
+
"dueDate": "1"
|
|
888
|
+
},
|
|
889
|
+
{
|
|
890
|
+
"type": "wait",
|
|
891
|
+
"value": 1,
|
|
892
|
+
"unit": "hours"
|
|
893
|
+
},
|
|
894
|
+
{
|
|
895
|
+
"type": "send_sms",
|
|
896
|
+
"smsRef": "sms.mc_sms_2",
|
|
897
|
+
"conditionalOn": "channels.sms == true"
|
|
898
|
+
}
|
|
899
|
+
]
|
|
900
|
+
},
|
|
901
|
+
{
|
|
902
|
+
"ref": "workflow.lead_nurture",
|
|
903
|
+
"name": "Lead Nurture (30 days)",
|
|
904
|
+
"trigger": {
|
|
905
|
+
"type": "contact_tag",
|
|
906
|
+
"tagRef": "tag.nurture_start"
|
|
907
|
+
},
|
|
908
|
+
"stopOnResponse": true,
|
|
909
|
+
"_design": "Starts from the Speed to Lead hand-off tag. 11 touches (6 emails + 5 texts) across 31 days of waits: give, give, ask. Removes its own trigger tag first so a later hand-off can start it again. Ends by tagging lapsed and handing off to Win-back. Any reply stops it (stopOnResponse) and Replied - Stop & Route takes over.",
|
|
910
|
+
"actions": [
|
|
911
|
+
{
|
|
912
|
+
"type": "remove_contact_tag",
|
|
913
|
+
"tagRef": "tag.nurture_start"
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
"type": "add_contact_tag",
|
|
917
|
+
"tagRef": "tag.lc_nurturing"
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
"type": "wait",
|
|
921
|
+
"value": 1,
|
|
922
|
+
"unit": "days"
|
|
923
|
+
},
|
|
924
|
+
{
|
|
925
|
+
"type": "send_email",
|
|
926
|
+
"emailRef": "email.n_email_1"
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
"type": "wait",
|
|
930
|
+
"value": 2,
|
|
931
|
+
"unit": "days"
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
"type": "send_sms",
|
|
935
|
+
"smsRef": "sms.n_sms_1",
|
|
936
|
+
"conditionalOn": "channels.sms == true"
|
|
937
|
+
},
|
|
938
|
+
{
|
|
939
|
+
"type": "wait",
|
|
940
|
+
"value": 2,
|
|
941
|
+
"unit": "days"
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
"type": "send_email",
|
|
945
|
+
"emailRef": "email.n_email_2"
|
|
946
|
+
},
|
|
947
|
+
{
|
|
948
|
+
"type": "wait",
|
|
949
|
+
"value": 3,
|
|
950
|
+
"unit": "days"
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
"type": "send_sms",
|
|
954
|
+
"smsRef": "sms.n_sms_2",
|
|
955
|
+
"conditionalOn": "channels.sms == true"
|
|
956
|
+
},
|
|
957
|
+
{
|
|
958
|
+
"type": "wait",
|
|
959
|
+
"value": 2,
|
|
960
|
+
"unit": "days"
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
"type": "send_email",
|
|
964
|
+
"emailRef": "email.n_email_3"
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
"type": "wait",
|
|
968
|
+
"value": 4,
|
|
969
|
+
"unit": "days"
|
|
970
|
+
},
|
|
971
|
+
{
|
|
972
|
+
"type": "send_email",
|
|
973
|
+
"emailRef": "email.n_email_4"
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
"type": "wait",
|
|
977
|
+
"value": 1,
|
|
978
|
+
"unit": "days"
|
|
979
|
+
},
|
|
980
|
+
{
|
|
981
|
+
"type": "send_sms",
|
|
982
|
+
"smsRef": "sms.n_sms_3",
|
|
983
|
+
"conditionalOn": "channels.sms == true"
|
|
984
|
+
},
|
|
985
|
+
{
|
|
986
|
+
"type": "wait",
|
|
987
|
+
"value": 5,
|
|
988
|
+
"unit": "days"
|
|
989
|
+
},
|
|
990
|
+
{
|
|
991
|
+
"type": "send_email",
|
|
992
|
+
"emailRef": "email.n_email_5"
|
|
993
|
+
},
|
|
994
|
+
{
|
|
995
|
+
"type": "wait",
|
|
996
|
+
"value": 3,
|
|
997
|
+
"unit": "days"
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
"type": "send_sms",
|
|
1001
|
+
"smsRef": "sms.n_sms_4",
|
|
1002
|
+
"conditionalOn": "channels.sms == true"
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
"type": "wait",
|
|
1006
|
+
"value": 4,
|
|
1007
|
+
"unit": "days"
|
|
1008
|
+
},
|
|
1009
|
+
{
|
|
1010
|
+
"type": "send_email",
|
|
1011
|
+
"emailRef": "email.n_email_6"
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
"type": "wait",
|
|
1015
|
+
"value": 3,
|
|
1016
|
+
"unit": "days"
|
|
1017
|
+
},
|
|
1018
|
+
{
|
|
1019
|
+
"type": "send_sms",
|
|
1020
|
+
"smsRef": "sms.n_sms_5",
|
|
1021
|
+
"conditionalOn": "channels.sms == true"
|
|
1022
|
+
},
|
|
1023
|
+
{
|
|
1024
|
+
"type": "wait",
|
|
1025
|
+
"value": 1,
|
|
1026
|
+
"unit": "days"
|
|
1027
|
+
},
|
|
1028
|
+
{
|
|
1029
|
+
"type": "add_notes",
|
|
1030
|
+
"body": "Lead Nurture (30 days) finished with no reply: 11 touches over 31 days. Tagged lapsed; Win-back starts from the winback-start tag."
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
"type": "add_contact_tag",
|
|
1034
|
+
"tagRef": "tag.lc_lapsed"
|
|
1035
|
+
},
|
|
1036
|
+
{
|
|
1037
|
+
"type": "add_contact_tag",
|
|
1038
|
+
"tagRef": "tag.winback_start"
|
|
1039
|
+
}
|
|
1040
|
+
]
|
|
1041
|
+
},
|
|
1042
|
+
{
|
|
1043
|
+
"ref": "workflow.reply_route",
|
|
1044
|
+
"name": "Replied - Stop & Route",
|
|
1045
|
+
"trigger": {
|
|
1046
|
+
"type": "customer_reply"
|
|
1047
|
+
},
|
|
1048
|
+
"stopOnResponse": false,
|
|
1049
|
+
"_design": "The exit workflow. The moment a contact replies on any channel: pull them out of every sequence, write a note, mark contacted, alert a real person and create a reply task with a 15-minute target.",
|
|
1050
|
+
"actions": [
|
|
1051
|
+
{
|
|
1052
|
+
"type": "remove_from_workflow",
|
|
1053
|
+
"workflowRef": "workflow.speed_to_lead"
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
"type": "remove_from_workflow",
|
|
1057
|
+
"workflowRef": "workflow.missed_call",
|
|
1058
|
+
"conditionalOn": "channels.sms == true"
|
|
1059
|
+
},
|
|
1060
|
+
{
|
|
1061
|
+
"type": "remove_from_workflow",
|
|
1062
|
+
"workflowRef": "workflow.lead_nurture"
|
|
1063
|
+
},
|
|
1064
|
+
{
|
|
1065
|
+
"type": "remove_from_workflow",
|
|
1066
|
+
"workflowRef": "workflow.win_back"
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
"type": "add_notes",
|
|
1070
|
+
"body": "Contact replied. Removed from Speed to Lead, Missed Call Text-Back, Lead Nurture, Win-back and No-Show Rescue. A human owns the conversation from here."
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
"type": "add_contact_tag",
|
|
1074
|
+
"tagRef": "tag.lc_contacted"
|
|
1075
|
+
},
|
|
1076
|
+
{
|
|
1077
|
+
"type": "internal_notification",
|
|
1078
|
+
"userRef": "user.owner",
|
|
1079
|
+
"title": "{{contact.first_name}} replied",
|
|
1080
|
+
"body": "{{contact.first_name}} {{contact.last_name}} replied. All automated sequences stopped. Answer within 15 minutes: {{contact.phone}}"
|
|
1081
|
+
},
|
|
1082
|
+
{
|
|
1083
|
+
"type": "task_notification",
|
|
1084
|
+
"userRef": "user.owner",
|
|
1085
|
+
"title": "Reply to {{contact.first_name}} (15-minute target)",
|
|
1086
|
+
"body": "They replied to a message. Read the conversation, answer the question they asked, and link the exact product page that fits.",
|
|
1087
|
+
"dueDate": "1"
|
|
1088
|
+
}
|
|
1089
|
+
]
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
"ref": "workflow.win_back",
|
|
1093
|
+
"name": "Win-back (30 days)",
|
|
1094
|
+
"trigger": {
|
|
1095
|
+
"type": "contact_tag",
|
|
1096
|
+
"tagRef": "tag.winback_start"
|
|
1097
|
+
},
|
|
1098
|
+
"stopOnResponse": true,
|
|
1099
|
+
"_design": "Starts from the Lead Nurture (or No-Show Rescue) hand-off tag. 5 touches across 31 days of waits, low pressure, one reason to come back per message. Ends by tagging lost. Any reply stops it.",
|
|
1100
|
+
"actions": [
|
|
1101
|
+
{
|
|
1102
|
+
"type": "remove_contact_tag",
|
|
1103
|
+
"tagRef": "tag.winback_start"
|
|
1104
|
+
},
|
|
1105
|
+
{
|
|
1106
|
+
"type": "send_email",
|
|
1107
|
+
"emailRef": "email.w_email_1"
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
"type": "wait",
|
|
1111
|
+
"value": 7,
|
|
1112
|
+
"unit": "days"
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
"type": "send_sms",
|
|
1116
|
+
"smsRef": "sms.w_sms_1",
|
|
1117
|
+
"conditionalOn": "channels.sms == true"
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
"type": "wait",
|
|
1121
|
+
"value": 7,
|
|
1122
|
+
"unit": "days"
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
"type": "send_email",
|
|
1126
|
+
"emailRef": "email.w_email_2"
|
|
1127
|
+
},
|
|
1128
|
+
{
|
|
1129
|
+
"type": "wait",
|
|
1130
|
+
"value": 8,
|
|
1131
|
+
"unit": "days"
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
"type": "send_sms",
|
|
1135
|
+
"smsRef": "sms.w_sms_2",
|
|
1136
|
+
"conditionalOn": "channels.sms == true"
|
|
1137
|
+
},
|
|
1138
|
+
{
|
|
1139
|
+
"type": "wait",
|
|
1140
|
+
"value": 8,
|
|
1141
|
+
"unit": "days"
|
|
1142
|
+
},
|
|
1143
|
+
{
|
|
1144
|
+
"type": "send_email",
|
|
1145
|
+
"emailRef": "email.w_email_3"
|
|
1146
|
+
},
|
|
1147
|
+
{
|
|
1148
|
+
"type": "wait",
|
|
1149
|
+
"value": 1,
|
|
1150
|
+
"unit": "days"
|
|
1151
|
+
},
|
|
1152
|
+
{
|
|
1153
|
+
"type": "add_notes",
|
|
1154
|
+
"body": "Win-back finished with no reply: 5 touches over 31 days. Tagged lost. The contact stays in the database for future campaigns; nothing else sends automatically."
|
|
1155
|
+
},
|
|
1156
|
+
{
|
|
1157
|
+
"type": "add_contact_tag",
|
|
1158
|
+
"tagRef": "tag.lc_lost"
|
|
1159
|
+
}
|
|
1160
|
+
]
|
|
1161
|
+
}
|
|
1162
|
+
],
|
|
1163
|
+
"handoffs": [
|
|
1164
|
+
{
|
|
1165
|
+
"ref": "handoff.add_staff",
|
|
1166
|
+
"conditionalOn": "staff is empty",
|
|
1167
|
+
"owner": "OPERATOR-UI",
|
|
1168
|
+
"title": "Add the people who get lead alerts and call tasks",
|
|
1169
|
+
"trigger": "the brief listed no staff",
|
|
1170
|
+
"instruction": "In the sub-account go to Settings > My Staff and add at least one user (yourself is fine): name, email, role. Every \"alert a real person\" and \"call task\" step in the workflows is already built and waiting; the moment a user exists, open each workflow and pick them in the Notify and Task steps (or re-run the build with useSavedPlan:true so the pending steps are re-pointed).",
|
|
1171
|
+
"produces": null,
|
|
1172
|
+
"successCheck": "At least one user exists and no workflow step still shows \"user pending\"",
|
|
1173
|
+
"blocks": [
|
|
1174
|
+
"workflow.speed_to_lead",
|
|
1175
|
+
"workflow.reply_route",
|
|
1176
|
+
"workflow.missed_call"
|
|
1177
|
+
],
|
|
1178
|
+
"_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."
|
|
1179
|
+
},
|
|
1180
|
+
{
|
|
1181
|
+
"ref": "handoff.phone_number",
|
|
1182
|
+
"conditionalOn": "flags includes phone_number_needed",
|
|
1183
|
+
"owner": "OPERATOR-UI",
|
|
1184
|
+
"title": "Get a phone number in GoHighLevel (so texts and missed-call text-back can work)",
|
|
1185
|
+
"trigger": "channels.sms == true && channels.hasPhoneNumber != yes",
|
|
1186
|
+
"instruction": "Settings > Phone Numbers > Add Number: buy a local number for the business, then paste it into the business_phone custom value. Every text step and the missed-call text-back are built and wait for this; A2P registration (next) needs the number too.",
|
|
1187
|
+
"produces": "cv.business_phone",
|
|
1188
|
+
"successCheck": "A number shows under Phone Numbers and business_phone matches it",
|
|
1189
|
+
"blocks": [
|
|
1190
|
+
"workflow.speed_to_lead",
|
|
1191
|
+
"workflow.missed_call",
|
|
1192
|
+
"workflow.lead_nurture",
|
|
1193
|
+
"workflow.win_back"
|
|
1194
|
+
]
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
"ref": "handoff.business_details",
|
|
1198
|
+
"owner": "OPERATOR-UI",
|
|
1199
|
+
"title": "Confirm your business phone and the name messages are signed with",
|
|
1200
|
+
"trigger": "always (30 seconds)",
|
|
1201
|
+
"instruction": "Settings > Custom Values: set business_phone to the number customers should call or text back, and owner_first_name to the first name every email is signed with. The build pre-fills both from the intake when it can.",
|
|
1202
|
+
"produces": "cv.owner_first_name",
|
|
1203
|
+
"successCheck": "business_phone and owner_first_name show real values, not blanks",
|
|
1204
|
+
"blocks": [
|
|
1205
|
+
"cv.owner_first_name"
|
|
1206
|
+
]
|
|
1207
|
+
},
|
|
1208
|
+
{
|
|
1209
|
+
"ref": "handoff.a2p",
|
|
1210
|
+
"conditionalOn": "flags includes needs_a2p",
|
|
1211
|
+
"owner": "OPERATOR-EXT",
|
|
1212
|
+
"title": "Register A2P 10DLC (so texts can send)",
|
|
1213
|
+
"trigger": "channels.sms == true",
|
|
1214
|
+
"instruction": "Submit your A2P brand and campaign through the GHL Trust Center / your carrier. Every text step is built but the SMS-bearing workflows stay DRAFT and will not send until this is approved (7-14 day review). Save your full submission package before submitting.",
|
|
1215
|
+
"produces": null,
|
|
1216
|
+
"successCheck": "A2P campaign status shows submitted or approved",
|
|
1217
|
+
"blocks": [
|
|
1218
|
+
"workflow.speed_to_lead",
|
|
1219
|
+
"workflow.missed_call",
|
|
1220
|
+
"workflow.lead_nurture",
|
|
1221
|
+
"workflow.win_back",
|
|
1222
|
+
"sms.stl_sms_1",
|
|
1223
|
+
"sms.stl_sms_2",
|
|
1224
|
+
"sms.stl_sms_3",
|
|
1225
|
+
"sms.mc_sms_1",
|
|
1226
|
+
"sms.mc_sms_2",
|
|
1227
|
+
"sms.n_sms_1",
|
|
1228
|
+
"sms.n_sms_2",
|
|
1229
|
+
"sms.n_sms_3",
|
|
1230
|
+
"sms.n_sms_4",
|
|
1231
|
+
"sms.n_sms_5",
|
|
1232
|
+
"sms.w_sms_1",
|
|
1233
|
+
"sms.w_sms_2"
|
|
1234
|
+
],
|
|
1235
|
+
"_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."
|
|
1236
|
+
},
|
|
1237
|
+
{
|
|
1238
|
+
"ref": "handoff.welcome_code",
|
|
1239
|
+
"owner": "OPERATOR-EXT",
|
|
1240
|
+
"title": "Create the welcome discount code in your store",
|
|
1241
|
+
"trigger": "always",
|
|
1242
|
+
"instruction": "In your store admin (Shopify: Discounts) create the welcome code the messages promise, set it to expire the number of days in the code_expiry_days custom value (default 14) and to one use per customer. Then paste the code into the welcome_code custom value in GHL. The Speed to Lead and nurture messages are built but stay DRAFT until the code exists, so nobody is promised a code that fails at checkout.",
|
|
1243
|
+
"produces": "cv.welcome_code",
|
|
1244
|
+
"successCheck": "The code works at checkout and welcome_code in GHL matches it exactly",
|
|
1245
|
+
"blocks": [
|
|
1246
|
+
"cv.welcome_code",
|
|
1247
|
+
"workflow.speed_to_lead",
|
|
1248
|
+
"workflow.lead_nurture",
|
|
1249
|
+
"workflow.win_back"
|
|
1250
|
+
]
|
|
1251
|
+
},
|
|
1252
|
+
{
|
|
1253
|
+
"ref": "handoff.store_orders",
|
|
1254
|
+
"owner": "OPERATOR-EXT",
|
|
1255
|
+
"title": "Connect store orders to GHL",
|
|
1256
|
+
"trigger": "always",
|
|
1257
|
+
"instruction": "Connect your store so orders reach GHL (Shopify: the native integration under Integrations; other platforms: an order webhook to an inbound webhook trigger). Then add a small workflow: on order → tag lifecycle-first-order, remove from Lead Nurture and Win-back, move the pipeline card to First Order. Until this exists, staff move cards by hand.",
|
|
1258
|
+
"produces": null,
|
|
1259
|
+
"successCheck": "A test order appears on the contact in GHL within a minute",
|
|
1260
|
+
"blocks": []
|
|
1261
|
+
},
|
|
1262
|
+
{
|
|
1263
|
+
"ref": "handoff.email_domain",
|
|
1264
|
+
"conditionalOn": "flags includes email_domain_needed",
|
|
1265
|
+
"owner": "OPERATOR-UI",
|
|
1266
|
+
"title": "Set up your sending email",
|
|
1267
|
+
"trigger": "channels.email == false",
|
|
1268
|
+
"instruction": "Connect a sending domain / mailbox in Settings > Email Services so every email below sends from your address instead of a default.",
|
|
1269
|
+
"produces": null,
|
|
1270
|
+
"successCheck": "A verified sending domain / from-address exists",
|
|
1271
|
+
"blocks": [
|
|
1272
|
+
"email.stl_email_1",
|
|
1273
|
+
"email.stl_email_2",
|
|
1274
|
+
"email.n_email_1",
|
|
1275
|
+
"email.n_email_2",
|
|
1276
|
+
"email.n_email_3",
|
|
1277
|
+
"email.n_email_4",
|
|
1278
|
+
"email.n_email_5",
|
|
1279
|
+
"email.n_email_6",
|
|
1280
|
+
"email.w_email_1",
|
|
1281
|
+
"email.w_email_2",
|
|
1282
|
+
"email.w_email_3"
|
|
1283
|
+
]
|
|
1284
|
+
}
|
|
1285
|
+
]
|
|
1286
|
+
}
|
|
1287
|
+
}
|