Widget Integration Guide
The dialektai widget provides an embeddable chat interface that allows your users to query their data using natural language. This guide will walk you through integrating the widget into your application.
- Build custom chat interfaces with your own design
- Integrate into mobile applications (iOS, Android, React Native)
- Create backend-to-backend integrations
See the API Integration Guide for direct API access (requires Starter plan or higher).
Prerequisites
Before you begin, you'll need:
- A dialektai organization account
- A connected database
- A database-level API key (recommended for widget integration)
Quick Start
The simplest way to add dialektai to your application:
<!-- Add widget container -->
<div id="dialektai-chat"></div>
<!-- Load widget script -->
<script src="https://widget.dialektai.com/widget.js"></script>
<!-- Initialize the widget -->
<script>
DialektAI.create('#dialektai-chat', {
apiKey: 'pk_your_database_api_key_here',
databaseId: 'your-database-uuid'
});
</script>
That's it! The widget will appear in the specified container.
Step-by-Step Integration
Step 1: Get Your API Key
- Log in to your dialektai dashboard
- Navigate to Databases â Select your database â API Keys
- Click Create Database API Key
- Copy the generated key (it starts with
pk_) - Note your database ID from the database settings
pk_*). These keys are:- Scoped to a single database for better security
- Safe for client-side use (e.g., embedded in web pages)
- Available on all plans
Organization API keys (
sk_*) provide broader access and are used for:- Direct API integration without the widget
- Custom chat UI implementations
- Requires Starter plan or higher
- See API Integration Guide for details
Step 2: Add the Widget Script
Add the widget script to your HTML page, preferably before the closing </body> tag:
<!DOCTYPE html>
<html>
<head>
<title>My Application</title>
</head>
<body>
<!-- Your application content -->
<!-- DialektAI Widget Container -->
<div id="dialektai-chat"></div>
<!-- dialektai Widget Script -->
<script src="https://widget.dialektai.com/widget.js"></script>
<script>
DialektAI.create('#dialektai-chat', {
apiKey: 'pk_your_api_key_here',
databaseId: 'your-database-uuid',
// Optional configuration
theme: 'light', // 'light', 'dark', or 'auto'
position: 'bottom-right', // Widget position
placeholder: 'Type your question...',
});
</script>
</body>
</html>
Step 3: Configure Personality (Optional)
To use a specific AI personality for customized responses:
- Log in to the dialektai portal
- Navigate to Settings â AI Personalities
- Find the personality card you want to use
- Click the Copy button next to the Personality ID
- Use that UUID in your widget configuration:
DialektAI.create('#dialektai-chat', {
apiKey: 'pk_your_api_key_here',
databaseId: 'your-database-uuid',
personalityId: 'a1201dbc-0d37-4c74-8ea0-235f7466162b' // Paste your personality ID here
});
- Name: Analytics Expert, Customer Support Bot, etc.
- Response Style: CASUAL, PROFESSIONAL, TECHNICAL, etc.
- Personality ID: UUID with a copy button for easy access
You can create custom personalities with specific tones, instructions, and behaviors.
Step 4: Enable Tenant Filtering (Optional)
If your application serves multiple customers and you want each user to see only their own data, enable tenant filtering:
<script>
DialektAI.create('#dialektai-chat', {
apiKey: 'pk_your_api_key_here',
databaseId: 'your-database-uuid',
// Enable tenant filtering
tenantId: getCurrentOrganizationId(), // Customer/organization ID (required for filtering)
scopeId: getCurrentUserId() // User ID (for tracking or additional filtering)
});
function getCurrentOrganizationId() {
// Your logic to get the current organization/customer ID
// FLEXIBLE: Accepts any string format (integers, UUIDs, custom strings)
// Examples: "82", "customer-123", "550e8400-e29b-41d4-a716-446655440000"
// Used for row-level data filtering: WHERE customer_id = tenantId
return window.currentUser?.organizationId || null;
}
function getCurrentUserId() {
// Your logic to get the current user's ID
// Can be ANY string format: number, UUID, "user-123", etc.
// Examples: "550e8400-e29b-41d4-a716-446655440000", "user-123", "42"
// - If tenant filtering DISABLED: Used for conversation tracking only
// - If tenant filtering ENABLED: Applies additional SQL filtering
return window.currentUser?.id || null;
}
</script>
1. Set
requires_organization_scoping = true on your database connection2. Configure the tenant filter column (usually
tenant_id, customer_id, or organization_id)3. Provide
tenantId in any string format (integers: "82", UUIDs, or custom strings: "customer-123")4. Ensure this column exists in all tables you want to query
Understanding scopeId behavior:
- When tenant filtering is DISABLED:
scopeId is used only for conversation tracking (no SQL filtering)- When tenant filtering is ENABLED:
scopeId applies additional SQL filtering on top of tenant filteringConfiguration Options
Basic Options
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
apiKey |
string | Yes | - | Database-level API key (pk_*) |
databaseId |
string | No | - | UUID of the database to query |
theme |
string | No | 'light' |
Widget theme: 'light', 'dark', or 'auto' |
position |
string | No | 'bottom-right' |
Widget position: 'bottom-right', 'bottom-left', 'top-right', 'top-left' |
Display Options
| Option | Type | Default | Description |
|---|---|---|---|
placeholder |
string | 'Ask a question about your data...' |
Input field placeholder text |
height |
number | 600 |
Widget height in pixels |
className |
string | - | Additional CSS classes for the widget container |
customStyles |
object | {} |
Custom CSS styles (React CSSProperties) |
Advanced Options
| Option | Type | Default | Description |
|---|---|---|---|
tenantId |
string | - | Customer/organization ID for row-level data filtering. Accepts any string format (integers, UUIDs, custom strings). Examples: "82", "customer-123", "550e8400-...". Requires requires_organization_scoping = true in DB config. |
scopeId |
string | - | User/scope ID for conversation tracking and optional filtering. Accepts any string format (UUIDs, "user-123", numbers, etc.). Dual purpose: (1) Conversation tracking when tenant filtering disabled, (2) Additional SQL filtering when enabled |
personalityId |
string | - | Use specific AI personality (UUID). Get from portal: Settings â AI Personalities â Copy ID |
enableLinks |
boolean | true |
Enable contextual links in responses |
qaEnabled |
boolean | true |
Enable Q&A functionality |
Complete Configuration Example
DialektAI.create('#dialektai-chat', {
// Required
apiKey: 'pk_prod_abc123def456',
// Optional: Database and personality
databaseId: '550e8400-e29b-41d4-a716-446655440000',
personalityId: 'a1201dbc-0d37-4c74-8ea0-235f7466162b',
// Multi-tenant data filtering (requires DB config: requires_organization_scoping = true)
tenantId: getCurrentOrganizationId(), // Organization ID (any string format: "82", "customer-123", UUID)
scopeId: getCurrentUserId(), // User ID (any string: UUID, "user-123", etc.)
// Display customization
theme: 'auto', // 'light', 'dark', or 'auto' (follows system preference)
position: 'bottom-right',
placeholder: 'Type your question about your data...',
height: 600,
// Features
enableLinks: true, // Show contextual links in responses
qaEnabled: true, // Enable Q&A functionality
// Advanced styling (optional)
className: 'my-custom-widget',
customStyles: {
borderRadius: '16px',
boxShadow: '0 10px 40px rgba(0, 0, 0, 0.1)'
}
});
Automatic Branding
The dialektai widget automatically fetches and applies your organization's branding configuration. No additional code required - just configure your branding in the portal and it applies to all widgets using your API key.
What's Included
The widget automatically applies:
- Custom colors - Primary, secondary, accent, and text colors
- Custom logo - Light and dark mode variants
- Widget positioning - Bottom-right, bottom-left, top-right, top-left
- Custom placeholder text - Personalized input field placeholder
- Greeting message - Welcome message for users
- Branded footer - Hide "Powered by dialektai" (Enterprise only)
How It Works
- Configure branding in the dialektai Portal: Settings â Branding
- Upload your logo (PNG, SVG, or JPG, max 2MB)
- Customize colors using the color picker
- Configure widget settings (position, messages, etc.)
- Save changes - All widgets update automatically
That's it! Your branding applies instantly to all widgets.
Example
<!-- Widget automatically applies your organization's branding -->
<div id="dialektai-chat"></div>
<script src="https://widget.dialektai.com/widget.js"></script>
<script>
DialektAI.create('#dialektai-chat', {
apiKey: 'pk_prod_abc123def456',
databaseId: '550e8400-e29b-41d4-a716-446655440000'
// No additional configuration needed!
// Widget fetches branding automatically from your organization settings
});
</script>
The widget will display with:
- Your custom logo in the header
- Your brand colors throughout the interface
- Your configured widget position
- Your custom placeholder and greeting messages
- Enterprise: No "Powered by dialektai" footer
Plan Requirements
| Feature | Starter | Professional | Business | Enterprise |
|---|---|---|---|---|
| Custom Colors | â | â | â | â |
| Custom Logo | â | â | â | â |
| Widget Positioning | â | â | â | â |
| Custom Placeholder | â | â | â | â |
| Custom Greeting | â | â | â | â |
| Hide "Powered by" | â | â | â | â |
| Dark Mode Logo | â | â | â | â |
Branding Configuration
To configure your organization's branding:
- Log in to the dialektai Portal
- Navigate to Settings â Branding
- Upload your logo (recommended: 200x60 pixels, PNG or SVG)
- Optional: Upload a dark mode logo variant
- Choose your color palette using the color pickers
- Configure widget settings (position, messages)
- Preview your changes in the live widget preview
- Click Save Changes
Changes apply automatically to all widgets within 1-2 minutes (cached for performance).
- Colors: Ensure sufficient contrast for accessibility (WCAG AA standard)
- Dark Mode: Upload a separate logo optimized for dark backgrounds
- Testing: Use the live preview to test your branding before saving
Troubleshooting Branding
Logo not displaying:
- Check file format (PNG, SVG, JPG only)
- Verify file size is under 2MB
- Ensure image has appropriate dimensions (recommended: 200x60)
- Clear browser cache and reload
Colors not applying:
- Use valid hex color codes (#RRGGBB format)
- Allow 1-2 minutes for changes to propagate
- Clear browser cache
- Check your plan supports custom colors (Business+ required)
Changes not visible:
- Branding is cached for 24 hours for performance
- Clear browser localStorage:
localStorage.removeItem('dialektai-branding-cache') - Refresh the page
Styling and Customization
Custom CSS
You can override the widget's styles using CSS:
<style>
/* Customize widget button */
.dialektai-widget-button {
background-color: #your-brand-color !important;
border-radius: 50% !important;
}
/* Customize chat window */
.dialektai-widget-window {
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2) !important;
border-radius: 16px !important;
}
/* Customize header */
.dialektai-widget-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
}
/* Customize messages */
.dialektai-message-user {
background-color: #your-color !important;
}
</style>
Programmatic Control
Control the widget programmatically via JavaScript:
// Create widget - returns widget ID (string)
const widgetId = DialektAI.create('#dialektai-chat', {
apiKey: 'pk_your_api_key_here',
databaseId: 'your-database-uuid'
});
console.log('Widget created with ID:', widgetId);
// Get widget instance (for advanced usage)
const instance = DialektAI.getInstance(widgetId);
console.log('Widget instance:', instance);
// Destroy widget when needed
DialektAI.destroy(widgetId);
// Auto-initialize widgets from DOM
// Finds all elements with [data-dialekt-ai-widget] attribute
const widgetIds = DialektAI.init();
console.log('Initialized widgets:', widgetIds);
Available Methods:
| Method | Parameters | Returns | Description |
|---|---|---|---|
create() |
containerSelector: string, config: object |
string |
Create widget in specified container, returns widget ID |
embed() |
config: EmbedConfig |
string |
Embed widget with advanced configuration |
destroy() |
widgetId: string |
boolean |
Destroy widget instance, returns success status |
getInstance() |
widgetId: string |
WidgetInstance | undefined |
Get widget instance for advanced usage |
init() |
selector?: string |
string[] |
Auto-initialize widgets from DOM, returns widget IDs |
Framework Integration Examples
React
import { useEffect, useRef } from 'react';
function App() {
const widgetIdRef = useRef(null);
const currentUser = useAuth(); // Your auth hook
useEffect(() => {
// Load widget script
const script = document.createElement('script');
script.src = 'https://widget.dialektai.com/widget.js';
script.async = true;
script.onload = () => {
// Create widget and store the widget ID
widgetIdRef.current = window.DialektAI.create('#dialektai-chat', {
apiKey: process.env.REACT_APP_DIALEKTAI_API_KEY,
databaseId: process.env.REACT_APP_DIALEKTAI_DB_ID,
tenantId: String(currentUser?.organizationId), // Any string format (integers, UUIDs, custom strings)
scopeId: currentUser?.id, // Any string format (UUID, "user-123", etc.)
theme: 'auto'
});
};
document.body.appendChild(script);
return () => {
// Cleanup
if (widgetIdRef.current) {
window.DialektAI.destroy(widgetIdRef.current);
}
document.body.removeChild(script);
};
}, [currentUser]);
return (
<div className="App">
{/* Your app content */}
<div id="dialektai-chat"></div>
</div>
);
}
Vue.js
<template>
<div id="app">
<!-- Your app content -->
<div id="dialektai-chat"></div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
widgetId: null
};
},
mounted() {
const script = document.createElement('script');
script.src = 'https://widget.dialektai.com/widget.js';
script.async = true;
script.onload = () => {
// Create widget and store the widget ID
this.widgetId = window.DialektAI.create('#dialektai-chat', {
apiKey: process.env.VUE_APP_DIALEKTAI_API_KEY,
databaseId: process.env.VUE_APP_DIALEKTAI_DB_ID,
tenantId: String(this.$store.state.user.organizationId), // Any string format (integers, UUIDs, custom strings)
scopeId: this.$store.state.user.id, // Any string format (UUID, "user-123", etc.)
theme: 'auto'
});
};
document.body.appendChild(script);
},
beforeUnmount() {
if (this.widgetId) {
window.DialektAI.destroy(this.widgetId);
}
}
}
</script>
Next.js
// components/DialektaiWidget.tsx
'use client';
import { useEffect, useRef } from 'react';
import { useSession } from 'next-auth/react';
export default function DialektaiWidget() {
const { data: session } = useSession();
const widgetIdRef = useRef<string | null>(null);
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://widget.dialektai.com/widget.js';
script.async = true;
script.onload = () => {
// Create widget and store the widget ID
widgetIdRef.current = window.DialektAI.create('#dialektai-chat', {
apiKey: process.env.NEXT_PUBLIC_DIALEKTAI_API_KEY!,
databaseId: process.env.NEXT_PUBLIC_DIALEKTAI_DB_ID!,
tenantId: String(session?.user?.organizationId), // Any string format (integers, UUIDs, custom strings)
scopeId: session?.user?.id, // Any string format (UUID, "user-123", etc.)
theme: 'auto'
});
};
document.body.appendChild(script);
return () => {
if (widgetIdRef.current) {
window.DialektAI.destroy(widgetIdRef.current);
}
document.body.removeChild(script);
};
}, [session]);
return <div id="dialektai-chat"></div>;
}
// app/layout.tsx
import DialektaiWidget from '@/components/DialektaiWidget';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<DialektaiWidget />
</body>
</html>
);
}
Security Best Practices
When integrating the dialektai widget, follow security best practices to protect your API keys and users' data.
For comprehensive security guidelines including key management, rotation schedules, and secure storage, see the API Keys Guide.
Key Points for Widget Integration:
1. Use Database-Level API Keys
Always use database-level API keys (pk_*) for widget integration, not organization-level keys (sk_*).
- Database keys (
pk_*): Scoped to a single database, safe for client-side use, protected by CORS - Organization keys (
sk_*): Broader access, server-side only, use for direct API integration
See API Integration Guide for when to use organization keys.
2. Enable Tenant Filtering for Multi-Tenant Apps
For multi-tenant applications, always enable tenant filtering to ensure data isolation:
DialektAI.create('#dialektai-chat', {
apiKey: 'pk_prod_abc123',
databaseId: 'your-db-id',
tenantId: String(getAuthenticatedOrganizationId()), // Any string format: "82", "customer-123", UUID
scopeId: getAuthenticatedUserId() // Any string (UUID, "user-123", etc.)
});
Important:
tenantIdaccepts any string format (integers, UUIDs, custom strings) for maximum flexibilityscopeIdcan be any string format (UUIDs, usernames, etc.)- Requires
requires_organization_scoping = truein database configuration
3. Additional Best Practices
- Configure allowed domains in the portal to restrict widget usage
- Use environment variables for API keys (never hardcode)
- Rotate keys regularly (every 90 days recommended)
- Monitor usage in the dashboard for unusual activity
Troubleshooting
Widget Not Appearing
Check:
- Script loaded correctly: Open browser console, check for errors
- API key is valid: Test at
/api/v1/auth/validate - Database ID is correct: Check dialektai dashboard
Tenant Filtering Not Working
Check:
- Database has
requires_organization_scoping = true - Tenant filter column is configured
tenantIdvalue matches database column format
Test with cURL:
curl -X POST https://api.dialektai.com/api/v1/chat/message \
-H "X-API-Key: pk_your_api_key_here" \
-H "X-Tenant-Id: 123" \
-H "Content-Type: application/json" \
-d '{"message": "test"}'
CORS Errors
Solution:
Add your domain to allowed origins in dialektai dashboard:
- Database Settings â API Keys â Allowed Origins
- Add
https://yourdomain.com
Widget Button Covered by Other Elements
Solution:
Adjust z-index in CSS:
.dialektai-widget-button {
z-index: 9999 !important;
}
Next Steps
- API Keys Guide - Authentication and key management
- API Integration Guide - Direct API integration for custom UIs
- Widget Quick Start - 5-minute setup guide