⚠️ EXAMPLE CODE - NO OFFICIAL SUPPORTThis is a demonstration/example implementation provided as-is for educational purposes and inspiration. It is not an officially supported product and should be considered experimental. Use at your own risk.
- ❌ No official support or maintenance guarantees
- ❌ Not recommended for production use without thorough security review
- ✅ Useful as a reference implementation
- ✅ Community contributions welcome
Embeddable support widget that integrates with PromptlyAgent's chat API. Provides AI-powered, context-aware assistance with element selection and screenshot capture.
This demo implementation exposes API credentials in client-side JavaScript.
This example uses Option 4: Direct API with Exposed Token which is:
- ✅ ACCEPTABLE for demos, local development, and testing
- ❌ NOT ACCEPTABLE for production websites
- ❌ INSECURE - API tokens are visible in browser source
For production deployment, you MUST implement one of these secure approaches:
- Widget ID instead of API token
- Domain allowlist validation
- Rate limiting per widget
- Similar to Intercom/Zendesk pattern
- Status: Planned for Phase 2
- Widget calls your backend endpoint
- Backend proxies to PromptlyAgent with stored credentials
- Full control over security and validation
- Status: Example implementations coming in Phase 3
See "Security Considerations" section below for detailed analysis of all security options.
Element Selection for Contextual Help

Bug Reporting with Visual Context

