Skip to main content

Web Chat Widget

The Web Chat Widget allows you to embed Crew’s AI chat agents directly on your website. Visitors can interact with your agent without leaving your site.

Quick Start

Add the widget to your website with a single script:
<script>
  window.crewConfig = {
    crewId: 'your_crew_id',
    agentId: 'agent_chat'
  };
</script>
<script src="https://widget.usecrew.ai/chat.js" async></script>

Installation Methods

Add to your HTML before </body>:
<script>
  window.crewConfig = {
    crewId: 'crew_xyz789',
    agentId: 'agent_chat',
    position: 'bottom-right',
    primaryColor: '#6366F1'
  };
</script>
<script src="https://widget.usecrew.ai/chat.js" async></script>

React Component

npm install @crew/chat-widget
import { CrewChat } from '@crew/chat-widget';

function App() {
  return (
    <div>
      <CrewChat
        crewId="crew_xyz789"
        agentId="agent_chat"
        position="bottom-right"
        primaryColor="#6366F1"
      />
    </div>
  );
}

Vue Component

npm install @crew/chat-widget
<template>
  <div>
    <CrewChat
      crew-id="crew_xyz789"
      agent-id="agent_chat"
      position="bottom-right"
      primary-color="#6366F1"
    />
  </div>
</template>

<script>
import { CrewChat } from '@crew/chat-widget';

export default {
  components: { CrewChat }
};
</script>

Configuration

Basic Options

OptionTypeDefaultDescription
crewIdstringrequiredYour Crew ID
agentIdstringrequiredChat agent ID
positionstringbottom-rightWidget position
primaryColorstring#6366F1Theme color
titlestringChat with usHeader title
subtitlestringnullHeader subtitle
greetingstringautoInitial message

Positioning

window.crewConfig = {
  position: 'bottom-right', // or 'bottom-left'
  offsetX: 20, // pixels from edge
  offsetY: 20  // pixels from bottom
};

Theming

window.crewConfig = {
  theme: {
    primaryColor: '#6366F1',
    textColor: '#1F2937',
    backgroundColor: '#FFFFFF',
    headerBackground: '#6366F1',
    headerTextColor: '#FFFFFF',
    userBubbleColor: '#6366F1',
    userTextColor: '#FFFFFF',
    agentBubbleColor: '#F3F4F6',
    agentTextColor: '#1F2937',
    fontFamily: 'Inter, sans-serif',
    borderRadius: '12px'
  }
};

Custom Launcher

Replace the default launcher button:
window.crewConfig = {
  launcher: {
    type: 'custom',
    element: '#my-chat-button'
  }
};
<button id="my-chat-button">Chat with AI</button>

User Identification

Anonymous Users

By default, users are tracked anonymously with a session ID:
window.crewConfig = {
  user: {
    anonymous: true
  }
};

Identified Users

Pass user information for personalized experiences:
window.crewConfig = {
  user: {
    id: 'user_12345',
    name: 'John Smith',
    email: 'john@example.com',
    metadata: {
      plan: 'enterprise',
      accountId: 'acc_xyz'
    }
  }
};

Dynamic Identification

Update user info after page load:
window.CrewChat.identify({
  id: 'user_12345',
  name: 'John Smith',
  email: 'john@example.com'
});

JavaScript API

Open/Close Widget

// Open the chat widget
window.CrewChat.open();

// Close the widget
window.CrewChat.close();

// Toggle open/closed
window.CrewChat.toggle();

Send Messages

// Send a message as the user
window.CrewChat.sendMessage('I need help with my order');

// Trigger agent response
window.CrewChat.triggerAgent('Order #12345');

Events

window.CrewChat.on('ready', () => {
  console.log('Widget loaded');
});

window.CrewChat.on('open', () => {
  console.log('Chat opened');
});

window.CrewChat.on('close', () => {
  console.log('Chat closed');
});

window.CrewChat.on('message', (message) => {
  console.log('New message:', message);
});

