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:

FeatureWeb ControlHosted Agents
HostingYour domainSharely.ai domain
BrandingFully customizableSharely.ai branding
AuthenticationYour auth systemSharely.ai auth
IntegrationEmbedded in appStandalone links
DevelopmentRequires codingNo code needed
Best forCustom applicationsQuick 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:

  1. User accesses your application without logging in
  2. Web Control initializes with anonymous user
  3. User can interact with AI assistant immediately
  4. Optionally, user can verify their identity later
  5. 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:

  1. User logs in to your application using your authentication system
  2. Your backend generates a Sharely.ai token for the authenticated user
  3. Frontend initializes Web Control with the generated token
  4. AI assistant has full user context and role-based permissions
  5. 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:

ParameterTypeRequiredDescription
workspaceIdstringYesYour Sharely.ai workspace UUID
externalTokenstringNoPre-generated user space token (for authenticated mode)
spaceIdstringNoSpace ID from backend (required when using externalToken)
externalUserIdstringNoUser identifier (UUID or custom string like email)
langstringNoUI language code (default: "en"). Supported: "en", "es"
langKnowledgestringNoKnowledge content language filter (default: "en"). Supported: "en", "es"
modestringNoDisplay mode: "placed-inline" (default), "floating", "modal"
saveSpaceNumMgsnumberNoNumber of messages to save locally (default: 1)
displayModeobjectNoUI display configuration (see below)

displayMode Object

Controls the appearance and behavior of the Web Control UI:

PropertyTypeDefaultDescription
OPEN_BY_DEFAULTbooleantrueWhether widget is open when initialized
WIDTHstring"100%"Widget width (CSS value: "100%", "400px", etc.)
MODEstring"PRIVATE"Privacy mode: "PRIVATE" or "PUBLIC"
VIEWSobjectSee belowConfigure 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:

PropertyTypeDescription
langstringCurrent UI language code ("en" or "es")
langKnowledgestringCurrent 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

  1. Create roles in your Sharely.ai workspace (e.g., "premium-user", "admin", "basic-user")
  2. Assign knowledge to specific roles via the Knowledge Roles API
  3. Generate tokens with roles by including customerRoleId in token generation
  4. 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

  1. Always use HTTPS for production deployments
  2. Validate users on your backend before generating tokens
  3. Implement rate limiting on token generation endpoints
  4. Use Content Security Policy headers to restrict script sources
  5. Monitor token usage for suspicious activity
  6. Rotate API keys periodically

Troubleshooting

Web Control Not Appearing

Problem: Nothing appears in the container div

Solutions:

  1. Check that the script is loaded: console.log(window.sharelyai)
  2. Verify the container ID matches your initialization
  3. Ensure render() is called after initialize()
  4. Check browser console for errors

Token Generation Failures

Problem: Backend fails to generate tokens

Solutions:

  1. Verify API key is correct and not expired
  2. Check that workspace ID and organization ID are correct
  3. Ensure role exists (if using RBAC)
  4. Check API endpoint URLs are correct

Content Not Filtered by Role

Problem: Users see content outside their role

Solutions:

  1. Verify RBAC is enabled for your workspace
  2. Check that roles are assigned to knowledge items
  3. Confirm customerRoleId is included in token generation
  4. Verify token contains role information (decode JWT)

Related Documentation

APIs

Concepts


Getting Help


Next Steps

  1. Get your API credentials - Sign up at https://app.sharely.ai (opens in a new tab)
  2. Choose your scenario - Anonymous or Authenticated integration
  3. Implement backend token generation - Use the Spaces API
  4. Initialize the Web Control - Add to your frontend
  5. Test thoroughly - Verify authentication and content filtering
  6. Deploy to production - Launch your AI-powered application