Sharely.ai Web Control
The Sharely.ai Web Control allows you to embed intelligent AI agents directly into your web applications, providing a seamless, branded experience for your users.
What is the Web Control?
The Sharely.ai Web Control is an embeddable JavaScript component that brings the full power of Sharely.ai agents into your application:
- Fully Customizable UI - Match your brand and design system
- Your Domain - Host on your own domain with your branding
- Integrated Experience - Seamlessly blend AI into your user experience
- Programmatic Control - Full API control over agent behavior and appearance
- Flexible Authentication - Support for both anonymous and authenticated users
- Role-Based Access Control - Built-in RBAC support for enterprise applications
When to Use Web Control
Use Web Control when you want to:
- ✅ Embed AI capabilities directly into your existing application
- ✅ Maintain complete control over the user experience and branding
- ✅ Integrate with your existing authentication system
- ✅ Implement role-based content access control
- ✅ Provide a native, seamless AI assistant experience
Compare to Sharely.ai Hosted Agents:
| Feature | Web Control | Hosted Agents |
|---|---|---|
| Hosting | Your domain | Sharely.ai domain |
| Branding | Fully customizable | Sharely.ai branding |
| Authentication | Your auth system | Sharely.ai auth |
| Integration | Embedded in app | Standalone links |
| Development | Requires coding | No code needed |
| Best for | Custom applications | Quick launches, sharing |
Two Authentication Scenarios
Sharely.ai Web Control supports two distinct authentication patterns to fit your application's needs.
Scenario 1: Anonymous to Verified Users
How it works:
- User accesses your application without logging in
- Web Control initializes with anonymous user
- User can interact with AI assistant immediately
- Optionally, user can verify their identity later
- Conversation history is preserved after verification
When to use:
- Public websites where anyone can access the AI
- Trial/freemium experiences
- Lead capture workflows
- Demo environments
Key characteristics:
- Immediate access, no authentication required
- User identified by workspace ID only
- Can convert anonymous users to verified users
- Simplified onboarding
Example use cases:
- Website chatbot for visitor engagement
- Product demo assistant
- Lead qualification bot
- Public knowledge base assistant
Scenario 2: Authenticated Integration
How it works:
- User logs in to your application using your authentication system
- Your backend generates a Sharely.ai token for the authenticated user
- Frontend initializes Web Control with the generated token
- AI assistant has full user context and role-based permissions
- User maintains their identity throughout the session
When to use:
- Enterprise applications with existing auth
- Customer portals with personalized content
- Applications requiring role-based access control (RBAC)
- SaaS platforms with multi-tenant requirements
Key characteristics:
- Seamless integration with your authentication
- Role-based content filtering
- Personalized AI experiences
- Full user context and history
Example use cases:
- Customer support portal
- Internal knowledge assistant
- Partner/reseller portals
- Enterprise SaaS applications
Installation
1. Include the Sharely.ai Script
Add the Sharely.ai Web Control script to your HTML:
<script type="module" crossorigin src="https://webcontrol.sharely.ai/assets/sharelyai.js"></script>Example in Next.js:
import Script from 'next/script';
<Script
type="module"
crossOrigin
src="https://webcontrol.sharely.ai/assets/sharelyai.js"
strategy="afterInteractive"
/>Example in React:
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://webcontrol.sharely.ai/assets/sharelyai.js';
script.type = 'module';
script.crossOrigin = 'true';
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, []);3. Add the Container Element
Add a container div where you want the Web Control to appear:
<div id="sharelyai-webcontroller-id"></div>Note: The ID can be customized, but the default is sharelyai-webcontroller-id.
3. Initialize the Web Control
Initialize the Web Control with your configuration (see scenarios below).
Scenario 1: Anonymous Implementation
Basic Setup
For anonymous users, initialize with just your workspace ID:
<!DOCTYPE html>
<html>
<head>
<title>My App with Sharely AI</title>
<script type="module" crossorigin src="https://webcontrol.sharely.ai/assets/sharelyai.js"></script>
</head>
<body>
<h1>Welcome to My App</h1>
<!-- Web Control Container -->
<div id="sharelyai-webcontroller-id"></div>
<script>
// Initialize when page loads
window.addEventListener('load', function() {
if (window.sharelyai) {
window.sharelyai.initialize({
workspaceId: 'your-workspace-id',
mode: 'placed-inline',
displayMode: {
OPEN_BY_DEFAULT: true,
WIDTH: '100%',
MODE: 'PRIVATE',
VIEWS: {
CHAT: { SHOW: true },
SEARCH: { SHOW: true },
BROWSE: { SHOW: true }
}
}
});
window.sharelyai.render();
}
});
</script>
</body>
</html>With User Identification
Even in anonymous mode, you can provide a user identifier for tracking:
window.sharelyai.initialize({
workspaceId: 'your-workspace-id',
externalUserId: 'anonymous-user-' + Date.now(), // Optional tracking ID
mode: 'placed-inline',
displayMode: {
OPEN_BY_DEFAULT: true,
WIDTH: '100%',
MODE: 'PRIVATE',
VIEWS: {
CHAT: { SHOW: true },
SEARCH: { SHOW: true },
BROWSE: { SHOW: true }
}
}
});
window.sharelyai.render();Scenario 2: Authenticated Implementation
Backend Token Generation
Your backend must generate a Sharely.ai token when users log in. This follows the two-step authentication process:
Step 1: Generate API Access Token
// Node.js/Express example
const API_KEY = process.env.SHARELY_API_KEY;
const WORKSPACE_ID = process.env.SHARELY_WORKSPACE_ID;
const ORGANIZATION_ID = process.env.SHARELY_ORGANIZATION_ID;
async function generateAPIAccessToken(customerRoleId) {
const response = await fetch(
`https://api.sharely.ai/workspaces/${WORKSPACE_ID}/generate-access-key-token`,
{
method: 'POST',
headers: {
'x-api-key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
customerRoleId: customerRoleId // Optional: for RBAC
})
}
);
if (!response.ok) {
throw new Error('Failed to generate API token');
}
return await response.json();
}Step 2: Create User Space Token
async function createUserSpaceToken(apiToken, userId) {
const response = await fetch(
`https://api.sharely.ai/workspaces/${WORKSPACE_ID}/activate-or-retrieve-user-space`,
{
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiToken}`,
'organizationId': ORGANIZATION_ID,
'Content-Type': 'application/json'
},
body: JSON.stringify({
workspaceId: WORKSPACE_ID,
customerIdString: userId // User email or custom ID
})
}
);
if (!response.ok) {
throw new Error('Failed to create user space');
}
return await response.json();
}Complete Login Endpoint
// Express endpoint that returns Sharely token on login
app.post('/api/login', async (req, res) => {
try {
const { email, password } = req.body;
// Your authentication logic
const user = await authenticateUser(email, password);
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Determine user's role (optional, for RBAC)
const customerRoleId = getUserRole(user); // e.g., "premium-user", "admin"
// Generate API access token with role
const apiToken = await generateAPIAccessToken(customerRoleId);
// Create user space token (role inherited automatically)
const userSpace = await createUserSpaceToken(apiToken.token, user.email);
// Return tokens to frontend
res.json({
user: {
id: user.id,
email: user.email
},
sharely: {
token: userSpace.token,
spaceId: userSpace.spaceId
}
});
} catch (error) {
console.error('Login error:', error);
res.status(500).json({ error: error.message });
}
});Frontend Initialization
After user logs in, initialize the Web Control with the token from your backend:
// Fetch Sharely token from your backend
async function initializeSharelyForUser() {
try {
// Login or get existing session
const response = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: userEmail,
password: userPassword
})
});
const data = await response.json();
// Initialize Web Control with external token
if (window.sharelyai) {
window.sharelyai.initialize({
workspaceId: 'your-workspace-id',
externalToken: data.sharely.token, // Token from backend
spaceId: data.sharely.spaceId, // Space ID from backend
externalUserId: data.user.email, // User identifier
mode: 'placed-inline',
displayMode: {
OPEN_BY_DEFAULT: true,
WIDTH: '100%',
MODE: 'PRIVATE',
VIEWS: {
CHAT: { SHOW: true },
SEARCH: { SHOW: true },
BROWSE: { SHOW: true }
}
}
});
window.sharelyai.render();
}
} catch (error) {
console.error('Failed to initialize Sharely:', error);
}
}
// Call when user is authenticated
initializeSharelyForUser();Complete React Example
import { useEffect, useState } from 'react';
function SharelyWidget({ user }) {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
if (!user) return;
const initializeSharely = async () => {
try {
// Fetch Sharely token for authenticated user
const response = await fetch('/api/sharely-token', {
method: 'GET',
headers: {
'Authorization': `Bearer ${user.sessionToken}`
}
});
if (!response.ok) {
throw new Error('Failed to get Sharely token');
}
const { token, spaceId } = await response.json();
// Wait for Sharely script to load
if (!window.sharelyai) {
throw new Error('Sharely script not loaded');
}
// Initialize with external token
window.sharelyai.initialize({
workspaceId: process.env.NEXT_PUBLIC_SHARELY_WORKSPACE_ID,
externalToken: token,
spaceId: spaceId,
externalUserId: user.email,
mode: 'placed-inline',
displayMode: {
OPEN_BY_DEFAULT: true,
WIDTH: '100%',
MODE: 'PRIVATE',
VIEWS: {
CHAT: { SHOW: true },
SEARCH: { SHOW: true },
BROWSE: { SHOW: true }
}
}
});
window.sharelyai.render();
setLoading(false);
} catch (err) {
console.error('Sharely initialization error:', err);
setError(err.message);
setLoading(false);
}
};
initializeSharely();
}, [user]);
if (loading) return <div>Loading AI Assistant...</div>;
if (error) return <div>Error loading AI Assistant: {error}</div>;
return (
<div style={{ width: '100%', height: '600px' }}>
<div id="sharelyai-webcontroller-id" />
</div>
);
}
export default SharelyWidget;Initialization API Reference
window.sharelyai.initialize(config)
Initializes the Sharely.ai Web Control with the specified configuration.
Parameters
The config object accepts the following parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
workspaceId | string | Yes | Your Sharely.ai workspace UUID |
externalToken | string | No | Pre-generated user space token (for authenticated mode) |
spaceId | string | No | Space ID from backend (required when using externalToken) |
externalUserId | string | No | User identifier (UUID or custom string like email) |
lang | string | No | UI language code (default: "en"). Supported: "en", "es" |
langKnowledge | string | No | Knowledge content language filter (default: "en"). Supported: "en", "es" |
mode | string | No | Display mode: "placed-inline" (default), "floating", "modal" |
saveSpaceNumMgs | number | No | Number of messages to save locally (default: 1) |
displayMode | object | No | UI display configuration (see below) |
displayMode Object
Controls the appearance and behavior of the Web Control UI:
| Property | Type | Default | Description |
|---|---|---|---|
OPEN_BY_DEFAULT | boolean | true | Whether widget is open when initialized |
WIDTH | string | "100%" | Widget width (CSS value: "100%", "400px", etc.) |
MODE | string | "PRIVATE" | Privacy mode: "PRIVATE" or "PUBLIC" |
VIEWS | object | See below | Configure which views are available |
VIEWS Object
Enable or disable specific views within the Web Control:
VIEWS: {
CHAT: { SHOW: true }, // Enable chat interface
SEARCH: { SHOW: true }, // Enable search interface
BROWSE: { SHOW: true } // Enable browse/knowledge navigation
}Complete Example
window.sharelyai.initialize({
// Required
workspaceId: '550e8400-e29b-41d4-a716-446655440000',
// For authenticated mode
externalToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
spaceId: 'space-uuid-123',
// User identification
externalUserId: 'user@example.com',
// Language configuration
lang: 'en', // UI language (English)
langKnowledge: 'en', // Knowledge content language (English)
// Display configuration
mode: 'placed-inline',
saveSpaceNumMgs: 5,
displayMode: {
OPEN_BY_DEFAULT: true,
WIDTH: '100%',
MODE: 'PRIVATE',
VIEWS: {
CHAT: { SHOW: true },
SEARCH: { SHOW: true },
BROWSE: { SHOW: true }
}
}
});window.sharelyai.render()
Renders the Web Control into the container element. Must be called after initialize().
window.sharelyai.initialize({ /* config */ });
window.sharelyai.render();window.sharelyai.config()
Returns the current language configuration of the Web Control.
Returns: Object with current language settings
const currentConfig = window.sharelyai.config();
console.log(currentConfig);
// Output:
// {
// lang: "en",
// langKnowledge: "en"
// }Properties:
| Property | Type | Description |
|---|---|---|
lang | string | Current UI language code ("en" or "es") |
langKnowledge | string | Current knowledge content language filter ("en" or "es") |
Use cases:
- Check the current UI language setting
- Verify which knowledge language filter is active
- Debug language configuration issues
- Programmatically detect language state
Example - Check configuration:
// Initialize with specific languages
window.sharelyai.initialize({
workspaceId: 'your-workspace-id',
lang: 'es', // Spanish UI
langKnowledge: 'en' // English knowledge content
});
// Later, check what's configured
const config = window.sharelyai.config();
if (config.lang === 'es') {
console.log('UI is in Spanish');
}
if (config.langKnowledge === 'en') {
console.log('Showing English knowledge content');
}Role-Based Access Control (RBAC)
When using authenticated mode, you can implement role-based content access control by including a customerRoleId when generating API tokens.
How RBAC Works
- Create roles in your Sharely.ai workspace (e.g., "premium-user", "admin", "basic-user")
- Assign knowledge to specific roles via the Knowledge Roles API
- Generate tokens with roles by including
customerRoleIdin token generation - Users see filtered content - Web Control automatically shows only role-permitted content
Backend Implementation
// Determine user's role based on your app logic
function getUserRole(user) {
if (user.isAdmin) return 'admin-role';
if (user.subscriptionTier === 'premium') return 'premium-user';
return 'basic-user';
}
// Generate token with role
async function generateTokenWithRole(user) {
const customerRoleId = getUserRole(user);
// Step 1: Generate API token with role
const apiToken = await fetch(
`https://api.sharely.ai/workspaces/${WORKSPACE_ID}/generate-access-key-token`,
{
method: 'POST',
headers: {
'x-api-key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({ customerRoleId })
}
).then(res => res.json());
// Step 2: Create user space (role inherited automatically)
const userSpace = await fetch(
`https://api.sharely.ai/workspaces/${WORKSPACE_ID}/activate-or-retrieve-user-space`,
{
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiToken.token}`,
'organizationId': ORGANIZATION_ID,
'Content-Type': 'application/json'
},
body: JSON.stringify({
workspaceId: WORKSPACE_ID,
customerIdString: user.email
})
}
).then(res => res.json());
return userSpace;
}The role is now embedded in the token - when you initialize Web Control with this token, content is automatically filtered by role.
Best Practices
Token Management
✅ DO:
- Generate tokens on your backend, never expose API keys to frontend
- Implement token refresh logic (tokens expire after 24 hours)
- Store tokens securely (session storage, not local storage)
- Validate user authentication before generating tokens
❌ DON'T:
- Expose your Sharely API key in frontend code
- Share tokens between different users
- Store tokens in cookies without proper security flags
- Generate tokens without user authentication
Error Handling
async function initializeSharelyWithErrorHandling() {
try {
// Check if script loaded
if (!window.sharelyai) {
throw new Error('Sharely script not loaded');
}
// Fetch token
const response = await fetch('/api/sharely-token');
if (!response.ok) {
throw new Error(`Token fetch failed: ${response.status}`);
}
const { token, spaceId } = await response.json();
// Initialize
window.sharelyai.initialize({
workspaceId: WORKSPACE_ID,
externalToken: token,
spaceId: spaceId,
externalUserId: user.email,
mode: 'placed-inline',
displayMode: {
OPEN_BY_DEFAULT: true,
WIDTH: '100%',
MODE: 'PRIVATE',
VIEWS: {
CHAT: { SHOW: true },
SEARCH: { SHOW: true },
BROWSE: { SHOW: true }
}
}
});
window.sharelyai.render();
} catch (error) {
console.error('Sharely initialization failed:', error);
// Show fallback UI
document.getElementById('sharelyai-webcontroller-id').innerHTML = `
<div style="padding: 20px; border: 1px solid #ddd; border-radius: 4px;">
<p>AI Assistant temporarily unavailable. Please try again later.</p>
</div>
`;
}
}User Experience
Loading States:
// Show loading indicator
const container = document.getElementById('sharelyai-webcontroller-id');
container.innerHTML = '<div class="loading">Loading AI Assistant...</div>';
// Initialize
try {
await initializeSharely();
} catch (error) {
container.innerHTML = '<div class="error">Failed to load</div>';
}Lazy Loading:
// Only initialize when user interacts
document.getElementById('open-ai-button').addEventListener('click', function() {
initializeSharely();
this.disabled = true;
this.textContent = 'AI Assistant Loading...';
});Security Recommendations
- Always use HTTPS for production deployments
- Validate users on your backend before generating tokens
- Implement rate limiting on token generation endpoints
- Use Content Security Policy headers to restrict script sources
- Monitor token usage for suspicious activity
- Rotate API keys periodically
Troubleshooting
Web Control Not Appearing
Problem: Nothing appears in the container div
Solutions:
- Check that the script is loaded:
console.log(window.sharelyai) - Verify the container ID matches your initialization
- Ensure
render()is called afterinitialize() - Check browser console for errors
Token Generation Failures
Problem: Backend fails to generate tokens
Solutions:
- Verify API key is correct and not expired
- Check that workspace ID and organization ID are correct
- Ensure role exists (if using RBAC)
- Check API endpoint URLs are correct
Content Not Filtered by Role
Problem: Users see content outside their role
Solutions:
- Verify RBAC is enabled for your workspace
- Check that roles are assigned to knowledge items
- Confirm
customerRoleIdis included in token generation - Verify token contains role information (decode JWT)
Related Documentation
APIs
- Spaces API - User space provisioning and token generation
- Roles API - Create and manage RBAC roles
- Knowledge Roles API - Assign knowledge to roles
- Authentication - API authentication guide
Concepts
- Roles Concept - Understanding workspace, space, and knowledge roles
- Space Concept - How spaces work in Sharely.ai
- Knowledge Concept - Knowledge management overview
Getting Help
- Documentation: https://docs.sharely.ai (opens in a new tab)
- Support Email: support@sharely.ai
- API Status: https://status.sharely.ai (opens in a new tab)
Next Steps
- Get your API credentials - Sign up at https://app.sharely.ai (opens in a new tab)
- Choose your scenario - Anonymous or Authenticated integration
- Implement backend token generation - Use the Spaces API
- Initialize the Web Control - Add to your frontend
- Test thoroughly - Verify authentication and content filtering
- Deploy to production - Launch your AI-powered application