Chat Widget Integration Guide

Alpha Updated 20 Aug 2026

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:

  1. ChatWidget.init(config) — Call once on initial application load to configure brand settings (position, colors, prompts).
  2. ChatWidget.create() — Mount the widget and create an active session for the current page.
  3. 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.
  4. 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