window.CrewChat.on('conversation.started', (conversation) => {
  console.log('Conversation started:', conversation.id);
});

Unread Count

// Get unread message count
const count = window.CrewChat.getUnreadCount();

// Listen for changes
window.CrewChat.on('unreadCount', (count) => {
  updateBadge(count);
});

Pre-Chat Form

Collect information before starting the conversation:
window.crewConfig = {
  preChatForm: {
    enabled: true,
    title: 'Before we chat...',
    fields: [
      {
        name: 'name',
        type: 'text',
        label: 'Your name',
        required: true
      },
      {
        name: 'email',
        type: 'email',
        label: 'Email address',
        required: true
      },
      {
        name: 'topic',
        type: 'select',
        label: 'What can we help with?',
        options: [
          { value: 'sales', label: 'Sales inquiry' },
          { value: 'support', label: 'Technical support' },
          { value: 'other', label: 'Something else' }
        ]
      }
    ]
  }
};

Rich Messages

The widget supports rich message types:

Quick Replies

{
  "type": "quick_replies",
  "text": "What would you like to do?",
  "replies": [
    { "title": "Schedule appointment", "payload": "schedule" },
    { "title": "Check order status", "payload": "order_status" },
    { "title": "Talk to human", "payload": "human" }
  ]
}

Cards

{
  "type": "card",
  "title": "Premium Plan",
  "subtitle": "$99/month",
  "image": "https://example.com/plan.png",
  "buttons": [
    { "title": "Learn more", "url": "https://example.com/premium" },
    { "title": "Subscribe", "payload": "subscribe_premium" }
  ]
}

Carousels

{
  "type": "carousel",
  "items": [
    {
      "title": "Product A",
      "image": "https://example.com/a.png",
      "buttons": [{ "title": "View", "url": "/products/a" }]
    },
    {
      "title": "Product B",
      "image": "https://example.com/b.png",
      "buttons": [{ "title": "View", "url": "/products/b" }]
    }
  ]
}

Human Handoff

Transfer chat to a human agent:
window.crewConfig = {
  handoff: {
    enabled: true,
    triggerPhrases: ['speak to human', 'real person'],
    destination: 'intercom', // or 'zendesk', 'freshdesk', 'webhook'
    message: 'Connecting you with a team member...'
  }
};

Webhook Handoff

window.crewConfig = {
  handoff: {
    enabled: true,
    destination: 'webhook',
    webhookUrl: 'https://yourapp.com/handoff',
    payload: {
      conversation_id: '{{conversation_id}}',
      transcript: '{{transcript}}',
      user: '{{user}}'
    }
  }
};

Offline Mode

Configure behavior when outside business hours:
window.crewConfig = {
  offlineMode: {
    enabled: true,
    schedule: {
      timezone: 'America/New_York',
      hours: {
        monday: { start: '09:00', end: '17:00' },
        tuesday: { start: '09:00', end: '17:00' },
        // ...
      }
    },
    message: 'We\'re currently offline. Leave a message and we\'ll respond during business hours.',
    collectEmail: true
  }
};

Security

Content Security Policy

If using CSP, add:
script-src 'self' https://widget.usecrew.ai;
connect-src 'self' https://api.usecrew.ai wss://ws.usecrew.ai;
style-src 'self' 'unsafe-inline';

Domain Allowlisting

Restrict which domains can use your widget:
{
  "widget": {
    "allowed_domains": [
      "yoursite.com",
      "www.yoursite.com",
      "app.yoursite.com"
    ]
  }
}

Analytics

Track widget usage:
window.CrewChat.on('analytics', (event) => {
  gtag('event', event.name, event.properties);
});
Events tracked:
  • widget_opened
  • widget_closed
  • message_sent
  • message_received
  • conversation_started
  • handoff_triggered

Best Practices

Always use async to prevent blocking page load.
Customize colors and styling to match your website.
Use the greeting to explain what the AI can help with.
Always offer a way to reach a human for complex issues.
Verify the widget works well on mobile devices.

Next Steps