#897
Integrate tawk.to ticketing support and retire Notion support flow
Goal
Replace the current Notion support integration with a tawk.to-powered support/ticketing flow for AI Stats users.
Domain/brand checked: tawk.to / https://www.tawk.to/.
Research notes
- The normal website integration is the tawk.to chat widget JavaScript snippet, copied from the tawk.to dashboard per property.
- tawk.to ticketing can manage longer-running support cases. Tickets can be created from forwarded support emails, escalated live chats, offline messages, Knowledge Base ticket forms, and ticket forms sent inside chats.
- The JavaScript API supports custom visitor/chat metadata through
window.Tawk_API.setAttributes(attributes, callback).- Attribute keys must be alphanumeric or dash-only.
- Custom attributes are limited to 50, excluding
name,email, andhash. - Attribute values cannot be empty and must be <= 255 characters.
- Setting verified
name/emailshould use Secure Mode with a server-generated HMAC hash.
- The JavaScript API also supports chat events and tags:
addEvent(eventName, metadata, callback)for custom chat events.addTags(tags, callback)with a max of 10 tags.
- Secure Mode requires a server-side HMAC-SHA256 hash using the visitor email and the tawk.to API key. Do not expose the API key to the client.
- Webhooks can notify AI Stats when chats start/end, transcripts are created, or new tickets are created. Webhook payloads include an
X-Tawk-SignatureHMAC-SHA1 signature that should be verified with the webhook secret. - tawk.to REST API exists for deeper automation, including tickets/chats/properties/webhooks, but access is by request, so treat REST API work as optional/follow-up until access is approved.
Official references:
- Main site: https://www.tawk.to/
- Add widget: https://help.tawk.to/article/adding-a-widget-to-your-website
- JavaScript API: https://developer.tawk.to/jsapi/
- Secure Mode /
setAttributeshash: https://help.tawk.to/article/how-to-use-setattributes-with-a-hash-in-javascript-api - Ticketing setup: https://help.tawk.to/article/how-to-set-up-ticketing-in-tawkto
- Webhooks: https://developer.tawk.to/webhooks/
- REST API: https://help.tawk.to/article/rest-api
Proposed implementation
- Create tawk.to properties for production and staging.
- Add environment variables:
NEXT_PUBLIC_TAWK_PROPERTY_IDNEXT_PUBLIC_TAWK_WIDGET_IDTAWK_SECURE_MODE_API_KEYor equivalent server-only secretTAWK_WEBHOOK_SECRETif webhook ingestion is enabled- Optional later:
TAWK_REST_API_KEYif REST API access is approved
- Add a client-only
TawkProvider/ support widget loader.- Load the widget only when support chat is enabled and the current route should expose support.
- Avoid loading the third-party script during SSR.
- Confirm CSP changes if the app uses strict
script-src,connect-src,frame-src, orimg-srcrules.
- For signed-in users, attach safe account context using Secure Mode +
setAttributes:user-idemailandnamevia Secure Mode/hashorg-id/ workspace id, if applicableplanbilling-statuscredit-balanceormonthly-usage-band, if safecurrent-pagelast-active-atsupport-context-version
- Do not send secrets or sensitive raw values into tawk.to metadata.
- Never send API keys, raw auth tokens, full payment details, or private provider keys.
- If referencing an API key, only use a non-sensitive internal id or short display prefix where already safe.
- Add a signed server endpoint/action for generating the visitor hash.
- Input: authenticated user session.
- Output: safe visitor payload + HMAC hash.
- The browser should never receive the tawk.to secure-mode API key.
- Replace Notion support UI links/forms with the tawk.to flow.
- Dashboard support button opens/maximises the widget.
- Public support page can either show the widget or route users to the support email/ticket flow.
- Offline users should still be able to leave a message/ticket.
- Configure tawk.to ticketing operationally.
- Set up departments such as
General,Billing,Account,API/Gateway,Bug Report. - Forward the support inbox into tawk.to ticketing if using email-based support.
- Configure notifications for new tickets and customer replies.
- Set up departments such as
- Optional webhook ingestion.
- Add
/api/webhooks/tawk. - Verify
X-Tawk-Signatureagainst the raw request body before processing. - Store/log ticket ids, chat ids, transcript ids, requester email, and user/org mapping where available.
- Use this later for Linear/GitHub issue creation or internal support analytics.
- Add
- Update privacy/support documentation to disclose tawk.to as the support provider and explain what account context is shared.
Acceptance criteria
- Existing Notion support entry point is removed or clearly deprecated.
- tawk.to widget loads on intended AI Stats routes without SSR errors.
- Authenticated users appear in tawk.to with verified name/email using Secure Mode.
- Safe account metadata is attached to chats/tickets and handles API errors gracefully.
- Unauthenticated visitors can still contact support without account metadata.
- CSP and privacy/support docs are updated.
- Ticketing is configured for offline messages and/or support email forwarding.
- If webhooks are included, signature verification is implemented and tested.
- No secrets, API keys, tokens, or raw payment details are sent to tawk.to.
Open questions
- Should tawk.to be loaded everywhere, only in the dashboard, or only after the user clicks Help/Support?
- Should support metadata include billing/credit context by default, or should that only be added when a user opens support from a billing page?
- Do we want webhook ingestion in the first pass, or should it be a follow-up after the widget/ticketing replacement is live?
- Should ticket ids be mirrored into Linear/GitHub later, or should tawk.to remain the source of truth for support cases?
Activity
7Issue understanding
This feature request asks to rip out the existing Notion-based support ticket system (contact form → Notion database → ticket comments via Notion API) and replace it with a tawk.to chat widget + ticketing flow. The Notion support code is substantial — a ~386-line Notion client (`apps/web/src/lib/support/notion.ts`), API routes at `/api/contact` and `/api/internal/support/tickets/[...]`, a contact page, a Support card in the quickstart section, and a support schedule module. There is already an empty `chat-widget.tsx` stub that returns null. No CSP exists yet (no middleware.ts). The key work is: tawk.to client widget (similar to the GA `CookieConsentManager` pattern using `next/script`), Secure Mode HMAC endpoint, env vars in turbo.json `globalEnv`, a server action for visitor hash generation, and cleaning up the Notion support code paths.AI Agent Prompt (Copy/Paste)
Replace the existing Notion-based support system with a tawk.to chat/ticketing integration.
Code to inspect first:
- `apps/web/src/lib/support/notion.ts` — current Notion API client
- `apps/web/src/lib/support/schedule.ts` — support availability logic
- `apps/web/src/app/api/contact/route.ts` — public contact endpoint
- `apps/web/src/app/api/internal/support/tickets/` — ticket CRUD routes
- `apps/web/src/components/contact/ContactClient.tsx` — contact form
- `apps/web/src/components/(data)/model/quickstart/Support.tsx` — support card
- `apps/web/src/components/chat-widget.tsx` — stub returning null
- `apps/web/src/app/(dashboard)/contact/page.tsx` — contact page
- `apps/web/src/components/analytics/CookieConsentManager.tsx` — pattern for next/script third-party loading
- `apps/web/src/lib/analytics.ts` — pattern for env-var config modules
- `turbo.json` `globalEnv` for where to add new env vars
- `apps/web/src/app/layout.tsx` — root layout for provider placement
Work required:
1. Remove Notion support code: delete `lib/support/notion.ts`, `lib/support/schedule.ts`, `app/api/contact/route.ts`, `app/api/internal/support/tickets/` directory, `components/contact/` directory, and clean up `components/(data)/model/quickstart/Support.tsx` to remove Notion-specific logic (keep Discord/email/docs links). Update the contact page to point to the new flow.
2. Create `apps/web/src/lib/support/tawk.ts` config module exporting env vars: `NEXT_PUBLIC_TAWK_PROPERTY_ID`, `NEXT_PUBLIC_TAWK_WIDGET_ID`, and server-only `TAWK_SECURE_MODE_API_KEY`. Add these to `turbo.json` `globalEnv`.
3. Create `apps/web/src/components/support/TawkProvider.tsx` — client component that loads the tawk.to widget script via `next/script` (like CookieConsentManager does for GA). Use `strategy="lazyOnload"`. Only load on routes that should show support (dashboard routes). For signed-in users, call `window.Tawk_API.setAttributes()` with safe account metadata (user-id, email via Secure Mode hash, plan, org-id, current-page). For Secure Mode, add a server action or API route at `app/api/internal/support/tawk-hash/route.ts` that takes the authenticated user session and returns `{ visitorPayload, hash }`.
4. Rewrite `components/chat-widget.tsx` to render `TawkProvider` conditionally (or integrate `TawkProvider` into root layout).
5. Add `app/api/webhooks/tawk/route.ts` for optional webhook ingestion — verify `X-Tawk-Signature` HMAC-SHA1 against the raw body using `TAWK_WEBHOOK_SECRET`.
6. Ensure no secrets/API keys/payment details are sent to tawk.to. Never expose `TAWK_SECURE_MODE_API_KEY` to the client.
7. Update privacy/support docs if they reference Notion.
For CSP: the app currently has no CSP. If adding one is in scope, add a `middleware.ts` with `script-src 'self' https://*.tawk.to https://*.tawk.com; connect-src 'self' https://*.tawk.to https://*.tawk.com; frame-src https://*.tawk.to; img-src 'self' data: https://*.tawk.to`. Otherwise, note that CSP is absent and tag as a follow-up.
Run `pnpm lint`, `pnpm typecheck`, and check `apps/web` builds cleanly after changes.admin assigned danielbutler12mo ago
admin added status/stalestatus/stalestatus/stalestatus/stale labels2mo ago
AI-220