1.Overview
The dataX.ai Chat Widget is a zero-dependency, high-performance customer assistant widget. It automatically ingests on-screen page context to deliver instant AI-driven answers to customer inquiries about page specifications, compatibility, and compliance.
Isolated Shadow DOM Architecture. Renders completely within an isolated open Shadow DOM root. This guarantees zero CSS style bleed into or out of your host website styles.
Browser Support
| Browser | Minimum Version | Required Features |
|---|---|---|
| Google Chrome / Edge | 90+ (April 2021) | Shadow DOM v1, Fetch ReadableStream, AbortController |
| Apple Safari (macOS / iOS) | 15+ (Sept 2021) | Shadow DOM v1, CSS color-mix(), Web APIs |
| Mozilla Firefox | 86+ (Feb 2021) | Shadow DOM v1, ReadableStream, EventListener Signal |
2.Quick start
Embed the widget bundle immediately after your opening
<body> tag:
<!-- dataX.ai Chat Widget -->
<script src="https://your-cdn-path.com/chat-widget.js" defer></script>
<script>
window.ChatWidget.init({
position: "right",
primaryColor: "#0c4af3",
togglePrompt: "Ask me about this product"
});
window.ChatWidget.create();
</script>
CDN Bundle URL: Please replace
https://your-cdn-path.com/chat-widget.js with the
actual deliverables CDN URL provided for your environment.
Automatic DOM Readiness Handling.
ChatWidget.create() internally checks
document.readyState and automatically awaits full DOM
readiness before mounting. Using the defer attribute
downloads the script concurrently without blocking DOM
construction
3.Script loading strategies
Choose the loading pattern that aligns best with your application stack:
Recommended Standard Deferred Loading
Best for standard HTML pages and web applications where scripts are included directly in the page markup.
<script src="https://your-cdn-path.com/chat-widget.js" defer></script>
Alternative Asynchronous Dynamic Injection
Ideal when loading and initializing the script dynamically at runtime.
<script>
(function () {
var s = document.createElement("script");
s.src = "https://your-cdn-path.com/chat-widget.js";
s.async = true;
s.onload = function () {
window.ChatWidget.init({ primaryColor: "#0c4af3" });
window.ChatWidget.create();
};
document.head.appendChild(s);
})();
</script>
4.Configuration
Initialize the widget by passing a configuration object to
ChatWidget.init(config). All parameters are optional.
| Option | Type | Default | Description |
|---|---|---|---|
position |
"right" | "left" |
"right" |
Bottom corner alignment. On viewports below
600px, automatically transitions to full-width
mobile view.
|
primaryColor |
string |
"#0c4af3" |
Hex brand color applied to the launcher button, header sparkles, send button, status badges, and focus rings via CSS variables. |
togglePrompt |
string |
"Ask me about this product" |
Text label rendered on the collapsed launcher badge next to the sparkles icon. |
5.API reference
The SDK exposes a global controller object
window.ChatWidget on the browser window with three
primary lifecycle methods:
ChatWidget.init(config)
Loads the widget configuration options and initializes internal
dependencies. This method must be invoked prior to
ChatWidget.create().
It accepts a config object with customization options
(such as position, primaryColor, and
togglePrompt).
Single Initialization Note:
ChatWidget.init() should be called only once during
initial application startup to preserve and enforce brand
configurations across the session.
window.ChatWidget.init({
position: "right",
primaryColor: "#0c4af3",
togglePrompt: "Ask me about this product"
});
ChatWidget.create()
Mounts the widget to the DOM, injecting Google Font dependencies, attaching the isolated Shadow DOM container, and rendering the floating launcher button in the corner of the viewport.
On mounting, the widget automatically ingests
document.body.innerText from the page. This makes the
assistant instantly context-aware of on-screen page details,
specifications, and text content. The AI chat session begins
automatically when the user first opens the chat window.
window.ChatWidget.create();
ChatWidget.destroy()
Cleans up the widget by completely removing it from the DOM,
aborting any active AI response network streams via
AbortController.abort(), and clearing background TTL
timers and typing indicators.
Executing destroy() preserves existing configuration
options while preventing memory leaks or orphaned background
requests, allowing ChatWidget.create() to be called
again later (e.g., during single-page app route transitions).
window.ChatWidget.destroy();
6.Single-page applications (SPAs)
The widget captures on-screen page context (via
document.body.innerText) once when
ChatWidget.create() is invoked.
In client-routed frameworks (React Router, Next.js client navigation, Vue Router, Angular Router), page content changes dynamically without a full browser reload. If route navigation occurs without resetting the widget, the assistant will continue holding the previous page's context.
SPA Lifecycle Sequence:
-
ChatWidget.init(config)— Call once on initial application load to configure brand settings (position, colors, prompts). -
ChatWidget.create()— Mount the widget and create an active session for the current page. -
ChatWidget.destroy()— Call when navigating away from the page/route to unmount the widget, abort active AI response streams, and tear down the old session. -
ChatWidget.create()— Call on the new route to recreate the widget and ingest the updated page details into a fresh AI session.
// Step 1: Configure brand settings once on app initialization
window.ChatWidget.init({
position: "right",
primaryColor: "#0c4af3",
togglePrompt: "Ask about this page"
});
// Step 2: Mount the widget and ingest initial page context
window.ChatWidget.create();
// Step 3: When navigating away from the page/route
window.ChatWidget.destroy();
// Step 4: Re-create the widget on the new route to ingest updated page context
window.ChatWidget.create();
7.Framework examples
React (React Router / SPA)
// components/ChatWidget.tsx
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function ChatWidget() {
const location = useLocation();
useEffect(() => {
// Configure once on initial mount
window.ChatWidget?.init({
position: "right",
primaryColor: "#0c4af3",
togglePrompt: "Ask about this page"
});
window.ChatWidget?.create();
return () => {
window.ChatWidget?.destroy();
};
}, []);
// Re-create widget on route changes to capture updated page context
useEffect(() => {
window.ChatWidget?.destroy();
window.ChatWidget?.create();
}, [location.pathname]);
return null;
}
Next.js (App Router)
// components/ChatWidget.tsx
"use client";
import { useEffect, useRef } from "react";
import { usePathname } from "next/navigation";
const BUNDLE_URL = "https://your-cdn-path.com/chat-widget.js";
export default function ChatWidget() {
const pathname = usePathname();
const isMounted = useRef(false);
useEffect(() => {
const script = document.createElement("script");
script.src = BUNDLE_URL;
script.async = true;
script.onload = () => {
window.ChatWidget.init({
position: "right",
primaryColor: "#0c4af3",
togglePrompt: "Ask about this page"
});
window.ChatWidget.create();
isMounted.current = true;
};
document.body.appendChild(script);
return () => {
window.ChatWidget?.destroy();
script.remove();
};
}, []);
useEffect(() => {
if (!isMounted.current) return;
window.ChatWidget?.destroy();
window.ChatWidget?.create();
}, [pathname]);
return null;
}
Vue 3 / Nuxt 3
<!-- components/ChatWidget.vue -->
<script setup>
import { onMounted, onUnmounted, watch } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute();
onMounted(() => {
const script = document.createElement('script');
script.src = 'https://your-cdn-path.com/chat-widget.js';
script.async = true;
script.onload = () => {
window.ChatWidget.init({
position: 'right',
primaryColor: '#0c4af3',
togglePrompt: 'Ask about this page'
});
window.ChatWidget.create();
};
document.head.appendChild(script);
});
// Re-create widget on route changes to capture updated page context
watch(() => route.fullPath, () => {
window.ChatWidget?.destroy();
window.ChatWidget?.create();
});
onUnmounted(() => {
window.ChatWidget?.destroy();
});
</script>
Angular
// src/app/components/chat-widget.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
@Component({
selector: 'app-chat-widget',
template: ''
})
export class ChatWidgetComponent implements OnInit, OnDestroy {
private routerSub!: Subscription;
constructor(private router: Router) {}
ngOnInit(): void {
// Initialize configuration & mount initial widget
window.ChatWidget?.init({
position: 'right',
primaryColor: '#0c4af3',
togglePrompt: 'Ask about this page'
});
window.ChatWidget?.create();
// Re-create widget on NavigationEnd to ingest new page context
this.routerSub = this.router.events
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe(() => {
window.ChatWidget?.destroy();
window.ChatWidget?.create();
});
}
ngOnDestroy(): void {
if (this.routerSub) {
this.routerSub.unsubscribe();
}
window.ChatWidget?.destroy();
}
}
Angular Type Declarations: Be sure to add the
global TypeScript declaration file (e.g.
src/chat-widget.d.ts or
src/typings.d.ts as detailed in
Section 8) to your Angular project. This
satisfies the Angular ng build compiler and resolves
Property 'ChatWidget' does not exist on type 'Window'
errors.
Global Configuration Note: Alternatively,
ChatWidget.init(config) can be called once in your
application's root index.html page right alongside
the <script> bundle tag. When initialized
globally in index.html, individual framework
components only need to handle
ChatWidget.create() and
ChatWidget.destroy().
8.TypeScript declarations
In TypeScript-based applications (such as Angular,
React TS, or Vue TS), accessing
window.ChatWidget directly triggers compilation errors
because the global Window interface does not include
the runtime-injected SDK property by default (e.g.,
Property 'ChatWidget' does not exist on type 'Window').
Adding a global type declaration file extends the native
Window interface, satisfying the TypeScript compiler
(tsc), resolving Angular build errors, and enabling
full IDE IntelliSense and autocompletion.
Create a declaration file (e.g., src/chat-widget.d.ts)
in your project source folder:
export {};
declare global {
interface ChatWidgetConfig {
position?: "left" | "right";
primaryColor?: string;
togglePrompt?: string;
}
interface Window {
ChatWidget: {
init: (config?: ChatWidgetConfig) => void;
create: () => void;
destroy: () => void;
};
}
}
9.Security & CSP
If your application enforces strict Content-Security-Policy (CSP) headers, whitelist the following origins:
| Directive | Target Domain / Value | Functionality |
|---|---|---|
script-src |
https://your-cdn-path.com |
Loads the widget JS bundle. |
connect-src |
https://productpal-dev.datax.work |
Session initialization and SSE stream completion endpoints. |
style-src |
'unsafe-inline' https://fonts.googleapis.com
|
Shadow DOM internal styles and Google Fonts stylesheets. |
font-src |
https://fonts.gstatic.com |
Inter font family files. |
10.Troubleshooting
| Issue / Symptom | Probable Cause | Resolution Step |
|---|---|---|
ChatWidget is not defined |
Script executed before bundle finished loading. |
Ensure the script tag includes the
defer attribute or verify the bundle has loaded
before calling ChatWidget.create().
|
| Session initialization error | CORS / CSP header blocking backend endpoint. |
Ensure connect-src whitelist includes
https://productpal-dev.datax.work.
|
| Stale context on page change | SPA router navigated without resetting widget context. |
Call destroy() → create() sequence on route
changes.
|
| Session expired | Server-issued session TTL elapsed after inactivity. | Expected behavior. The visitor can click Restart Session; no integration change required. |
| Retry limit reached (3 attempts) | Backend service unavailable or network connectivity lost. |
Verify network status. Contact dataX.ai support at
cs@datax.ai if issue persists.
|
11.Support
| Support Contact | cs@datax.ai |
| Current Release | v1 |