NewEmbeddable Widget

Embed Widget

Add an AI chat widget to any website with a single script tag. Works like Intercom, powered by your ASH agents.

One Script

Just paste a script tag. No React, no build tools required on the host site.

Floating or Embedded

Show as a floating chat bubble or embed directly into any container element.

Fully Customizable

Match your brand with custom colors, sizes, position, and greeting messages.

Quick Start

Add this snippet before </body> on any page:

HTML
<!-- ASH Widget -->
<script>
  window.AshSettings = {
    apiBasePath: 'https://your-api.com/api',
    agent: 'your-agent-slug'
  };
  (function(){var w=window;var a=w.Ash;if(typeof a==="function"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://cdn.your-domain.com/ash-widget.js';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();
</script>

Configuration Options

Customize the widget to match your needs:

Configuration
window.AshSettings = {
  // Required
  apiBasePath: 'https://your-api.com/api',

  // Optional: Agent slug (auto-selects first agent if not specified)
  agent: 'your-agent-slug',

  // Position: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'embedded'
  position: 'bottom-right',

  // For embedded mode, specify the container element ID
  containerId: 'my-widget-container',

  // Resume an existing session
  sessionId: 'session_abc123',

  // Start with widget open
  open: false,

  // Custom launcher button text
  launcherText: 'Chat with us',

  // Hide the default launcher (for custom triggers)
  hideLauncher: false,

  // Theme customization
  theme: {
    accentColor: '#ccff00',      // Primary color
    backgroundColor: '#0a0a0a',  // Widget background
    textColor: '#f3f4f6',        // Text color
    borderRadius: '16px'         // Border radius
  },

  // Widget dimensions (floating mode only)
  size: {
    width: '400px',
    height: '600px',
    maxHeight: '80vh'
  },

  // Z-index (default: max z-index)
  zIndex: 2147483647,

  // Greeting message shown before first interaction
  greeting: 'Hi! How can I help you today?',

  // Input placeholder
  placeholder: 'Type a message...',

  // Initial context data (passed with every message)
  context: {
    userId: 'user_123',
    page: 'pricing',
    customData: { plan: 'pro' }
  }
};

JavaScript API

Control the widget programmatically from your JavaScript code:

API Commands
// Open/close the widget
Ash('open');
Ash('close');
Ash('toggle');

// Show/hide the entire widget
Ash('show');
Ash('hide');

// Show/hide just the launcher button
Ash('showLauncher');
Ash('hideLauncher');

// Update settings dynamically
Ash('update', {
  greeting: 'New greeting!',
  theme: { accentColor: '#ff6b6b' }
});

// Shutdown and remove the widget
Ash('shutdown');

// Re-initialize with new settings
Ash('boot', {
  apiBasePath: 'https://new-api.com',
  agent: 'different-agent'
});

Context & Data API

Push data to the widget and send messages programmatically. This enables your app to share context with the AI agent.

Context Commands
// Set context data (replaces existing context)
Ash('setContext', {
  userId: 'user_123',
  currentPage: 'checkout',
  cartItems: ['item_1', 'item_2']
});

// Update context (merges with existing)
Ash('updateContext', { cartTotal: 99.99 });

// Clear all context
Ash('clearContext');

// Send a message programmatically
Ash('sendMessage', 'What products do you recommend?');

// Send a message with additional one-time context
Ash('sendMessageWithContext', 'Help me with this', {
  selectedProduct: 'SKU-12345',
  error: 'Payment failed'
});

// Query current state
Ash('getSessionId', (sessionId) => {
  console.log('Current session:', sessionId);
});

Ash('getContext', (context) => {
  console.log('Current context:', context);
});

Ash('getMessages', (messages) => {
  console.log('Conversation history:', messages);
});

Event Hooks

Listen to widget events to integrate with your application. Perfect for analytics, UI updates, or custom tool handling.

Event Callbacks
window.AshSettings = {
  apiBasePath: 'https://your-api.com/api',

  // Basic lifecycle events
  onOpen: () => console.log('Widget opened'),
  onClose: () => console.log('Widget closed'),
  onSessionStart: (sessionId) => console.log('Session:', sessionId),

  // Message events
  onMessageSent: (message) => {
    analytics.track('chat_message_sent', { message });
  },
  onMessageReceived: (message) => {
    analytics.track('chat_message_received');
  },

  // Streaming events
  onStreamStart: () => {
    showTypingIndicator();
  },
  onStreamDelta: (delta, fullContent) => {
    // Called for each chunk of streaming content
    updateLivePreview(fullContent);
  },
  onStreamEnd: (fullContent) => {
    hideTypingIndicator();
  },

  // Tool events - react to agent actions!
  onToolUse: (event) => {
    console.log('Agent using tool:', event.toolName, event.input);
    if (event.toolName === 'create_order') {
      showOrderPending(event.input);
    }
  },
  onToolResult: (event) => {
    console.log('Tool result:', event.result);
    if (!event.isError) {
      refreshOrderStatus();
    }
  },

  // Error handling
  onError: (error, code) => {
    console.error('Widget error:', error, code);
    showErrorToast(error);
  },

  // Catch-all event handler
  onEvent: (event) => {
    // All events come through here
    analytics.track('ash_event', { type: event.type, ...event });
  }
};

Embedded Mode

Instead of a floating widget, embed the chat directly into your page layout. The widget will fill its container 100%.

Embedded Example
<!-- Container with fixed height -->
<div id="chat-container" style="height: 600px;"></div>

<script>
  window.AshSettings = {
    apiBasePath: 'https://your-api.com/api',
    agent: 'support-agent',
    position: 'embedded',  // Fills container 100%
    containerId: 'chat-container',
    theme: { borderRadius: '12px' }
  };
  // ... loader script
</script>

Note: In embedded mode, make sure to set a height on the container element. No floating launcher button is shown — the widget is always visible.

Self-Hosting the Widget

Build and host the widget bundle on your own infrastructure:

Terminal
# Build the embed bundle
cd harness/packages/ash-ai
pnpm build:embed

# Output: dist/ash-widget.js (~50KB gzipped)

Serve dist/ash-widget.js from your CDN and update the src in the loader script.

Generating Embed Code

Use the helper functions to generate embed snippets programmatically:

TypeScript
import { generateEmbedSnippet } from '@conviction-labs/ash-ai/embed';

const snippet = generateEmbedSnippet('https://cdn.example.com/ash-widget.js', {
  apiBasePath: 'https://api.example.com',
  agent: 'support-agent',
  greeting: 'Hello! How can I help?',
  theme: { accentColor: '#0066ff' }
});

console.log(snippet);
// Outputs the full HTML snippet ready to copy

Ready to Embed?

Create an agent in your project, then grab the embed code from the agent settings.