The standard
text
<script>1. Create the widget component
Save this as
text
PromptlyWidget.jsxjsx// PromptlyWidget.jsx — mounts the Promptly chat widget in a React SPA. 'use client'; // Next.js App Router only — harmless elsewhere import { useEffect } from 'react'; const SCRIPT_ID = 'promptly-embed-script'; export default function PromptlyWidget({ enabled = true }) { useEffect(() => { if (!enabled) return undefined; if (window.__promptlyLoaded || document.getElementById(SCRIPT_ID)) { return undefined; } const script = document.createElement('script'); script.id = SCRIPT_ID; script.src = 'https://api.promptly-assistant.com/widget/embed.js'; script.async = true; script.setAttribute('data-tenant', 'your-tenant-slug'); script.setAttribute('data-api-key', 'pk_your-api-key'); script.setAttribute('data-api-base', 'https://api.promptly-assistant.com'); document.body.appendChild(script); return () => { // The embed script has no destroy API — remove its DOM host and reset // the init guard so the widget can mount again after the next login. document.getElementById(SCRIPT_ID)?.remove(); document.getElementById('promptly-widget-host')?.remove(); delete window.__promptlyLoaded; delete window.Promptly; }; }, [enabled]); return null; }
The component:
- injects the Promptly embed script when it mounts (only once, even if rendered twice),
- removes the widget and resets its state when it unmounts,
- renders nothing itself, so it can live anywhere in your tree.
2. Render it once, near the root
jsximport PromptlyWidget from './components/PromptlyWidget'; function App() { return ( <> <YourRoutes /> <PromptlyWidget /> </> ); }
3. Apps behind a login
If your app requires sign-in, pass your auth state through the
text
enabledjsx<PromptlyWidget enabled={isLoggedIn} />
The widget appears right after login and is fully removed on logout — it never shows on your login screen.
4. Allowed domains
In Widget → Install → Allowed Domains, add every origin your app runs on — production domain, staging, and
text
http://localhost:5173Embedding the documentation too?
If you also embed your help center in the app (see Documentation → Settings → Embed), set "Help center URL on your site" to the page where the iframe lives. Chat answers that cite your documentation will then deep-link straight to that page (
text
?article=<slug>Troubleshooting
- Widget shows on the login page — you're rendering it unconditionally; pass .text
enabled={isLoggedIn} - Widget doesn't appear after login — check the browser console for a blocked-origin warning and verify your domain is in Allowed Domains.
- Widget stays after logout — make sure the component actually unmounts or receives ; the cleanup runs in both cases.text
enabled={false}