3 · Support (9C)
Objective — give customers a way to get help by standing up two customer-facing systems — a live chat widget and a help center / knowledge base — picking one tool per row and recording the choice.
Background
Section titled “Background”Two customer-facing systems close out Phase 9, each with several alternatives in the reference set:
- Live chat widget — multiple alternatives (hosted vs self-hosted, free vs paid). Choose by budget and data-residency needs.
- Help center / knowledge base — several alternatives. A searchable KB deflects repetitive support tickets before they’re filed.
1. Assess your chat options
Section titled “1. Assess your chat options”Check whether a chat widget is already installed, then pick a provider that fits your budget and needs.
-
Check for an existing chat widget. Open the live site → DevTools (F12) → Console and run:
console.log('Crisp:', typeof $crisp);console.log('Tawk:', typeof Tawk_API);console.log('ThriveDesk:', typeof ThriveDesk);Also grep your layout files:
Terminal window grep -rE "crisp|intercom|tawk|thrivedesk" resources/views/ --include="*.blade.php"- ✅ You know whether a chat widget is already present.
-
Pick a provider using the decision table.
First, compare the providers on features and business capabilities, then use the recommendation table below.
Support features:
Provider Price AI chatbot Knowledge base Mobile app Crisp Free / $25+ Pro only Pro only Yes Intercom $74+/mo Yes Yes Yes Tawk.to Free Basic Basic Yes ThriveDesk LTD / $25+ Limited Yes Yes Tiny Talk LTD Yes (AI-first) No No Leadster LTD Limited No No Business features:
| Provider | CRM | Analytics | White-label | API | |---|---|---|---| | Crisp | Yes | Yes | Pro | Yes | | Intercom | Yes | Yes | Yes | Yes | | Tawk.to | Limited | Yes | Paid | Limited | | ThriveDesk | Yes | Yes | Yes | Yes | | Tiny Talk | Limited | Yes | Yes | Yes | | Leadster | Yes | Yes | No | Limited |
Your situation Recommended provider Zero budget Tawk.to (free) Starting out, want features Crisp (free tier) Have a lifetime deal budget ThriveDesk Want an AI-first chatbot Tiny Talk Lead-capture focus Leadster Enterprise, larger budget Intercom - ✅ A provider is chosen and noted.
-
Record the decision in
_CUSTOMIZATIONS.md(which you chose and why).- ✅ Chat provider decision is documented.
2. Choose your help-center approach
Section titled “2. Choose your help-center approach”Pick the help-center / knowledge-base tool that fits your team’s effort and budget.
-
Compare the options and pick one.
Option Effort Cost Best for GitBook Medium Free (public) / $8/mo Developer docs, Git sync Notion Low Free Quickest setup ThriveDesk KB Low Included if using ThriveDesk chat Chat widget auto-suggests articles Guidejar Medium LTD available Visual step-by-step guides - ✅ A help-center tool is chosen and noted.
-
Record the decision in
_CUSTOMIZATIONS.md.- ✅ Help-center decision is documented.
2.1 Wire the chosen help center
Section titled “2.1 Wire the chosen help center”Once you’ve picked a tool, the setup is short — the detail that blocks people is the CNAME target for the docs/help subdomain.
-
Point the docs subdomain at your tool’s CNAME target, then verify it resolves.
Tool Subdomain CNAME target Notes GitBook docs.<DOMAIN>hosting.gitbook.ioSpace → Settings → Domains; Cloudflare DNS only (gray cloud). Notion via Super.so docs.<DOMAIN>cname.super.soPublish the Notion page first, then connect in Super. ThriveDesk KB help.<DOMAIN>kb.thrivedesk.comBest if ThriveDesk is also the chat tool. Terminal window dig docs.<DOMAIN> CNAME +shortcurl -I https://docs.<DOMAIN># Expected: CNAME target resolves and TLS returns 200- ✅ The docs/help subdomain resolves to the tool target and loads over HTTPS.
-
Add the help link to the app — navbar and footer at minimum.
<a href="https://docs.<DOMAIN>" target="_blank" rel="noopener" class="nav-link">Docs</a>- ✅ The help center is reachable from the app’s primary navigation.
3. Choose and wire the support systems
Section titled “3. Choose and wire the support systems”Pick one tool per row, embed it, and record the decision so it’s traceable later.
-
Pick a live chat widget by budget and data-residency needs, then embed it.
- ✅ A chat widget is wired and reachable on the live site.
-
Pick a help center / knowledge base and seed it with starter articles.
- ✅ A searchable KB is live and deflects common questions.
-
Record the choices. Note which tool you picked (and why) in
_CUSTOMIZATIONS.md.- ✅ Both choices are documented for later traceability.
3.1 Generic KB fallback (any platform)
Section titled “3.1 Generic KB fallback (any platform)”If none of the hosted tools fit, the structure and first articles matter more than the platform.
-
Create the category structure: Getting Started · Features · Billing & Payments · Troubleshooting · API (if applicable).
-
Write the 5 priority starter articles.
# Article Deflects 1 Getting Started ”How do I begin?“ 2 Account Settings Profile/preferences questions 3 Billing FAQ Plan/payment/refund questions 4 Password Reset The single most common ticket 5 Contact Support ”How do I reach a human?” -
Use one article template for consistency:
## OverviewOne or two sentences: what this article covers and who it's for.## Steps1. First action with exact UI label/path.2. Next action.## Common Issues- Symptom → cause → fix.## Related Articles- Link to the next logical article. -
Link from the app and test search.
- ✅ The KB has starter articles, is reachable from the app, and search finds each article.
Embed snippets (per provider)
Section titled “Embed snippets (per provider)”Each provider follows the same shape — one .env key, one config/services.php entry, one consent-gated Blade block before </body>, plus an optional authed identify block. All three ship user identity to a third party, so the embed must sit behind your Phase-6 consent gate (same condition the engagement page uses for ProductLift). Never commit a literal widget/website/app ID inline — read it from config.
-
Crisp — free tier, good default when starting out.
.env:Terminal window CRISP_WEBSITE_ID=config/services.php:'crisp' => ['website_id' => env('CRISP_WEBSITE_ID'),],Before
</body>in the main layout:{{-- Crisp — loads only after functional/analytics consent (Phase 6 §6 gate). --}}@if (config('services.crisp.website_id') && (function_exists('consent') ? consent('analytics') : request()->cookie('consent_analytics') === 'yes'))<script type="text/javascript">window.$crisp = [];window.CRISP_WEBSITE_ID = @json(config('services.crisp.website_id'));(function () {var d = document, s = d.createElement("script");s.src = "https://client.crisp.chat/l.js";s.async = 1;d.getElementsByTagName("head")[0].appendChild(s);})();</script>@auth<script>$crisp.push(["set", "user:email", [@json(Auth::user()->email ?? '')]]);$crisp.push(["set", "user:nickname", [@json(Auth::user()->name ?? '')]]);$crisp.push(["set", "session:data", [[["user_id", @json((string) Auth::id())],["plan", @json(Auth::user()->plan ?? 'free')]]]]);</script>@endauth@endif- ✅
CRISP_WEBSITE_IDset; widget loads only after consent; an authed user’s email/name reach the Crisp dashboard.
- ✅
-
Tawk.to — fully free, the zero-budget pick.
.env:Terminal window TAWK_PROPERTY_ID=TAWK_WIDGET_ID=config/services.php:'tawk' => ['property_id' => env('TAWK_PROPERTY_ID'),'widget_id' => env('TAWK_WIDGET_ID'),],Before
</body>in the main layout:{{-- Tawk.to — consent-gated (Phase 6 §6). --}}@if (config('services.tawk.property_id') && (function_exists('consent') ? consent('analytics') : request()->cookie('consent_analytics') === 'yes'))<script type="text/javascript">var Tawk_API = Tawk_API || {}, Tawk_LoadStart = new Date();@authTawk_API.onLoad = function () {Tawk_API.setAttributes({'name': @json(Auth::user()->name ?? ''),'email': @json(Auth::user()->email ?? ''),'userId': @json((string) Auth::id()),'plan': @json(Auth::user()->plan ?? 'free')}, function (error) {});};@endauth(function () {var s1 = document.createElement("script"),s0 = document.getElementsByTagName("script")[0];s1.async = true;s1.src = 'https://embed.tawk.to/'+ @json(config('services.tawk.property_id')) + '/'+ @json(config('services.tawk.widget_id'));s1.charset = 'UTF-8';s1.setAttribute('crossorigin', '*');s0.parentNode.insertBefore(s1, s0);})();</script>@endif- ✅ Both Tawk IDs set; widget loads only after consent; authed identity flows to the Tawk dashboard.
-
Intercom — enterprise / larger budget.
.env:Terminal window INTERCOM_APP_ID=config/services.php:'intercom' => ['app_id' => env('INTERCOM_APP_ID'),],Before
</body>in the main layout:{{-- Intercom — consent-gated (Phase 6 §6). --}}@if (config('services.intercom.app_id') && (function_exists('consent') ? consent('analytics') : request()->cookie('consent_analytics') === 'yes'))<script>window.intercomSettings = {api_base: "https://api-iam.intercom.io",app_id: @json(config('services.intercom.app_id')),@authuser_id: @json((string) Auth::id()),name: @json(Auth::user()->name ?? ''),email: @json(Auth::user()->email ?? ''),created_at: {{ optional(Auth::user()->created_at)->timestamp ?? 'null' }},plan: @json(Auth::user()->plan ?? 'free'),@endauth};</script><script>(function () { var w = window; var ic = w.Intercom; if (typeof ic === "function") { ic('reattach_activator'); ic('update', w.intercomSettings); } else { var d = document; var i = function () { i.c(arguments); }; i.q = []; i.c = function (args) { i.q.push(args); }; w.Intercom = i; var l = function () { var s = d.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'https://widget.intercom.io/widget/' + @json(config('services.intercom.app_id')); var x = d.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); }; if (document.readyState === 'complete') { l(); } else if (w.attachEvent) { w.attachEvent('onload', l); } else { w.addEventListener('load', l, false); } } })();</script>@endif- ✅
INTERCOM_APP_IDset; widget loads only after consent; authed user identity (includingcreated_at) reaches Intercom.
- ✅
4. Confirm the phase gate
Section titled “4. Confirm the phase gate”Run the Phase 9 gate — the app is “polished” only when discoverability, engagement, and support all pass.
-
Walk the phase gate and confirm each line.
- ✅ Valid sitemap + robots; meta/schema/titles in place.
- ✅ Search Console verified, sitemap submitted, PageSpeed pass run.
- ✅ Onboarding + changelog + feedback path exists.
- ✅ Chat widget + help center chosen and wired.
Checklist
Section titled “Checklist”Do not mark this step done until every box below is checked.
- 👤 Chat decision — provider assessed and chosen; recorded in
_CUSTOMIZATIONS.md. - 👤 Help center decision — approach chosen; recorded in
_CUSTOMIZATIONS.md. - 🤖 SEO foundation — valid sitemap + robots; meta/schema/titles in place.
- 👤 Search Console — verified, sitemap submitted, PageSpeed pass run.
- 🔀 Engagement — onboarding + changelog + feedback path exists.
- 👤 Support — chat widget + help center chosen and wired.