Kembali ke Blog
TutorialIntegrationWidget

Embedding a Chat Widget: React, Next.js, WordPress, Webflow

LaunchChat Team9 min read

One Widget, Every Platform

LaunchChat's chat widget is a lightweight JavaScript bundle that works on any website. The embed process is the same regardless of platform: add a config object and load the script. But each platform has its own best practices for script loading.

This guide covers the five most common platforms with copy-paste code snippets.

Embed on any platform
Embed on any platform

Prerequisites

  1. A LaunchChat account with a configured widget
  2. Your widget ID (found in Widget Settings → Embed Code)
  3. Access to your website's HTML or CMS

Plain HTML

The simplest integration. Add these two lines before the closing </body> tag:

<script>
  window.NotionSupportConfig = { widgetId: 'your-widget-id' };
</script>
<script src="https://launchchat.dev/widget.js" defer></script>

The defer attribute ensures the script loads without blocking page rendering.

With Custom Options

<script>
  window.NotionSupportConfig = {
    widgetId: 'your-widget-id',
    position: 'bottom-right',  // or 'bottom-left'
    locale: 'en',              // language code
  };
</script>
<script src="https://launchchat.dev/widget.js" defer></script>

React (Create React App, Vite)

For React apps, use a useEffect hook to load the script:

// components/ChatWidget.tsx
import { useEffect } from 'react';

export function ChatWidget({ widgetId }: { widgetId: string }) {
  useEffect(() => {
    // Set config
    (window as any).NotionSupportConfig = { widgetId };

    // Load script
    const script = document.createElement('script');
    script.src = 'https://launchchat.dev/widget.js';
    script.defer = true;
    document.body.appendChild(script);

    return () => {
      // Cleanup on unmount
      document.body.removeChild(script);
      delete (window as any).NotionSupportConfig;
    };
  }, [widgetId]);

  return null;
}

Usage in your app:

// App.tsx
import { ChatWidget } from './components/ChatWidget';

function App() {
  return (
    <>
      {/* Your app content */}
      <ChatWidget widgetId="your-widget-id" />
    </>
  );
}

Why useEffect?

React's virtual DOM doesn't handle raw <script> tags well. Using useEffect ensures the script loads after the component mounts and cleans up when it unmounts. This prevents memory leaks in single-page applications.

Next.js (App Router)

Next.js has a built-in <Script> component optimized for third-party scripts:

// app/layout.tsx
import Script from 'next/script';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script id="launchchat-config" strategy="afterInteractive">
          {`window.NotionSupportConfig = { widgetId: 'your-widget-id' };`}
        </Script>
        <Script
          src="https://launchchat.dev/widget.js"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}

Strategy Options

  • afterInteractive (recommended): Loads after the page is interactive. Best balance of performance and availability.
  • lazyOnload: Loads during idle time. Slightly better performance but the widget appears later.
  • beforeInteractive: Loads before hydration. Not recommended — the widget doesn't need to be available that early.

Next.js Pages Router

If you're using the Pages Router instead of App Router:

// pages/_app.tsx
import Script from 'next/script';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <Script id="launchchat-config" strategy="afterInteractive">
        {`window.NotionSupportConfig = { widgetId: 'your-widget-id' };`}
      </Script>
      <Script
        src="https://launchchat.dev/widget.js"
        strategy="afterInteractive"
      />
    </>
  );
}

WordPress

Two options for WordPress:

Option A: Theme Footer (Recommended)

  1. Go to Appearance → Theme File Editor
  2. Open footer.php
  3. Add before the closing </body> tag:
<script>
  window.NotionSupportConfig = { widgetId: 'your-widget-id' };
</script>
<script src="https://launchchat.dev/widget.js" defer></script>

Option B: Plugin (No Code)

Use a "Header and Footer Scripts" plugin (e.g., Insert Headers and Footers by WPBeginner):

  1. Install and activate the plugin
  2. Go to Settings → Insert Headers and Footers
  3. Paste the embed code in the "Scripts in Footer" section
  4. Save

Option C: functions.php

For theme developers who prefer the WordPress way:

// functions.php
function launchchat_widget_scripts() {
    wp_enqueue_script(
        'launchchat-config',
        '',
        array(),
        null,
        true
    );
    wp_add_inline_script(
        'launchchat-config',
        "window.NotionSupportConfig = { widgetId: 'your-widget-id' };"
    );
    wp_enqueue_script(
        'launchchat-widget',
        'https://launchchat.dev/widget.js',
        array('launchchat-config'),
        null,
        true
    );
}
add_action('wp_enqueue_scripts', 'launchchat_widget_scripts');

Webflow

Webflow supports custom code injection:

  1. Go to Project Settings → Custom Code
  2. In the "Footer Code" section, paste:
<script>
  window.NotionSupportConfig = { widgetId: 'your-widget-id' };
</script>
<script src="https://launchchat.dev/widget.js" defer></script>
  1. Save and publish

Page-Specific Widget

To show the widget only on certain pages:

  1. Open the page in the Webflow Designer
  2. Go to Page Settings → Custom Code → Before </body> tag
  3. Paste the embed code
  4. Publish

Performance Considerations

Does the Widget Slow Down My Site?

No. The widget script:

  • Loads asynchronously (doesn't block rendering)
  • Is ~30KB gzipped (smaller than most images)
  • Initializes after the page is interactive
  • Doesn't affect Core Web Vitals (LCP, FID, CLS)

Content Security Policy (CSP)

If your site uses a Content Security Policy, add these directives:

script-src 'self' https://launchchat.dev;
connect-src 'self' https://launchchat.dev;
style-src 'self' 'unsafe-inline';

Subresource Integrity (SRI)

For maximum security, you can add SRI to the script tag. Contact support for the current hash.

Troubleshooting

Widget Doesn't Appear

  1. Check the browser console for errors
  2. Verify the widget ID is correct
  3. Ensure the script URL is https://launchchat.dev/widget.js (not http)
  4. Check if a Content Security Policy is blocking the script
  5. Verify the widget is active in your LaunchChat dashboard

Widget Appears But Doesn't Respond

  1. Check the browser console for API errors
  2. Verify your knowledge base has indexed content
  3. Test the widget in the LaunchChat dashboard preview first

Widget Conflicts With Other Scripts

The widget uses Shadow DOM to isolate its styles. If you experience conflicts:

  1. Check if another chat widget is loaded (only one should be active)
  2. Ensure no other script is overwriting window.NotionSupportConfig

Advanced: Programmatic Control

The widget exposes a JavaScript API for programmatic control:

// Open the widget
window.LaunchChat?.open();

// Close the widget
window.LaunchChat?.close();

// Toggle the widget
window.LaunchChat?.toggle();

This is useful for:

  • Opening the widget from a custom "Help" button
  • Triggering the widget based on user behavior
  • Integrating with your app's navigation

Generate Your Embed Code

Don't want to write code manually? Use our Widget Code Generator to generate platform-specific embed code with your widget ID pre-filled.

Get started — embed your AI support widget on any platform.