An open API service indexing awesome lists of open source software.

https://github.com/vbrazo/upriser-agents

A standalone JavaScript widget for integrating Upriser ElevenLabs ConvAI into any website.
https://github.com/vbrazo/upriser-agents

Last synced: 5 months ago
JSON representation

A standalone JavaScript widget for integrating Upriser ElevenLabs ConvAI into any website.

Awesome Lists containing this project

README

          

# Upriser Widget

A standalone JavaScript widget for integrating Upriser ConvAI into any website. This package provides both npm module support and raw JavaScript files for maximum flexibility.

## ๐Ÿ“š Table of Contents

- [Installation](#installation)
- [Usage](#usage)
- [NPM Module Usage](#npm-module-usage)
- [Raw JavaScript Usage](#raw-javascript-usage)
- [๐Ÿš€ Modal & Client Tools (NEW!)](#-modal--client-tools-new)
- [๐ŸŽจ Whitelabel Features](#-whitelabel-features)
- [Configuration Options](#configuration-options)
- [API Methods](#api-methods)
- [React Integration Example](#react-integration-example)
- [๐ŸŽฏ Client Tools Use Cases](#-client-tools-use-cases)
- [Vue Integration Example](#vue-integration-example)
- [๐Ÿ“ก Event Handling](#-event-handling)
- [Browser Support](#browser-support)
- [Features](#features)
- [Development](#development)
- [๐Ÿ”„ Continuous Integration (CI)](#-continuous-integration-ci)
- [File Structure](#file-structure)
- [License](#license)
- [Support](#support)

## Installation

### Option 1: NPM Package (Recommended for React, Vue, Angular, etc.)

```bash
npm install @upriser.ai/widget
```

### Option 2: CDN / Direct Script Inclusion

```html

```

## Usage

### NPM Module Usage

#### ES Modules (Modern bundlers like Webpack, Vite, etc.)

```javascript
import UpriserWidget from "@upriser.ai/widget/dist/upriser-widget.js";

// Create and initialize the widget
const widget = new UpriserWidget({
agentId: "your-agent-id-here",
fontColor: "#ffffff",
linkColor: "#007bff",
});

// Initialize the widget
widget
.init()
.then(() => {
console.log("Upriser widget initialized successfully!");
})
.catch((error) => {
console.error("Failed to initialize widget:", error);
});
```

#### CommonJS (Node.js style)

```javascript
import UpriserWidget from "@upriser.ai/widget/dist/upriser-widget.js";

const widget = new UpriserWidget({
agentId: "your-agent-id-here",
debug: false,
});

widget.init();
```

#### TypeScript Support

The package includes full TypeScript definitions:

```typescript
import UpriserWidget, { UpriserWidgetConfig } from "@upriser.ai/widget";

const config: UpriserWidgetConfig = {
agentId: "your-agent-id-here",
};

const widget = new UpriserWidget(config);
widget.init();
```

### Raw JavaScript Usage

#### Basic Usage

```html


My Website




// The widget will auto-initialize with default settings
// Or manually initialize:

// Option 1: Use the global instance (auto-created)
if (window.upriserWidget) {
console.log("Widget auto-initialized");
}

// Option 2: Create your own instance
const myWidget = new UpriserWidget({
agentId: "your-custom-agent-id",
fontColor: "#ffffff",
linkColor: "#007bff",
});
myWidget.init();

```

#### Custom Configuration

```html

// Configure before the script loads (for auto-initialization)
window.UPRISER_WIDGET_CONFIG = {
agentId: "your-agent-id-here",
};

// Disable auto-initialization if you want full control
// window.UPRISER_DISABLE_AUTO_INIT = true;

```

#### WordPress Integration

```php
// In your WordPress theme's functions.php
function add_upriser_widget() {
?>

window.UPRISER_WIDGET_CONFIG = {
agentId: '<?php echo get_option('upriser_agent_id', 'agent_8401k5nnvgqpezf9fd17t3tb7t69'); ?>'
};


{
const url = parameters?.url || "https://meetings.hubspot.com/default";
return widget.openModal({
url,
title: "Schedule a Demo",
onClose: () => console.log("Demo modal closed"),
});
},
},
});
```

### Client Tools System

Client tools are JavaScript functions that the AI agent can call to perform specific actions:

```javascript
// Option 1: Global client tools
window.UPRISER_CLIENT_TOOLS = {
show_demo_form: (parameters) => {
const url = parameters?.url || "https://meetings.hubspot.com/default";
// Open your custom modal or use the built-in one
return { success: true, message: "Demo form opened" };
},

show_vehicle_page: (parameters) => {
if (!parameters?.url) {
return { success: false, message: "URL required" };
}
// Open vehicle details modal
return { success: true, message: "Vehicle page opened" };
},
};

// Option 2: Widget configuration
const widget = new UpriserWidget({
agentId: "your-agent-id",
clientTools: {
// Your client tools here
},
});
```

## ๐ŸŽจ Whitelabel Features

Upriser Widget supports complete whitelabeling with custom branding and colors!

### Custom HTML Element

```html

```

### Custom Element Attributes

| Attribute | Type | Default | Description |
| ------------ | ------ | --------- | -------------------------------------- |
| `agent-id` | string | Required | Upriser agent ID |
| `font-color` | string | `#ffffff` | Color for "Powered by Upriser.ai" text |
| `link-color` | string | `#ffffff` | Color for links to Upriser.ai |

### Dynamic Color Changes

You can change colors dynamically using JavaScript:

```javascript
// Get the widget element
const widget = document.querySelector("upriser-convai");

// Change colors
widget.setAttribute("font-color", "#ff6b6b");
widget.setAttribute("link-color", "#4ecdc4");
```

### JavaScript Class with Colors

Use the UpriserWidget class with custom colors:

```javascript
const widget = new UpriserWidget({
agentId: "agent_8401k5nnvgqpezf9fd17t3tb7t69",
fontColor: "#ffffff",
linkColor: "#007bff",
});

widget.init();
```

### Color Examples

```html

```

### Benefits of Whitelabel Version

- โœ… **Custom Colors** - Match your brand colors exactly
- โœ… **Dynamic Updates** - Change colors on the fly
- โœ… **Better Events** - Enhanced event handling and API

## Configuration Options

| Option | Type | Default | Description |
| ----------------- | ------------------------ | -------------------------------------- | --------------------------------------------------------- |
| `agentId` | string | `'agent_8401k5nnvgqpezf9fd17t3tb7t69'` | Upriser agent ID to use |
| `widgetContainer` | HTMLElement \| null | `null` | Container to append widget to (defaults to document.body) |
| `debug` | boolean | `false` | Enable debug logging |
| `fontColor` | string | `'#ffffff'` | Custom color for "Powered by Upriser.ai" text |
| `linkColor` | string | `'#ffffff'` | Custom color for links to Upriser.ai |
| `clientTools` | Record | `{}` | **NEW!** Custom functions that the AI agent can call |

## API Methods

### `widget.init()`

Initializes the widget. Returns a Promise.

```javascript
await widget.init();
```

### `widget.updateConfig(newConfig)`

Updates the widget configuration.

```javascript
widget.updateConfig({ debug: true, agentId: "new-agent-id" });
```

### `widget.test()`

Tests widget functionality and returns status.

```javascript
const status = widget.test();
console.log("Widget status:", status);
```

### `widget.openModal(options)`

**NEW!** Opens a modal with the specified URL and options.

```javascript
const result = widget.openModal({
url: "https://meetings.hubspot.com/demo",
title: "Schedule a Demo",
onClose: () => console.log("Modal closed"),
});
console.log(result);
// { success: true, message: "Modal opened successfully" }
```

### `widget.setClientTools(clientTools)`

**NEW!** Updates the client tools available to the AI agent.

```javascript
widget.setClientTools({
show_demo_form: (parameters) => {
const url = parameters?.url || "https://meetings.hubspot.com/default";
return widget.openModal({ url, title: "Schedule Demo" });
},
show_vehicle_page: (parameters) => {
if (!parameters?.url) {
return { success: false, message: "URL required" };
}
return widget.openModal({
url: parameters.url,
title: parameters.title || "Vehicle Details",
});
},
});
```

### `widget.getClientTools()`

**NEW!** Returns the current client tools configuration.

```javascript
const tools = widget.getClientTools();
console.log("Available tools:", Object.keys(tools));
```

### `widget.destroy()`

Destroys the widget and cleans up all resources.

```javascript
widget.destroy();
```

## React Integration Example

```jsx
import React, { useEffect, useRef } from "react";
import UpriserWidget from "@upriser.ai/widget/dist/upriser-widget.js";

function ChatWidget({ agentId, debug = false }) {
const widgetRef = useRef(null);
const containerRef = useRef(null);

useEffect(() => {
if (containerRef.current) {
const widget = new UpriserWidget({
agentId,
debug,
widgetContainer: containerRef.current,
});

widget.init().catch(console.error);
widgetRef.current = widget;

return () => {
if (widgetRef.current) {
widgetRef.current.destroy();
}
};
}
}, [agentId, debug]);

return

;
}

export default ChatWidget;
```

## ๐ŸŽฏ Client Tools Use Cases

### Demo Scheduling Integration

Perfect for sales teams and lead generation websites:

```javascript
// Setup demo scheduling client tools
window.UPRISER_CLIENT_TOOLS = {
show_demo_form: (parameters) => {
const url = parameters?.url || "https://meetings.hubspot.com/default";

// Use the built-in modal system
if (window.upriserWidgetInstance) {
return window.upriserWidgetInstance.openModal({
url,
title: "Schedule a Demo",
onClose: () => {
console.log("Demo modal closed");
// Track analytics
},
});
}

// Fallback to custom implementation
openCustomDemoModal(url);
return { success: true, message: "Demo form opened" };
},
};

// The AI agent can now call: "Let me show you our demo scheduling form"
// This will trigger the show_demo_form client tool
```

### Vehicle Browsing Integration

Ideal for automotive dealerships:

```javascript
// Setup vehicle browsing client tools
window.UPRISER_CLIENT_TOOLS = {
show_vehicle_page: (parameters) => {
const url = parameters?.url;
const title = parameters?.title || "Vehicle Details";

// Validate required parameters
if (!url || typeof url !== "string") {
console.warn("show_vehicle_page requires a valid URL");
return { success: false, message: "Missing or invalid URL parameter" };
}

// Use the built-in modal system
if (window.upriserWidgetInstance) {
return window.upriserWidgetInstance.openModal({
url,
title,
onClose: () => {
console.log("Vehicle modal closed");
},
});
}

// Fallback to new tab
window.open(url, "_blank", "noopener,noreferrer");
return {
success: true,
message: "Opened vehicle page in new tab (fallback)",
};
},
};

// The AI agent can now call: "Let me show you this vehicle"
// This will trigger the show_vehicle_page client tool with the vehicle URL
```

### Custom Modal Content

You can also create completely custom modals:

```javascript
window.UPRISER_CLIENT_TOOLS = {
show_product_catalog: (parameters) => {
const category = parameters?.category || "all";
const searchTerm = parameters?.search || "";

// Create custom modal content
const modalContent = document.createElement("div");
modalContent.innerHTML = `


Product Catalog





All Categories
Electronics
Clothing






`;

// Use built-in modal with custom content
if (window.upriserWidgetInstance) {
const modal = window.upriserWidgetInstance.createModal({
title: "Product Catalog",
content: modalContent,
className: "product-catalog-modal",
});

if (modal) {
return { success: true, message: "Product catalog opened" };
}
}

return { success: false, message: "Failed to open catalog" };
},
};
```

## Vue Integration Example

```vue

import UpriserWidget from "@upriser.ai/widget/dist/upriser-widget.js";

export default {
name: "UpriserChat",
props: {
agentId: {
type: String,
default: "agent_8401k5nnvgqpezf9fd17t3tb7t69",
},
debug: {
type: Boolean,
default: false,
},
},
data() {
return {
widget: null,
};
},
async mounted() {
this.widget = new UpriserWidget({
agentId: this.agentId,
debug: this.debug,
widgetContainer: this.$refs.chatContainer,
});

try {
await this.widget.init();
} catch (error) {
console.error("Failed to initialize Upriser widget:", error);
}
},
beforeUnmount() {
if (this.widget) {
this.widget.destroy();
}
},
};

```

## ๐Ÿ“ก Event Handling

The widget dispatches custom events that you can listen for:

### Modal Events

```javascript
// Listen for modal opened events
window.addEventListener("upriser:modal-opened", (event) => {
console.log("Modal opened:", event.detail);

// Track analytics based on modal type
if (event.detail.type === "demo") {
// ...
} else if (event.detail.type === "vehicle") {
// ...
}
});

// Listen for modal closed events
window.addEventListener("upriser:modal-closed", (event) => {
console.log("Modal closed:", event.detail);

// you could track analytics here
});
```

### Widget Events

```javascript
// Listen for widget initialization
window.addEventListener("upriser:initialized", (event) => {
console.log("Widget initialized:", event.detail);

// Widget is ready, you can now safely call client tools
const tools = event.detail.element.getClientTools();
console.log("Available client tools:", Object.keys(tools));
});

// Listen for widget errors
window.addEventListener("upriser:error", (event) => {
console.error("Widget error:", event.detail.error);

// Handle errors gracefully
showErrorMessage(
"Chat widget encountered an error. Please refresh the page.",
);
});
```

### Client Tool Response Handling

```javascript
// Example of handling client tool responses
window.UPRISER_CLIENT_TOOLS = {
show_demo_form: (parameters) => {
try {
const url = parameters?.url || "https://meetings.hubspot.com/default";

// Attempt to open modal
if (window.upriserWidgetInstance) {
const result = window.upriserWidgetInstance.openModal({
url,
title: "Schedule a Demo",
});

if (result.success) {
// Dispatch custom success event
window.dispatchEvent(
new CustomEvent("upriser:demo-opened", {
detail: { url, timestamp: Date.now() },
}),
);
}

return result;
}

return { success: false, message: "Widget not available" };
} catch (error) {
console.error("Error in show_demo_form:", error);

// Dispatch error event
window.dispatchEvent(
new CustomEvent("upriser:client-tool-error", {
detail: { tool: "show_demo_form", error: error.message },
}),
);

return { success: false, message: "Failed to open demo form" };
}
},
};
```

## Browser Support

- Modern browsers (Chrome 60+, Firefox 55+, Safari 12+, Edge 79+)
- Supports both ES modules and UMD
- Works with or without build tools
- No external dependencies

## Features

- ๐Ÿš€ **Zero dependencies** - Works standalone
- ๐Ÿ“ฆ **Multiple formats** - UMD, ESM, and raw JavaScript
- ๐ŸŽฏ **TypeScript support** - Full type definitions included
- ๐Ÿ”ง **Auto-initialization** - Works out of the box
- ๐ŸŽจ **Customizable** - Override default agent and styling
- ๐Ÿงช **Well tested** - Comprehensive test suite
- ๐Ÿ“ฑ **Responsive** - Works on desktop and mobile
- ๐ŸชŸ **Built-in modals** - **NEW!** Integrated modal system for seamless user experiences
- ๐Ÿ› ๏ธ **Client tools** - **NEW!** Custom functions that AI agents can call
- ๐Ÿ“ก **Event system** - **NEW!** Rich event handling for modal and widget interactions
- ๐ŸŽฏ **Use case ready** - **NEW!** Pre-built patterns for demos, vehicle browsing, and more

## Development

```bash
# Install dependencies
npm install

# Build all formats
npm run build

# Run tests
npm test

# Watch tests
npm test:watch
```

## ๐Ÿ”„ Continuous Integration (CI)

This project uses GitHub Actions for continuous integration to ensure code quality and reliability across multiple Node.js versions.

### CI Pipeline Overview

The CI pipeline runs on every push and pull request to `main`, `master`, and `develop` branches, performing the following checks:

#### Test Job
- **Node.js Matrix Testing**: Tests against Node.js versions 16.x, 18.x, and 20.x
- **Dependency Installation**: Uses `npm ci` for clean, reproducible builds
- **Code Linting**: Runs ESLint to ensure code quality
- **Test Execution**: Runs the complete test suite
- **Build Verification**: Ensures all build formats compile successfully
- **Coverage Reports**: Uploads test coverage to Codecov (Node.js 18.x only)

#### Lint Job
- **Dedicated Linting**: Separate job for thorough ESLint checks
- **Node.js 18.x**: Uses stable Node.js version for consistent linting

### Available Scripts for CI

```bash
# Core CI commands
npm ci # Clean install (used in CI)
npm run lint # Run ESLint
npm run lint:check # Check linting without fixing
npm run lint:fix # Fix linting issues automatically
npm test # Run test suite
npm test:coverage # Run tests with coverage report
npm run build # Build all formats (UMD, ESM, Types, Raw)

# Individual build commands
npm run build:raw # Build raw JavaScript file
npm run build:umd # Build UMD format
npm run build:esm # Build ES module format
npm run build:types # Generate TypeScript definitions
```

### Local Development Workflow

To match the CI environment locally:

```bash
# 1. Clean install dependencies (like CI)
npm ci

# 2. Run linting checks
npm run lint:check

# 3. Run tests with coverage
npm test:coverage

# 4. Verify build works
npm run build

# 5. Fix any linting issues
npm run lint:fix
```

### CI Configuration Details

The CI configuration includes:

- **Automated Testing**: Ensures all tests pass before merging
- **Multi-Node Support**: Validates compatibility across Node.js LTS versions
- **Code Quality**: ESLint enforcement for consistent code style
- **Build Verification**: Confirms all distribution formats build successfully
- **Coverage Tracking**: Monitors test coverage trends via Codecov
- **Fail-Fast**: Stops on first failure to provide quick feedback

### Contributing Guidelines

When contributing to this project:

1. **Write Tests**: All new features must include comprehensive tests [[memory:9100424]]
2. **Follow Linting**: Ensure `npm run lint:check` passes
3. **Test Locally**: Run `npm test` before submitting PRs
4. **Build Verification**: Confirm `npm run build` succeeds
5. **Coverage**: Maintain or improve test coverage

### CI Status

The CI pipeline must pass for all pull requests. Check the GitHub Actions tab for detailed build logs and status updates.

## File Structure

```
@upriser/widget/
โ”œโ”€โ”€ dist/ # Built files for npm
โ”‚ โ”œโ”€โ”€ upriser-widget.js # UMD build
โ”‚ โ”œโ”€โ”€ upriser-widget.esm.js # ES module build
โ”‚ โ””โ”€โ”€ upriser-widget.d.ts # TypeScript definitions
โ”œโ”€โ”€ upriser-widget.js # Raw JavaScript file (for CDN/direct use)
โ”œโ”€โ”€ src/ # Source files
โ””โ”€โ”€ package.json
```

## License

MIT

## Support

For support, please visit [https://www.upriser.ai](https://www.upriser.ai) or create an issue in the repository.