- 💬 AI-Powered Chat - Real-time streaming responses with PromptlyAgent
- 🎯 Element Selection - Click-to-select DOM elements for contextual help
- 📸 Screenshot Capture - Automatic visual context capture
- 🔄 Session Persistence - Cookie-based session management across page loads
- ⚡ Real-time Streaming - Server-Sent Events (SSE) for instant responses
- 📱 Mobile Responsive - Works on desktop, tablet, and mobile
- 🎨 Customizable - Theme colors, position, and behavior
- 🔧 Standalone - Single JavaScript file, no build process required
You need:
- A running PromptlyAgent instance
- API Bearer token (generated in Filament admin)
- Promptly Manual agent ID
- CORS configured to allow your domain
Add html2canvas library (required for screenshot capture):
<!-- Load html2canvas for screenshot capture -->
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script><!-- Load PromptlySupport widget -->
<script src="promptly-support.js"></script><script>
PromptlySupport.init({
// Required: Your PromptlyAgent instance URL
apiBaseUrl: 'https://your-instance.com',
// Required: Bearer token (⚠️ EXPOSED - DEMO ONLY)
apiToken: 'your-api-token-here',
// Required: Promptly Manual agent ID
agentId: 123,
// Optional: Customization
position: 'bottom-right',
primaryColor: '#3b82f6',
enableScreenshots: true,
debug: false
});
</script>Open your page, click the support button (bottom-right corner), and start chatting!
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
apiBaseUrl |
string | - | ✅ Yes | PromptlyAgent instance URL (e.g., 'https://promptly.example.com') |
apiToken |
string | - | ✅ Yes | Bearer token for authentication ( |
agentId |
number | - | ✅ Yes | Agent ID (Promptly Manual agent) |
position |
string | 'bottom-right' |
No | Widget position: 'bottom-right', 'bottom-left', 'top-right', 'top-left' |
primaryColor |
string | '#3b82f6' |
No | Theme color (CSS color value) |
sessionCookieName |
string | 'promptly_session_id' |
No | Cookie name for session persistence |
sessionCookieExpiry |
number | 30 |
No | Cookie expiry in days |
fabText |
string | '?' |
No | Floating action button text |
widgetTitle |
string | 'Help & Support' |
No | Chat window header title |
placeholderText |
string | 'Ask a question...' |
No | Input field placeholder |
welcomeMessage |
string | 'Hi! How can I help you today?' |
No | Initial greeting message |
enableScreenshots |
boolean | true |
No | Enable screenshot capture (requires html2canvas) |
debug |
boolean | false |
No | Enable debug logging to console |
PromptlySupport.init({
apiBaseUrl: 'https://promptly.example.com',
apiToken: 'prod_abc123...',
agentId: 5,
position: 'bottom-left',
primaryColor: '#10b981',
fabText: '💬',
widgetTitle: 'Support Chat',
welcomeMessage: 'Hello! How may I assist you?',
enableScreenshots: true,
debug: true
});PromptlySupport.init(config)Initialize the widget with configuration object. Must be called before the widget can be used.
Returns: void
Clear the current session and create a new one. Clears conversation history and selected element.
PromptlySupport.newSession();Returns: void
Programmatically close the chat window.
PromptlySupport.close();Returns: void
You can also configure via data-promptly-config attribute:
<script
src="promptly-support.js"
data-promptly-config='{"apiBaseUrl":"https://your-instance.com","apiToken":"your-token","agentId":123}'>
</script>- Log into your PromptlyAgent Filament admin panel
- Navigate to Settings → API Tokens
- Click "Generate New Token"
- Give it a name (e.g., "Support Widget - Demo")
- Copy the generated token
⚠️ Important: Store this token securely - it won't be shown again
./vendor/bin/sail artisan tinker
# Generate token for a user
$user = User::first();
$token = $user->createToken('support-widget')->plainTextToken;
echo $token;./vendor/bin/sail artisan tinker
# Find Promptly Manual agent ID
$agent = Agent::where('name', 'Promptly Manual')->first();
echo $agent->id;./vendor/bin/sail artisan tinker
Agent::where('name', 'LIKE', '%Manual%')->get(['id', 'name']);- Navigate to Agents in Filament admin
- Find "Promptly Manual" agent
- Click to edit
- The ID is in the URL:
/admin/agents/{id}/edit
Your PromptlyAgent instance must have:
The widget uses these API endpoints:
POST /api/v1/chat/sessions- Create new chat sessionGET /api/v1/chat/sessions/{id}- Get session detailsPOST /api/v1/chat/stream- Send message with SSE streaming
Configure CORS in config/cors.php to allow requests from your widget domain:
'paths' => ['api/*'],
'allowed_origins' => ['https://yourdomain.com'],
'allowed_methods' => ['GET', 'POST'],
'allowed_headers' => ['Content-Type', 'Authorization', 'Accept'],
'supports_credentials' => true,The widget is designed to work with the "Promptly Manual" agent, which has specialized tools for:
database_schema_inspector- Database introspectionsafe_database_query- Read-only queriessecure_file_reader- File reading with security filteringdirectory_listing- File system navigationcode_search- Code pattern searchroute_inspector- Laravel route mapping
Ensure this agent exists and is active in your PromptlyAgent instance.
| Browser | Version | Support |
|---|---|---|
| Chrome | 90+ | ✅ Full |
| Edge | 90+ | ✅ Full |
| Firefox | 88+ | ✅ Full |
| Safari | 14+ | ✅ Full |
| Mobile Safari | iOS 14+ | ✅ Full |
| Mobile Chrome | Android 10+ | ✅ Full |
- ES6+ JavaScript (async/await, arrow functions, classes)
- Fetch API
- FormData API
- ReadableStream API (for SSE streaming)
- Promises
- localStorage/Cookies
How it works:
- Widget configured with actual API token in JavaScript
- Widget calls PromptlyAgent directly
Pros:
- ✅ Simplest setup for demos
- ✅ No backend needed
Cons:
- ❌ INSECURE - Token exposed in browser
- ❌ Anyone can extract and abuse token
- ❌ Only suitable for examples/demos
Status: Planned for Phase 2
How it will work:
- Customer creates widget account in PromptlyAgent admin
- Receives unique widget ID (non-sensitive, public identifier)
- Widget configuration:
widgetId: 'widget_abc123'(no API token) - Widget calls PromptlyAgent directly with widget ID
- PromptlyAgent validates widget ID server-side
Security features:
- Domain allowlist (CORS + Referer validation)
- Rate limiting per widget
- Active subscription status checks
- Agent configuration enforcement
- No exposed credentials
Similar to: Intercom, Zendesk, Crisp pattern
Status: Example implementations coming in Phase 3
How it works:
- Customer implements backend endpoint:
/api/support/chat - Backend stores PromptlyAgent credentials securely
- Widget calls customer's backend (no credentials)
- Backend proxies to PromptlyAgent with validation
Security features:
- Full control over security logic
- Can add custom business logic
- Rate limiting on customer's terms
- Can log/audit all requests
- Most secure option
Best for: Enterprise deployments, self-hosted solutions
Check:
- JavaScript console for errors
- Widget script loaded correctly:
<script src="promptly-support.js"></script> - html2canvas loaded before widget:
<script src="https://...html2canvas..."></script> - Configuration provided correctly in
init()call - No JavaScript errors preventing initialization
Debug:
PromptlySupport.init({
// ... your config
debug: true // Enable debug logging
});Error: Access to fetch at 'https://...' from origin 'https://...' has been blocked by CORS policy
Solution:
Add your domain to config/cors.php in PromptlyAgent:
'allowed_origins' => ['https://yourdomain.com'],Test CORS:
curl -H "Origin: https://yourdomain.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type,Authorization" \
-X OPTIONS \
https://your-promptly-instance.com/api/v1/chat/sessionsError: HTTP 401: Unauthorized
Causes:
- Invalid or expired API token
- Token not sent correctly in Authorization header
- Token doesn't have required permissions
Solution:
- Regenerate API token in Filament admin
- Verify token format:
Bearer your-token-here - Check token has API access permissions
Causes:
- Cookies blocked by browser settings
- Cookie
SameSitepolicy issues - Third-party cookie restrictions
Solution:
- Check browser cookie settings
- Use same domain for widget and PromptlyAgent (avoids third-party cookies)
- Test in incognito/private mode
Causes:
- html2canvas library not loaded
enableScreenshotsset tofalse- CORS issues with images on page
- Browser security restrictions
Solution:
- Verify html2canvas loaded:
typeof html2canvas !== 'undefined' - Set
enableScreenshots: truein config - Check console for html2canvas errors
- Test without cross-origin images
Error: Messages appear all at once instead of streaming
Causes:
- SSE streaming not supported by browser
- Network proxy buffering responses
- Server not sending SSE events correctly
Solution:
- Test in supported browser (Chrome, Firefox, Safari)
- Check network tab for
text/event-streamcontent-type - Verify PromptlyAgent SSE implementation
examples/support-widget/
├── promptly-support.js # Main widget implementation (~1300 lines)
├── demo.html # Integration example page
├── README.md # This documentation
└── configuration.example.js # Configuration reference
-
Start PromptlyAgent instance:
cd /path/to/promptlyagent ./vendor/bin/sail up -d -
Generate API token (see "Getting API Token" section)
-
Find Promptly Manual agent ID (see "Finding Agent ID" section)
-
Start local web server:
cd examples/support-widget python3 -m http.server 8000 -
Open demo page:
http://localhost:8000/demo.html -
Update configuration in
demo.html:PromptlySupport.init({ apiBaseUrl: 'http://localhost', // Your local PromptlyAgent apiToken: 'YOUR_GENERATED_TOKEN', agentId: YOUR_AGENT_ID, debug: true });
Enable debug logging to see widget activity:
PromptlySupport.init({
// ... your config
debug: true
});This will log:
- Widget initialization
- Session creation/restoration
- Element selection events
- Screenshot capture
- API requests and responses
- Streaming events
The widget is available globally as PromptlySupport:
// Check widget state
console.log(PromptlySupport.state);
// Get current session
console.log(PromptlySupport.state.chatSession);
// View messages
console.log(PromptlySupport.state.messages);
// Programmatically control widget
PromptlySupport.ui.toggleChat();
PromptlySupport.selector.enable();
PromptlySupport.session.clearSession();- Standalone widget implementation
- UI module with FAB and chat window
- Element selector with visual highlighting
- Context capture with screenshots
- Session management with cookies
- API client with SSE streaming
- Demo page with examples
- Documentation with security warnings
- Widget Account System implementation in PromptlyAgent
- Database table:
widget_configurations - Filament admin resource for widget management
- API endpoint:
POST /api/v1/widget/{widgetId}/chat - Domain allowlist + rate limiting + CORS validation
- Widget updated to use
widgetIdinstead of API token - Migration guide from Option 4 to Option 1
- Node.js/Express proxy example
- PHP/Laravel proxy example
- Python/Flask proxy example
- Ruby/Rails proxy example
- Enterprise deployment guide
- TypeScript rewrite for type safety
- Unit tests with Jest/Vitest
- E2E tests with Playwright/Cypress
- Framework integrations (React/Vue/Angular wrappers)
- Advanced features (file attachments, rich text, voice input)
- Offline support with message queuing
- Multi-language support (i18n)
- Theming system (dark mode, custom themes)
- Analytics and usage tracking
MIT License
Built with ❤️ for PromptlyAgent
Remember: This is a demo implementation. Always implement proper security for production use.