@elitedcs/ghl-mcp 3.72.0 → 3.72.2
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 +63 -2
- package/dist/index.js +11682 -9238
- package/guide/guide.html +1 -1
- package/package.json +7 -8
- package/skills/blueprint/examples/medspa-dry-run-report.md +1 -1
- package/skills/blueprint/presets/clinic.md +1 -1
- package/skills/blueprint/presets/clinic.preset.json +1 -1
- package/skills/blueprint/presets/generic-client.md +1 -1
- package/skills/blueprint/presets/generic-client.preset.json +1 -1
- package/skills/blueprint/presets/med-spa.md +1 -1
- package/skills/blueprint/presets/med-spa.preset.json +1 -1
- package/skills/blueprint/references/agency-os-detection.md +1 -1
- package/templates/action-schemas.json +1 -1
- package/templates/clinic-medspa.json +1 -1
- package/templates/external-funnel/README.md +5 -2
- package/templates/external-funnel/wrangler.toml.example +40 -0
- package/skills/blueprint/presets/clinic-launch-a2p.md +0 -39
- package/skills/blueprint/presets/clinic-launch-a2p.preset.json +0 -338
package/guide/guide.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>GHL Command — User Guide</title>
|
|
7
|
-
<!-- guides-hash:
|
|
7
|
+
<!-- guides-hash: a47eca1c8dbf1dd3 -->
|
|
8
8
|
<style>
|
|
9
9
|
/* Deliberately light in every environment, including a dark-mode OS. This is a
|
|
10
10
|
reference document people read at length, print, and save to PDF, and a page
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elitedcs/ghl-mcp",
|
|
3
|
-
"version": "3.72.
|
|
3
|
+
"version": "3.72.2",
|
|
4
4
|
"mcpName": "io.github.drjerryrelth/ghl-command",
|
|
5
|
-
"description": "GoHighLevel MCP Server for Claude. 247 tools
|
|
5
|
+
"description": "GoHighLevel MCP Server for Claude. 247 tools — full CRM, automation, marketing control, account-wide workflow audit, live funnel-capture verification, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"ghl-mcp": "dist/index.js"
|
|
@@ -15,19 +15,18 @@
|
|
|
15
15
|
"templates/trigger-schemas.json",
|
|
16
16
|
"templates/external-funnel/cloudflare-worker.js",
|
|
17
17
|
"templates/external-funnel/README.md",
|
|
18
|
+
"templates/external-funnel/wrangler.toml.example",
|
|
18
19
|
"README.md",
|
|
19
20
|
"CHANGELOG.md",
|
|
20
|
-
"skills",
|
|
21
21
|
"guide",
|
|
22
|
-
"skills
|
|
23
|
-
"skills/blueprint/presets/
|
|
24
|
-
"skills/blueprint/presets/
|
|
25
|
-
"skills/blueprint/presets/clinic-launch-a2p.preset.json",
|
|
26
|
-
"skills/blueprint/examples/sample-build-plan.json"
|
|
22
|
+
"skills",
|
|
23
|
+
"!skills/blueprint/presets/clinic-launch-a2p.preset.json",
|
|
24
|
+
"!skills/blueprint/presets/clinic-launch-a2p.md"
|
|
27
25
|
],
|
|
28
26
|
"scripts": {
|
|
29
27
|
"build": "esbuild src/index.ts --bundle --platform=node --target=node20 --format=cjs --outfile=dist/index.js --packages=external && esbuild src/capture-helper.ts --bundle --platform=node --target=node20 --format=cjs --outfile=dist/capture-helper.js --packages=external",
|
|
30
28
|
"setup": "node setup-wizard.mjs",
|
|
29
|
+
"catalogue": "node scripts/export-command-os-catalogue.mjs",
|
|
31
30
|
"start": "node dist/index.js",
|
|
32
31
|
"dev": "tsc --watch",
|
|
33
32
|
"test": "vitest run",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
This is the live proof that the med_spa preset produces a plan that passes the MCP's
|
|
6
6
|
authoritative validator and dry-runs clean. Captured 2026-06-25 against the **MCP Testing**
|
|
7
|
-
sandbox (
|
|
7
|
+
sandbox (a throwaway 1-user account). dry_run writes nothing.
|
|
8
8
|
|
|
9
9
|
Source artifacts: [`medspa-brief.json`](medspa-brief.json) → [`medspa-build-plan.json`](medspa-build-plan.json).
|
|
10
10
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Preset: Clinic / Practice
|
|
2
2
|
|
|
3
3
|
**File:** `clinic.preset.json` · **id:** `clinic` · **version:** 2.0.0 · **default:** no
|
|
4
|
-
**Source:** Generalized from
|
|
4
|
+
**Source:** Generalized from proven clinic builds with the intake industry pack "clinic" (insurance_or_cash, new_patient_offer, compliance_notes); v2 depth per the owner review of 2026-08-26.
|
|
5
5
|
|
|
6
6
|
## When it is selected
|
|
7
7
|
Routes from the "Clinic / practice" business type and the `clinic` / `practice` / `chiro` / `dental` / `pt` / `functional_medicine` aliases. Med spas route to `med_spa`; a time-boxed launch event routes to `clinic_launch_a2p`.
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"functional_medicine"
|
|
26
26
|
]
|
|
27
27
|
},
|
|
28
|
-
"source": "Generalized from
|
|
28
|
+
"source": "Generalized from proven clinic builds with the intake industry pack \"clinic\" (insurance_or_cash, new_patient_offer, compliance_notes); v2 depth per the owner review of 2026-08-26.",
|
|
29
29
|
"conventions": {
|
|
30
30
|
"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.",
|
|
31
31
|
"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.",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Preset: Generic Client
|
|
2
2
|
|
|
3
3
|
**File:** `generic-client.preset.json` · **id:** `generic` · **version:** 2.0.0 · **default:** no
|
|
4
|
-
**Source:** ghl-command showcase-video Modules 0-7 +
|
|
4
|
+
**Source:** ghl-command showcase-video Modules 0-7 + a proven med-spa build; v2 depth per the owner review of 2026-08-26.
|
|
5
5
|
|
|
6
6
|
## When it is selected
|
|
7
7
|
The fallback for every `business_type` without a dedicated preset: agencies, "other", and anything unmatched. Med spa, clinic, coach, ecommerce and local service each route to their own preset now; this one carries the same workflow depth with neutral copy.
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"other"
|
|
17
17
|
]
|
|
18
18
|
},
|
|
19
|
-
"source": "ghl-command showcase-video Modules 0-7 +
|
|
19
|
+
"source": "ghl-command showcase-video Modules 0-7 + a proven med-spa build; v2 depth per the owner review of 2026-08-26.",
|
|
20
20
|
"conventions": {
|
|
21
21
|
"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.",
|
|
22
22
|
"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.",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Preset: Med Spa (default)
|
|
2
2
|
|
|
3
3
|
**File:** `med-spa.preset.json` · **id:** `med_spa` · **version:** 2.0.0 · **default:** yes
|
|
4
|
-
**Source:** ghl-command showcase Modules 0-7 +
|
|
4
|
+
**Source:** ghl-command showcase Modules 0-7 + proven med-spa builds; v2 depth per the owner review of 2026-08-26 (every workflow must do real work; nurture never under 30 days; copy to the Gary V / Hormozi standard in references/copy-guide.md).
|
|
5
5
|
|
|
6
6
|
## When it is selected
|
|
7
7
|
The default reference preset, and the routing target for med-spa / aesthetics business types (`selectors.businessTypes`) and the `med_spa` / `medspa` / `aesthetics` / `injectables` aliases. A brief whose `business_type` matches no preset resolves here.
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"injectables"
|
|
22
22
|
]
|
|
23
23
|
},
|
|
24
|
-
"source": "ghl-command showcase Modules 0-7 +
|
|
24
|
+
"source": "ghl-command showcase Modules 0-7 + proven med-spa builds; v2 depth per the owner review of 2026-08-26 (every workflow must do real work; nurture never under 30 days; copy to the Gary V / Hormozi standard in references/copy-guide.md).",
|
|
25
25
|
"conventions": {
|
|
26
26
|
"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.",
|
|
27
27
|
"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.",
|
|
@@ -32,7 +32,7 @@ Use the §3 question set, and surface the credit line once:
|
|
|
32
32
|
|
|
33
33
|
## 4. Ingestion mapping — Agency OS artifacts → Brief (§4)
|
|
34
34
|
|
|
35
|
-
The artifact files are markdown with predictable headings (validated against real instances in Jerry's `
|
|
35
|
+
The artifact files are markdown with predictable headings (validated against real instances in Jerry's `client-workspace/brand/` and `_shared/`). Parse by section heading; carry the deep structures **verbatim** into the brief's `extended` block so plan-gen uses full psychographics, not a flattened summary. Set `briefSource: "agency_os"` (or `"hybrid"` if you mix in form answers for channel/tech facts Agency OS does not capture).
|
|
36
36
|
|
|
37
37
|
### `owner-profile.md` (brand-dna / build-profile) → brief
|
|
38
38
|
| Section in owner-profile.md | Brief field |
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
"traffic_index": [{ "id": "USER_ID", "indexes": [1] }],
|
|
166
166
|
"total_index": 1
|
|
167
167
|
},
|
|
168
|
-
"notes": "[
|
|
168
|
+
"notes": "[PROVEN LIVE 2026-08-27 on the MCP Testing sandbox: a scratch workflow carrying both a single-user and a two-user round-robin assign_user node saved, read back with every attribute intact (user_list, only_unassigned_contact, traffic_split, traffic_weightage, traffic_index, total_index) and both real user ids present, and PUBLISHED — GHL's own builder validator accepted it, which is the check that requires a non-empty user_list and verifies each id against the location's users. Scratch workflow deleted; the account was left byte-identical.] 'Assign to user' — the listed users become the contact owner. Linear actions-category node like add_contact_tag. user_list is REQUIRED and non-empty (GHL's builder validator: 'user_list_required'; every id is checked against the location's users — a dead id silently never assigns). Multiple users = round-robin; the equal-split bookkeeping the builder saves is weightage {id:1 each}, traffic_index [{id, indexes:[1..weight]}] with globally sequential indexes, total_index = sum of weights — single user: weightage {id:1}, index [{id, indexes:[1]}], total 1. only_unassigned_contact false always (re)assigns; true skips contacts that already have an owner. traffic_split 'unevenly' + custom weights and customUserList (custom-value mode) exist in the builder but are NOT built by us. LIVE TEST TO CLOSE: build one workflow with this node on a sandbox (MCP Testing), publish, run a test contact through, read back with get_workflow_full + get_contact — confirm the node persists byte-for-byte and the contact's assignedTo/owner becomes USER_ID; then remove this UNVERIFIED label."
|
|
169
169
|
},
|
|
170
170
|
"remove_from_workflow": {
|
|
171
171
|
"example": {
|
|
@@ -36,8 +36,11 @@ The executor returns what you plug into the Worker config + form:
|
|
|
36
36
|
## Deploy (Cloudflare)
|
|
37
37
|
1. `npm i -g wrangler && wrangler login`
|
|
38
38
|
2. `wrangler secret put GHL_PIT` ← paste your token (secret; never in code/repo)
|
|
39
|
-
3.
|
|
40
|
-
`ALLOWED_ORIGIN` (your funnel
|
|
39
|
+
3. `cp wrangler.toml.example wrangler.toml`, then fill in the four values it
|
|
40
|
+
asks for: `GHL_LOCATION_ID`, `TRIGGER_TAG`, `ALLOWED_ORIGIN` (your funnel
|
|
41
|
+
domain — locks CORS), and optional `RE_ENROLL`. The example file ships beside
|
|
42
|
+
this README with each value explained and the right/wrong forms of
|
|
43
|
+
`ALLOWED_ORIGIN` spelled out.
|
|
41
44
|
4. (Optional) Turnstile: add the widget to your form, `wrangler secret put
|
|
42
45
|
TURNSTILE_SECRET`.
|
|
43
46
|
5. `wrangler deploy` → point your form at the Worker URL.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# External-Funnel Lead Bridge — Worker config.
|
|
2
|
+
#
|
|
3
|
+
# Copy this file to `wrangler.toml` (same directory as cloudflare-worker.js),
|
|
4
|
+
# fill in the four values below, then `wrangler deploy`.
|
|
5
|
+
#
|
|
6
|
+
# cp wrangler.toml.example wrangler.toml
|
|
7
|
+
#
|
|
8
|
+
# The GHL token is NOT in here on purpose. It is a secret:
|
|
9
|
+
# wrangler secret put GHL_PIT
|
|
10
|
+
# Never put a token in this file — wrangler.toml is committed by most people,
|
|
11
|
+
# and a Private Integration token can write to your whole sub-account.
|
|
12
|
+
|
|
13
|
+
name = "ghl-lead-bridge" # your Worker's name; becomes <name>.<subdomain>.workers.dev
|
|
14
|
+
main = "cloudflare-worker.js"
|
|
15
|
+
compatibility_date = "2026-01-01"
|
|
16
|
+
|
|
17
|
+
[vars]
|
|
18
|
+
# The GHL sub-account this bridge writes into. `apply_build_plan` returns it.
|
|
19
|
+
GHL_LOCATION_ID = "PUT_YOUR_LOCATION_ID_HERE"
|
|
20
|
+
|
|
21
|
+
# The tag that starts your speed-to-lead workflow. `apply_build_plan` returns it.
|
|
22
|
+
TRIGGER_TAG = "PUT_YOUR_TRIGGER_TAG_HERE"
|
|
23
|
+
|
|
24
|
+
# Your funnel's exact origin — scheme + host, no trailing slash, no path.
|
|
25
|
+
# This locks CORS. The Worker refuses to start without it and never falls back
|
|
26
|
+
# to "*", so a stranger's page cannot post leads into your account.
|
|
27
|
+
# right: "https://clinic.example.com"
|
|
28
|
+
# wrong: "https://clinic.example.com/" | "clinic.example.com" | "*"
|
|
29
|
+
ALLOWED_ORIGIN = "https://PUT_YOUR_FUNNEL_DOMAIN_HERE"
|
|
30
|
+
|
|
31
|
+
# Optional. "true" removes and re-adds the trigger tag so a returning lead
|
|
32
|
+
# re-enters the workflow. Leave "false" if a second submission should not
|
|
33
|
+
# restart the sequence.
|
|
34
|
+
RE_ENROLL = "false"
|
|
35
|
+
|
|
36
|
+
# ── Optional: Turnstile (bot protection on your form) ─────────────────
|
|
37
|
+
# The Worker checks Turnstile ONLY when TURNSTILE_SECRET is set, so this is
|
|
38
|
+
# entirely opt-in. Add the widget to your form, then:
|
|
39
|
+
# wrangler secret put TURNSTILE_SECRET
|
|
40
|
+
# Nothing to add here — it is a secret, not a var.
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# Preset: Clinic Launch Event + A2P (not default)
|
|
2
|
-
|
|
3
|
-
**File:** `clinic-launch-a2p.preset.json` · **id:** `clinic_launch_a2p` · **version:** 1.0.0 · **default:** no
|
|
4
|
-
**Source:** `client-provisioning-spec.md` + CLL `CLIENT_BUILD_AUTOMATION_BLUEPRINT.md` + `A2P_Client_Playbook.md` + QA v3 snapshot.
|
|
5
|
-
|
|
6
|
-
## When it is selected
|
|
7
|
-
Explicitly, or when the brief describes a **time-boxed on-site event + database-reactivation** model: event start/end dates, a deposit + balance, package tiers, and SMS reactivation of an existing opted-in list. It is **not** auto-selected by `business_type` — a med spa running a steady-state practice gets the `generic` preset, not this one.
|
|
8
|
-
|
|
9
|
-
## Why it exists
|
|
10
|
-
It proves the preset format scales to the hardest case: a build that is mostly **operator handoffs and compliance gates**, not auto-created objects. It also makes Jerry's most-proven asset (the CLL launch system) reusable as one preset without making the whole feature CLL-specific.
|
|
11
|
-
|
|
12
|
-
## What it builds (skeleton)
|
|
13
|
-
- **15-stage DBR pipeline** (DBR Lead → … → Package Sold → … → Lost) — the proven launch funnel.
|
|
14
|
-
- **9 representative intake/consent + sale fields** (the full launch intake is ~49 fields from the CLL onboarding/consent set; the skill creates the subset the workflows use). Package Recommended is genericized to Tier 1-4 with prices in custom values, not option labels.
|
|
15
|
-
- **17 tags** — DBR lines (1-4), DBR events, event status, routing.
|
|
16
|
-
- **25 custom values** — the launch data map (business/clinic identity, event window + capacity, deposit/trial/balance, package tier names + prices, and the link values filled by handoffs).
|
|
17
|
-
- **1 event calendar** — event-type, scoped to the event window, with a deposit.
|
|
18
|
-
- **1 patient intake & consent form** (phone not required — A2P opt-in rule).
|
|
19
|
-
- **No GHL funnel** — the opt-in presence is the dedicated **A2P compliance site** (6-page template), because A2P approval requires a real hosted site with exact consent HTML, not a GHL preview.
|
|
20
|
-
- **10 workflows** — DBR SMS line 1, auto-tag reply, send booking link (keyword BOOK), deposit-paid confirm, no-show, balance collection, package sold, post-event non-buyer (72hr), sold-out waitlist, STOP→DND. (The full system is ~27 WFs incl. lines 2-4; line 1 + the core set are encoded; additional lines clone the line-1 shape.)
|
|
21
|
-
|
|
22
|
-
> **Known manual step — SMS keyword triggers (decided 2026-06-27).** The keyword-routed workflows (BOOK / STOP / WAIT) use an `inbound_keyword` trigger that the executor does NOT auto-build yet. They build with all their steps, but the trigger is surfaced as a "set up this keyword trigger by hand in the GHL UI" step rather than auto-wiring. ghl-command-mcp decided to keep it manual for the v3.48.0 release (a new trigger type needs its own build-and-prove cycle) and queued a native build for when clinic keyword routing is prioritized. This is CLL-only and does not affect the med_spa/generic presets.
|
|
23
|
-
|
|
24
|
-
## The handoff chain (the heart of this preset)
|
|
25
|
-
This preset is handoff-dominated. In dependency order:
|
|
26
|
-
1. **add-staff** (blocks the calendar)
|
|
27
|
-
2. **stripe-products** → fills the deposit/balance/tier link custom values
|
|
28
|
-
3. **calendar-config** (dates, hours, deposit, connect) → fills the booking link
|
|
29
|
-
4. **phone-numbers** (1 per ~500, max 4) → blocks the DBR lines
|
|
30
|
-
5. **a2p-site** (deploy the compliance site, exact consent HTML) → blocks A2P submission
|
|
31
|
-
6. **a2p-brand-campaign** (submit, avoid forbidden words, 7-14 day review) → blocks all SMS sends
|
|
32
|
-
7. **conv-ai** (Chloe normal + sold-out prompts)
|
|
33
|
-
8. **sms-warming** (4-week ramp, parallel with A2P)
|
|
34
|
-
9. **list-import** (clean + split per line, test batch of 5) → blocks the DBR lines
|
|
35
|
-
|
|
36
|
-
The §5A approval view renders these as the "you must do manually, in this order" list, with each success check. That honesty — "here is everything GHL Command cannot do for you, sequenced" — is the point of the launch preset.
|
|
37
|
-
|
|
38
|
-
## A2P safety carried into the copy
|
|
39
|
-
SMS `copyDirection` enforces A2P-safe wording (clinic name not legal entity, opt-out lines, and explicit avoidance of the forbidden list: weight-loss / health-claim / income / 'operated by' / reactivation-lead-gen language). The compliance-site handoff carries the exact consent-HTML requirements that passed 8/8 in the playbook.
|
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"presetId": "clinic_launch_a2p",
|
|
3
|
-
"presetVersion": "1.0.0",
|
|
4
|
-
"schemaVersion": "0.1",
|
|
5
|
-
"title": "Clinic Launch Event + A2P",
|
|
6
|
-
"description": "The database-reactivation launch-event build (clinic / med spa on-site events): a 15-stage DBR pipeline, intake/consent fields, the launch custom-value set, the DBR SMS line + booking + sale workflow system, an event calendar with deposit, and the full compliance handoff chain (A2P site, A2P brand + campaign, Stripe products + links, phone purchase, Conversation AI prompts, SMS warming). NOT the default; selected explicitly for a launch-event / database-reactivation engagement. Heavy on operator handoffs by design.",
|
|
7
|
-
"default": false,
|
|
8
|
-
"selectors": {
|
|
9
|
-
"businessTypes": [],
|
|
10
|
-
"aliases": ["clinic_launch_a2p", "cll", "dbr", "launch_event"],
|
|
11
|
-
"selectBy": "Chosen explicitly, or when the brief describes a time-boxed on-site event / database-reactivation model (event_start/end dates, deposit + balance, package tiers, SMS reactivation of an existing list). Not auto-selected by business_type."
|
|
12
|
-
},
|
|
13
|
-
"source": "command-center/shared/client-provisioning-spec.md + clinic-launch-lab CLIENT_BUILD_AUTOMATION_BLUEPRINT.md + A2P_Client_Playbook.md + QA v3 snapshot",
|
|
14
|
-
"skeleton": {
|
|
15
|
-
"pipelines": [
|
|
16
|
-
{
|
|
17
|
-
"ref": "pipeline.launch",
|
|
18
|
-
"name": "{{business.name}} Launch Events || Launch Events",
|
|
19
|
-
"stages": {
|
|
20
|
-
"fillFrom": "goal.salesStages",
|
|
21
|
-
"transform": "stageList",
|
|
22
|
-
"default": [
|
|
23
|
-
{ "ref": "stage.dbr_lead", "name": "DBR Lead", "position": 0 },
|
|
24
|
-
{ "ref": "stage.active_dbr", "name": "Active In DBR", "position": 1 },
|
|
25
|
-
{ "ref": "stage.replied_dbr", "name": "Replied To DBR", "position": 2 },
|
|
26
|
-
{ "ref": "stage.completed_dbr", "name": "Completed DBR", "position": 3 },
|
|
27
|
-
{ "ref": "stage.booking_link_sent", "name": "Interested - Booking Link Sent", "position": 4 },
|
|
28
|
-
{ "ref": "stage.deposit_paid", "name": "Booked - Deposit Paid", "position": 5 },
|
|
29
|
-
{ "ref": "stage.showed", "name": "Appointment Showed", "position": 6 },
|
|
30
|
-
{ "ref": "stage.package_sold", "name": "Package Sold", "position": 7 },
|
|
31
|
-
{ "ref": "stage.no_sale", "name": "No Package Sold - Follow Up", "position": 8 },
|
|
32
|
-
{ "ref": "stage.no_show", "name": "Appointment No Show", "position": 9 },
|
|
33
|
-
{ "ref": "stage.canceled", "name": "Appointment Canceled", "position": 10 },
|
|
34
|
-
{ "ref": "stage.rescheduled", "name": "Rescheduled", "position": 11 },
|
|
35
|
-
{ "ref": "stage.not_interested", "name": "Not Interested", "position": 12 },
|
|
36
|
-
{ "ref": "stage.dnd", "name": "DND", "position": 13 },
|
|
37
|
-
{ "ref": "stage.lost", "name": "Lost", "position": 14 }
|
|
38
|
-
]
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
],
|
|
42
|
-
"customFields": [
|
|
43
|
-
{ "ref": "field.package_recommended", "name": "Package Recommended", "dataType": "SINGLE_OPTIONS", "model": "contact", "notes": "Generic Tier 1-4 options; the dollar amount lives in the package_tier_*_price custom values, NOT in the option label (avoids the Lux-specific hardcoding)." },
|
|
44
|
-
{ "ref": "field.intake_height", "name": "Intake - Height", "dataType": "TEXT", "model": "contact" },
|
|
45
|
-
{ "ref": "field.intake_weight", "name": "Intake - Weight", "dataType": "TEXT", "model": "contact" },
|
|
46
|
-
{ "ref": "field.intake_sex", "name": "Intake - Sex", "dataType": "SINGLE_OPTIONS", "model": "contact" },
|
|
47
|
-
{ "ref": "field.intake_physician_care", "name": "Intake - Under Physician Care", "dataType": "CHECKBOX", "model": "contact" },
|
|
48
|
-
{ "ref": "field.deposit_paid", "name": "Deposit Paid", "dataType": "CHECKBOX", "model": "contact" },
|
|
49
|
-
{ "ref": "field.balance_due", "name": "Balance Due At Appointment", "dataType": "MONETORY", "model": "contact" },
|
|
50
|
-
{ "ref": "field.lead_source", "name": "Lead Source", "dataType": "SINGLE_OPTIONS", "model": "contact" },
|
|
51
|
-
{ "ref": "field.ltv", "name": "Estimated Lifetime Value", "dataType": "MONETORY", "model": "contact" }
|
|
52
|
-
],
|
|
53
|
-
"_fieldNote": "The full launch intake captures ~49 fields (the CLL onboarding form nI5dPig1RIJvd6vQNcEf + patient intake/consent). The skill ingests the operator's onboarding answers and creates the subset the workflows actually use; the consent/health fields above are representative. The full field list is in the CLL onboarding spec.",
|
|
54
|
-
"tags": [
|
|
55
|
-
{ "ref": "tag.dbr_line_1", "name": "dbr-line-1" },
|
|
56
|
-
{ "ref": "tag.dbr_line_2", "name": "dbr-line-2" },
|
|
57
|
-
{ "ref": "tag.dbr_line_3", "name": "dbr-line-3" },
|
|
58
|
-
{ "ref": "tag.dbr_line_4", "name": "dbr-line-4" },
|
|
59
|
-
{ "ref": "tag.dbr_import", "name": "dbr-import" },
|
|
60
|
-
{ "ref": "tag.active_in_dbr", "name": "active-in-dbr" },
|
|
61
|
-
{ "ref": "tag.interested_in_dbr", "name": "interested-in-dbr" },
|
|
62
|
-
{ "ref": "tag.completed_dbr", "name": "completed-dbr" },
|
|
63
|
-
{ "ref": "tag.completed_dbr_appt", "name": "completed-dbr-appointment" },
|
|
64
|
-
{ "ref": "tag.dbr_waitlist", "name": "dbr-waitlist" },
|
|
65
|
-
{ "ref": "tag.event_sold_out", "name": "event-sold-out" },
|
|
66
|
-
{ "ref": "tag.link_sent_no_book", "name": "link-sent-no-book" },
|
|
67
|
-
{ "ref": "tag.balance_paid", "name": "balance-paid" },
|
|
68
|
-
{ "ref": "tag.intake_form_submitted", "name": "intake-form-submitted" },
|
|
69
|
-
{ "ref": "tag.package_purchased", "name": "package-purchased" },
|
|
70
|
-
{ "ref": "tag.patient_no_show", "name": "patient-no-show" },
|
|
71
|
-
{ "ref": "tag.patient_rescheduled", "name": "patient-rescheduled" }
|
|
72
|
-
],
|
|
73
|
-
"customValues": [
|
|
74
|
-
{ "ref": "cv.business_name", "name": "business_name", "value": "{{business.name}}" },
|
|
75
|
-
{ "ref": "cv.clinic_name", "name": "clinic_name", "value": "{{business.name}}" },
|
|
76
|
-
{ "ref": "cv.clinic_director_name", "name": "clinic_director_name", "value": "" },
|
|
77
|
-
{ "ref": "cv.clinic_phone", "name": "clinic_phone", "value": "" },
|
|
78
|
-
{ "ref": "cv.clinic_address", "name": "clinic_address", "value": "{{business.location}}" },
|
|
79
|
-
{ "ref": "cv.event_start_date", "name": "event_start_date", "value": "" },
|
|
80
|
-
{ "ref": "cv.event_end_date", "name": "event_end_date", "value": "" },
|
|
81
|
-
{ "ref": "cv.event_capacity", "name": "event_capacity", "value": "" },
|
|
82
|
-
{ "ref": "cv.spots_left", "name": "spots_left", "value": "", "notes": "= event_capacity at launch" },
|
|
83
|
-
{ "ref": "cv.deposit_amount", "name": "deposit_amount", "value": "" },
|
|
84
|
-
{ "ref": "cv.trial_price", "name": "trial_price", "value": "" },
|
|
85
|
-
{ "ref": "cv.balance_amount", "name": "balance_amount", "value": "" },
|
|
86
|
-
{ "ref": "cv.package_tier_1_name", "name": "package_tier_1_name", "value": "" },
|
|
87
|
-
{ "ref": "cv.package_tier_1_price", "name": "package_tier_1_price", "value": "" },
|
|
88
|
-
{ "ref": "cv.package_tier_2_name", "name": "package_tier_2_name", "value": "" },
|
|
89
|
-
{ "ref": "cv.package_tier_2_price", "name": "package_tier_2_price", "value": "" },
|
|
90
|
-
{ "ref": "cv.package_tier_3_name", "name": "package_tier_3_name", "value": "" },
|
|
91
|
-
{ "ref": "cv.package_tier_3_price", "name": "package_tier_3_price", "value": "" },
|
|
92
|
-
{ "ref": "cv.booking_link", "name": "booking_link", "value": "", "filledBy": "handoff.calendar_config" },
|
|
93
|
-
{ "ref": "cv.deposit_link", "name": "deposit_link", "value": "", "filledBy": "handoff.stripe_products" },
|
|
94
|
-
{ "ref": "cv.balance_payment_link", "name": "balance_payment_link", "value": "", "filledBy": "handoff.stripe_products" },
|
|
95
|
-
{ "ref": "cv.package_tier_1_link", "name": "package_tier_1_link", "value": "", "filledBy": "handoff.stripe_products" },
|
|
96
|
-
{ "ref": "cv.package_tier_2_link", "name": "package_tier_2_link", "value": "", "filledBy": "handoff.stripe_products" },
|
|
97
|
-
{ "ref": "cv.package_tier_3_link", "name": "package_tier_3_link", "value": "", "filledBy": "handoff.stripe_products" },
|
|
98
|
-
{ "ref": "cv.intake_form_url", "name": "intake_form_url", "value": "", "filledBy": "form.intake" }
|
|
99
|
-
],
|
|
100
|
-
"calendars": [
|
|
101
|
-
{
|
|
102
|
-
"ref": "calendar.event",
|
|
103
|
-
"name": "{{business.name}} Launch Event || Launch Event",
|
|
104
|
-
"calendarType": "event",
|
|
105
|
-
"_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).",
|
|
106
|
-
"openHours": [{ "daysOfTheWeek": [1, 2, 3, 4, 5], "hours": [{ "openHour": 9, "openMinute": 0, "closeHour": 18, "closeMinute": 0 }] }],
|
|
107
|
-
"availabilityType": 0,
|
|
108
|
-
"slotDuration": 30,
|
|
109
|
-
"requiresStaff": true,
|
|
110
|
-
"notes": "Event-type calendar scoped to the event window (event_start_date..event_end_date) with a deposit (deposit_amount, e.g. $19). Dates/hours/deposit set at handoff.calendar_config."
|
|
111
|
-
}
|
|
112
|
-
],
|
|
113
|
-
"forms": [
|
|
114
|
-
{
|
|
115
|
-
"ref": "form.intake",
|
|
116
|
-
"name": "{{business.name}} Patient Intake & Consent",
|
|
117
|
-
"fields": [
|
|
118
|
-
{ "type": "standard", "key": "first_name", "required": true },
|
|
119
|
-
{ "type": "standard", "key": "last_name", "required": true },
|
|
120
|
-
{ "type": "standard", "key": "email", "required": true },
|
|
121
|
-
{ "type": "standard", "key": "phone", "required": false },
|
|
122
|
-
{ "type": "custom", "fieldRef": "field.intake_height", "required": false },
|
|
123
|
-
{ "type": "custom", "fieldRef": "field.intake_weight", "required": false },
|
|
124
|
-
{ "type": "custom", "fieldRef": "field.intake_sex", "required": false },
|
|
125
|
-
{ "type": "custom", "fieldRef": "field.intake_physician_care", "required": false }
|
|
126
|
-
],
|
|
127
|
-
"notes": "Phone is NOT required and carries no asterisk (A2P opt-in rule). Full intake mirrors the CLL onboarding/consent field set."
|
|
128
|
-
}
|
|
129
|
-
],
|
|
130
|
-
"funnels": [],
|
|
131
|
-
"_funnelNote": "The launch preset does NOT build a GHL funnel. The opt-in / compliance presence is the dedicated A2P compliance SITE (6-page template: index/about/services/contact/privacy/terms), deployed at handoff.a2p_site — its consent HTML is what A2P approval depends on, and it must be a real hosted site, not a GHL preview.",
|
|
132
|
-
"emails": [
|
|
133
|
-
{ "ref": "email.deposit_confirm", "name": "Deposit Confirmation", "subject": "You're booked — deposit received", "copyDirection": "Confirm deposit + appointment date/time + location from custom values; what to bring; reassurance.", "mergeTags": ["contact.first_name"] },
|
|
134
|
-
{ "ref": "email.post_event_non_buyer", "name": "Post-Event Follow-up (non-buyer)", "subject": "Following up from your visit", "copyDirection": "72-hour close for non-buyers; restate the package value; CTA to a tier link; no health/income claims.", "mergeTags": ["contact.first_name"] }
|
|
135
|
-
],
|
|
136
|
-
"sms": [
|
|
137
|
-
{ "ref": "sms.dbr_line_1", "name": "Main DBR SMS - Line 1", "copyDirection": "Reactivation opener to an opted-in list. Clinic name (not legal entity); one line; offer the booking step; include opt-out (Reply STOP). A2P-safe wording — NO weight-loss / health-claim / income language.", "mergeTags": ["contact.first_name"] },
|
|
138
|
-
{ "ref": "sms.booking_link", "name": "Send Booking Link", "copyDirection": "Send the booking link (cv.booking_link) on interest/keyword; one line; opt-out.", "mergeTags": ["contact.first_name"] },
|
|
139
|
-
{ "ref": "sms.balance_collect", "name": "Balance Collection", "copyDirection": "Request balance via balance_payment_link before/at appointment; opt-out.", "mergeTags": ["contact.first_name"] },
|
|
140
|
-
{ "ref": "sms.sold_out_waitlist", "name": "Sold-Out Waitlist", "copyDirection": "When event-sold-out: offer waitlist (Reply WAIT); set expectation; opt-out.", "mergeTags": ["contact.first_name"] }
|
|
141
|
-
],
|
|
142
|
-
"workflows": [
|
|
143
|
-
{
|
|
144
|
-
"ref": "workflow.dbr_line_1",
|
|
145
|
-
"name": "Main DBR SMS - Line 1",
|
|
146
|
-
"trigger": { "type": "contact_tag", "tagRef": "tag.dbr_line_1" },
|
|
147
|
-
"stopOnResponse": true,
|
|
148
|
-
"sendWindow": "8am-10pm local",
|
|
149
|
-
"actions": [
|
|
150
|
-
{ "type": "add_contact_tag", "tagRef": "tag.active_in_dbr" },
|
|
151
|
-
{ "type": "create_opportunity", "pipelineRef": "pipeline.launch", "stageRef": "stage.active_dbr", "name": "{{contact.name}} - DBR" },
|
|
152
|
-
{ "type": "send_sms", "smsRef": "sms.dbr_line_1" }
|
|
153
|
-
]
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
"ref": "workflow.auto_tag_reply",
|
|
157
|
-
"name": "Auto-Tag DBR Reply",
|
|
158
|
-
"trigger": { "type": "customer_reply" },
|
|
159
|
-
"stopOnResponse": false,
|
|
160
|
-
"actions": [
|
|
161
|
-
{ "type": "add_contact_tag", "tagRef": "tag.interested_in_dbr" },
|
|
162
|
-
{ "type": "internal_notification", "to": "{{operator.userId}}", "title": "DBR reply", "body": "{{contact.first_name}} replied to the launch campaign" }
|
|
163
|
-
]
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
"ref": "workflow.send_booking_link",
|
|
167
|
-
"name": "Reply BOOK - Send Booking Link",
|
|
168
|
-
"trigger": { "type": "inbound_keyword", "keyword": "BOOK" },
|
|
169
|
-
"stopOnResponse": false,
|
|
170
|
-
"actions": [
|
|
171
|
-
{ "type": "add_contact_tag", "tagRef": "tag.link_sent_no_book" },
|
|
172
|
-
{ "type": "send_sms", "smsRef": "sms.booking_link" }
|
|
173
|
-
]
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
"ref": "workflow.deposit_paid",
|
|
177
|
-
"name": "Deposit Paid - Confirm Appointment",
|
|
178
|
-
"trigger": { "type": "appointment", "appointmentStatus": "confirmed", "calendarRef": "calendar.event" },
|
|
179
|
-
"stopOnResponse": false,
|
|
180
|
-
"actions": [
|
|
181
|
-
{ "type": "add_contact_tag", "tagRef": "tag.balance_paid" },
|
|
182
|
-
{ "type": "send_email", "emailRef": "email.deposit_confirm" },
|
|
183
|
-
{ "type": "internal_notification", "to": "{{operator.userId}}", "title": "Deposit paid", "body": "{{contact.first_name}} paid deposit + booked" }
|
|
184
|
-
]
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
"ref": "workflow.no_show",
|
|
188
|
-
"name": "Appointment No-Show - Alert + Status",
|
|
189
|
-
"trigger": { "type": "appointment", "appointmentStatus": "noshow", "calendarRef": "calendar.event" },
|
|
190
|
-
"stopOnResponse": false,
|
|
191
|
-
"actions": [
|
|
192
|
-
{ "type": "add_contact_tag", "tagRef": "tag.patient_no_show" },
|
|
193
|
-
{ "type": "internal_notification", "to": "{{operator.userId}}", "title": "No-show", "body": "{{contact.first_name}} did not show" }
|
|
194
|
-
]
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
"ref": "workflow.balance_collection",
|
|
198
|
-
"name": "Balance Collection - Auto-Send",
|
|
199
|
-
"trigger": { "type": "appointment", "appointmentStatus": "confirmed", "calendarRef": "calendar.event" },
|
|
200
|
-
"stopOnResponse": false,
|
|
201
|
-
"actions": [
|
|
202
|
-
{ "type": "wait", "value": 1, "unit": "days" },
|
|
203
|
-
{ "type": "send_sms", "smsRef": "sms.balance_collect" }
|
|
204
|
-
]
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
"ref": "workflow.package_sold",
|
|
208
|
-
"name": "Package Sold - Confirmation",
|
|
209
|
-
"trigger": { "type": "contact_tag", "tagRef": "tag.package_purchased" },
|
|
210
|
-
"stopOnResponse": false,
|
|
211
|
-
"actions": [
|
|
212
|
-
{ "type": "internal_notification", "to": "{{operator.userId}}", "title": "Package sold", "body": "{{contact.first_name}} purchased a package" }
|
|
213
|
-
]
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
"ref": "workflow.post_event_followup",
|
|
217
|
-
"name": "Post-Event Follow-up (Non-Buyers, 72hr)",
|
|
218
|
-
"trigger": { "type": "contact_tag", "tagRef": "tag.completed_dbr_appt" },
|
|
219
|
-
"stopOnResponse": true,
|
|
220
|
-
"actions": [
|
|
221
|
-
{ "type": "send_email", "emailRef": "email.post_event_non_buyer" }
|
|
222
|
-
]
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
"ref": "workflow.sold_out_waitlist",
|
|
226
|
-
"name": "Sold Out - DBR Waitlist",
|
|
227
|
-
"trigger": { "type": "contact_tag", "tagRef": "tag.event_sold_out" },
|
|
228
|
-
"stopOnResponse": false,
|
|
229
|
-
"actions": [
|
|
230
|
-
{ "type": "add_contact_tag", "tagRef": "tag.dbr_waitlist" },
|
|
231
|
-
{ "type": "send_sms", "smsRef": "sms.sold_out_waitlist" }
|
|
232
|
-
]
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
"ref": "workflow.reply_stop_dnd",
|
|
236
|
-
"name": "Replied STOP - DND",
|
|
237
|
-
"trigger": { "type": "inbound_keyword", "keyword": "STOP" },
|
|
238
|
-
"stopOnResponse": false,
|
|
239
|
-
"actions": [
|
|
240
|
-
{ "type": "internal_notification", "to": "{{operator.userId}}", "title": "Opt-out", "body": "{{contact.first_name}} replied STOP" }
|
|
241
|
-
]
|
|
242
|
-
}
|
|
243
|
-
],
|
|
244
|
-
"handoffs": [
|
|
245
|
-
{
|
|
246
|
-
"ref": "handoff.add_staff",
|
|
247
|
-
"owner": "OPERATOR-UI",
|
|
248
|
-
"title": "Add staff users (you, your coordinator, the client)",
|
|
249
|
-
"trigger": "always",
|
|
250
|
-
"instruction": "Add the event team as users in Settings > My Staff. The event calendar needs assignable staff and GHL Command cannot add users.",
|
|
251
|
-
"produces": null,
|
|
252
|
-
"successCheck": "Staff users present",
|
|
253
|
-
"blocks": ["calendar.event"]
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
"ref": "handoff.stripe_products",
|
|
257
|
-
"owner": "OPERATOR-EXT",
|
|
258
|
-
"title": "Connect Stripe + create products and payment links",
|
|
259
|
-
"trigger": "always",
|
|
260
|
-
"instruction": "Connect Stripe, create the deposit, balance, and package tier products, and generate payment links. Paste the links back so they fill the deposit_link / balance_payment_link / package_tier_*_link custom values.",
|
|
261
|
-
"produces": "cv.deposit_link, cv.balance_payment_link, cv.package_tier_1_link, cv.package_tier_2_link, cv.package_tier_3_link",
|
|
262
|
-
"successCheck": "Products exist; each payment link resolves",
|
|
263
|
-
"blocks": ["cv.deposit_link", "cv.balance_payment_link", "cv.package_tier_1_link", "cv.package_tier_2_link", "cv.package_tier_3_link"]
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
"ref": "handoff.calendar_config",
|
|
267
|
-
"owner": "OPERATOR-UI",
|
|
268
|
-
"title": "Configure the event calendar (dates, hours, deposit) + connect it",
|
|
269
|
-
"trigger": "always",
|
|
270
|
-
"instruction": "Set the event window (event_start_date..event_end_date), hours, and the deposit amount on the event calendar, and authorize your Google/Outlook connection. Copy the booking link back to fill booking_link.",
|
|
271
|
-
"produces": "cv.booking_link",
|
|
272
|
-
"successCheck": "Calendar shows the event dates + connected account; booking link resolves",
|
|
273
|
-
"blocks": ["cv.booking_link"]
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
"ref": "handoff.phone_numbers",
|
|
277
|
-
"owner": "OPERATOR-UI",
|
|
278
|
-
"title": "Purchase phone numbers (1 per ~500 contacts, max 4)",
|
|
279
|
-
"trigger": "always",
|
|
280
|
-
"instruction": "Buy SMS-capable numbers sized to your list (roughly one per 500 contacts, up to four). Required before the DBR SMS lines can run.",
|
|
281
|
-
"produces": null,
|
|
282
|
-
"successCheck": "Numbers present and SMS-capable",
|
|
283
|
-
"blocks": ["workflow.dbr_line_1"]
|
|
284
|
-
},
|
|
285
|
-
{
|
|
286
|
-
"ref": "handoff.a2p_site",
|
|
287
|
-
"owner": "OPERATOR-EXT",
|
|
288
|
-
"title": "Build + deploy your A2P compliance website",
|
|
289
|
-
"trigger": "always",
|
|
290
|
-
"instruction": "Deploy the 6-page compliance site (index/about/services/contact/privacy/terms) from the provided template, filling your real business details. The consent HTML must be exact (two unchecked checkboxes, brand name in <strong> matching the Trust Center, no inline styles, clean URLs, privacy + terms with the full SMS clause set). It must be a real hosted site, not a GHL preview. A2P approval depends on this.",
|
|
291
|
-
"produces": null,
|
|
292
|
-
"successCheck": "Live site returns 200; consent + privacy + terms pass the 8/8 + 7-item checks",
|
|
293
|
-
"blocks": ["handoff.a2p_brand_campaign"]
|
|
294
|
-
},
|
|
295
|
-
{
|
|
296
|
-
"ref": "handoff.a2p_brand_campaign",
|
|
297
|
-
"owner": "OPERATOR-EXT",
|
|
298
|
-
"title": "Submit A2P brand + campaign",
|
|
299
|
-
"trigger": "always",
|
|
300
|
-
"instruction": "Submit the A2P brand (exact IRS legal name, EIN, address) and campaign (use-case description, two sample messages, opt-in description) in the Trust Center. Avoid the forbidden-words list (weight loss, revenue/income claims, 'operated by', reactivation/lead-gen language). Save the full submission before sending. 7-14 day review.",
|
|
301
|
-
"produces": null,
|
|
302
|
-
"successCheck": "Brand + campaign status submitted/approved",
|
|
303
|
-
"blocks": ["workflow.dbr_line_1", "workflow.send_booking_link", "workflow.balance_collection", "workflow.sold_out_waitlist", "sms.dbr_line_1", "sms.booking_link", "sms.balance_collect", "sms.sold_out_waitlist"],
|
|
304
|
-
"_blocksNote": "Lists the SMS-bearing WORKFLOW refs (so they stay DRAFT until A2P is met) plus the sms.* asset refs — only an explicit workflow.* ref gates a workflow's publish state."
|
|
305
|
-
},
|
|
306
|
-
{
|
|
307
|
-
"ref": "handoff.conv_ai",
|
|
308
|
-
"owner": "OPERATOR-UI",
|
|
309
|
-
"title": "Activate Conversation AI (normal + sold-out prompts)",
|
|
310
|
-
"trigger": "always",
|
|
311
|
-
"instruction": "Create the Conversation AI bot, paste the normal-mode and sold-out-mode prompts, and wire the sold-out swap to the event-sold-out tag.",
|
|
312
|
-
"produces": null,
|
|
313
|
-
"successCheck": "Bot active; sold-out prompt swap fires on event-sold-out",
|
|
314
|
-
"blocks": []
|
|
315
|
-
},
|
|
316
|
-
{
|
|
317
|
-
"ref": "handoff.sms_warming",
|
|
318
|
-
"owner": "OPERATOR-EXT",
|
|
319
|
-
"title": "SMS warming ramp (4 weeks, parallel with A2P)",
|
|
320
|
-
"trigger": "always",
|
|
321
|
-
"instruction": "Import the number pool and run the 4-week warming ramp so deliverability holds at launch volume. Runs in parallel with the A2P review window.",
|
|
322
|
-
"produces": null,
|
|
323
|
-
"successCheck": "Warming on track; deliverability healthy",
|
|
324
|
-
"blocks": []
|
|
325
|
-
},
|
|
326
|
-
{
|
|
327
|
-
"ref": "handoff.list_import",
|
|
328
|
-
"owner": "OPERATOR-EXT",
|
|
329
|
-
"title": "Receive + clean + split the contact list",
|
|
330
|
-
"trigger": "always",
|
|
331
|
-
"instruction": "Provide the contact list. It gets deduped, cleaned, and split per line (dbr-line-1..4). Test a batch of 5 before throttled mass enroll.",
|
|
332
|
-
"produces": null,
|
|
333
|
-
"successCheck": "Lists ready; test batch passes before mass enroll",
|
|
334
|
-
"blocks": ["workflow.dbr_line_1"]
|
|
335
|
-
}
|
|
336
|
-
]
|
|
337
|
-
}
|
|
338
|
-
}
|