Run your workspace
Widget on the marketing site
APP_URL serves). It is a platform-level
setting โ only super_admins of the install can configure it.
Customers (workspace members) who want a chat widget on
their marketing site embed the standard install
snippet (see Install snippet)
on their own server โ they don't need this toggle at all.
The Pitchbar install's public marketing site (home page + any
/marketing/* route) can host a real chat widget
pointed at one of the install's published agents โ not just the
seeded demo sandbox. Configure it under
Settings โ Marketing โ Marketing-site widget
(super_admin only).
How it works
- Toggle Enable widget on marketing pages. While off, the marketing site has no chat surface (default).
- Pick an agent from the dropdown. The dropdown lists every published agent across every workspace on this install (super_admin can mount any agent).
- Click Save marketing widget. The form sends only the widget toggle + agent id; the marketing home content editor is a separate sibling form on the same page and is unaffected. The widget mounts for anonymous visitors only โ signed-in admins, customers, and platform admins never see it (would look like surveillance and pollute your own analytics with internal traffic).
Gate logic
The blade gate in resources/views/app.blade.php
resolves the agent in this order:
-
AppSetting override โ when
marketing_widget_enabled = trueANDmarketing_widget_agent_idresolves to a published agent, that agent is mounted with no demo pill. - Explicit choice with invalid agent โ no widget. When the toggle is ON but the selected agent is unpublished or deleted, the gate mounts nothing. It does not silently substitute the demo agent โ that would surface a stranger's persona name on your marketing site (client report 2026-05-23).
-
DEMO env fallback โ when the toggle was never
enabled (default false) AND
DEMO=trueis set in the environment, the seededMarketingDemoAgentmounts with thedata-demo="true"attribute so visitors see a "DEMO" pill. - Nothing โ no script tag emitted at all.
Agent name shown to visitors
The widget header label resolves with this fallback chain:
-
agent.persona.nameโ set in Agent โ Customize โ Persona โ Display name. This is the visitor-facing persona; treat it as a stage name. -
agent.nameโ the internal label set in Agent โ Settings โ Basics โ Name. Used when the persona display name is empty, so an agent created through the dashboard ships with a sensible header without needing to also touch the persona form. -
Localized literal
AI assistantโ last-resort fallback when both fields are empty (legacy seed data).
Toggle changes apply immediately
Saving Marketing โ Marketing-site widget flushes
the marketing.demo_agent_id cache (5-minute TTL) and
the per-id marketing.demo_agent_id.explicit_valid.*
cache (2-minute TTL) so the next marketing-page request reflects
the change. Without the flush, toggling off could leave the demo
widget visible for up to 5 minutes (client report 2026-05-23).
Open marketing tabs also pick up the change without a hard reload.
The widget mount payload ships as the marketingWidget
Inertia shared prop, and a small controller component
(resources/js/components/marketing-widget-mount.tsx)
reactively injects or tears down the widget <script>
tag whenever the prop changes. Two trigger paths cover the common
cases:
-
Same-tab navigation โ any Inertia visit
between marketing pages refreshes shared props; the controller's
useEffectcompares the newagent_idto the live DOM and remounts or removes the widget as needed. -
Cross-tab focus โ when a backgrounded
marketing tab regains focus, the controller dispatches a
router.reload({ only: ['marketingWidget'] })partial reload so an admin toggling the widget in a sibling tab takes effect on the marketing tab without a manual refresh. Client report 2026-05-25.
CORS
The agent you pick must have your marketing site's origin (the
APP_URL) in its allowed_origins. Saving
the marketing widget with the agent picked auto-appends the current
APP_URL to the agent's allowed_origins if
it isn't already there โ so the widget works the moment you save.
Disabling the widget does not remove origins; you can
safely toggle the widget off and back on without losing CORS
configuration on the agent.