Skip to main content
Share
Guides

How to Embed a Chatbot in a React App: Loader Component, Next.js and Testing (2026)

Add a chatbot to a React app the right way: a small loader component that adds the widget script once, mounted at the root so it survives route changes, with user identity passed at load time. Includes Next.js, Strict Mode, performance and testing.

Content & Engineering
May 25, 2026
26 min read
Updated Oct 2026
embed chatbot React appReact chatbot integrationchatbot React componentReact chatbot widgetchatbot useEffect React
TL;DR

Add a chatbot to a React app the right way: a small loader component that adds the widget script once, mounted at the root so it survives route changes, with user identity passed at load time. Includes Next.js, Strict Mode, performance and testing.

Key Takeaways
  • To embed a chatbot in a React app, load the widget script once from a small component mounted at the root of your app, and start the bot in the script's onload callback.
  • Mounting it outside your routes keeps the same conversation open while users navigate, and passing the signed-in user at load time lets the bot greet them by name.
  • The widget is a self-contained web component, so React does not render or re-render it: your component's only job is to load it once at the right time.
  • That keeps the integration small, safe in React 18 and 19 Strict Mode, and easy to test.

The short answer

To embed a chatbot in a React app, load the widget script once from a small component mounted at the root of your app, and start the bot in the script's onload callback. Mounting it outside your routes keeps the same conversation open while users navigate, and passing the signed-in user at load time lets the bot greet them by name.

The widget is a self-contained web component, so React does not render or re-render it: your component's only job is to load it once at the right time. That keeps the integration small, safe in React 18 and 19 Strict Mode, and easy to test.

Step 1: A Loader Component

Create one component that adds the script if it is not already on the page and starts the bot when it loads:

// ConferbotWidget.jsx
import { useEffect } from 'react';

const SRC = 'https://cdn.conferbot.com/dist/v1/widget.min.js';

export default function ConferbotWidget({ botId, embedType = 'live_chat', user }) {
  useEffect(() => {
    // Load the script once, even if the component re-renders or remounts
    if (document.getElementById('conferbot-js')) return;
    const script = document.createElement('script');
    script.id = 'conferbot-js';
    script.src = SRC;
    script.async = true;
    script.onload = () => {
      window.ConferbotWidget(botId, embedType, user ? { user } : undefined);
    };
    document.body.appendChild(script);
  }, [botId, embedType, user]);

  return null; // the widget renders itself as <conferbot-widget>
}

The id check is what makes it safe in Strict Mode, which runs effects twice in development, and when the component remounts. Choose the embed type to match where the chat should appear:

Embed typeWhat it shows
live_chatA launcher bubble that opens the chat window (the usual choice)
popup_chatThe chat opens as a popup
fullpage_chatThe chat fills the page, for a dedicated chat or support page

Step 2: Mount It Once, at the Root

Render the loader outside your router's routes so it is mounted once and never unmounts on navigation:

// App.jsx - mount once, at the root, so it survives route changes
import ConferbotWidget from './ConferbotWidget';

export default function App() {
  return (
    <>
      <Routes />
      <ConferbotWidget botId={import.meta.env.VITE_CONFERBOT_BOT_ID} />
    </>
  );
}

Once loaded, the widget stays on the page across client-side route changes, so the conversation is not lost. To keep it off certain pages, such as checkout or an admin area, use the page rules in the Conferbot dashboard (hide on specific URLs, optionally including their sub-pages) rather than unmounting the component. The same settings let you show it on desktop only, phones only, or both.

Try it yourself
Build your first chatbot free
Free plan, no credit card required. Live on your site in about 10 minutes.
Start building free

Step 3: Pass the Signed-In User

If your app knows who the visitor is, pass it at load time so the bot and your agents see a name and email instead of an anonymous visitor:

<ConferbotWidget
  botId={BOT_ID}
  user={currentUser ? {
    id: currentUser.id,
    name: currentUser.name,
    email: currentUser.email,
  } : undefined}
/>

Because the identity is read when the widget starts, render the loader after your auth state has resolved (for example inside your authenticated layout) if you want logged-in details on the first message. You can also pass customData in the same options object for values such as plan or account ID.

The widget's public interface is deliberately small: one call, ConferbotWidget(botId, embedType, options), where options can carry user (id, name, email and other fields) and customData. Appearance, greeting, which pages it appears on and whether it shows on desktop, phones or both are set in the Conferbot dashboard, not in code. There are no JavaScript methods to open, close or send messages programmatically, so build your integration around loading it once and passing identity at load time.

Styling the Widget

Colours, launcher icon, position, corner radius, fonts and greeting are set in the Conferbot dashboard and apply everywhere the bot runs, so you do not need styled-components, Tailwind or CSS modules for the widget itself. Avoid overriding its internal CSS from your app: internal class names are not a stable API and can change between releases. To try designs before you build, the free chat widget designer previews colours and launchers in a working window.

Try the free chatbot builder
600 conversations a month, every channel, no credit card.
Start free

Next.js, Remix and Server-Side Rendering

The widget needs window and document, so it must only load in the browser. A useEffect never runs on the server, so the loader component above is already SSR-safe in Remix, Gatsby and plain React with SSR. In Next.js, the built-in Script component is the simplest option:

// app/layout.jsx (App Router) or pages/_app.jsx
import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://cdn.conferbot.com/dist/v1/widget.min.js"
          strategy="afterInteractive"
          onLoad={() => window.ConferbotWidget(process.env.NEXT_PUBLIC_CONFERBOT_BOT_ID, 'live_chat')}
        />
      </body>
    </html>
  );
}

See our dedicated Next.js chatbot guide for App Router, Pages Router and loading-strategy details.

Performance

  • Load asynchronously. The loader sets async and runs after your app renders, so it does not block your first paint.
  • Load it later if you prefer. To defer it further, start the loader in requestIdleCallback or after the first user interaction; the chat bubble then appears a moment later.
  • Do not bundle it. Loading from the CDN keeps the widget out of your JavaScript bundle and lets browsers cache it across pages.
  • Measure. Run Lighthouse or PageSpeed Insights before and after adding it to confirm there is no regression on your pages.

Testing and Debugging

In unit tests, mock window.ConferbotWidget and assert that your loader adds the script once and starts the bot with the right arguments:

// ConferbotWidget.test.jsx (Jest or Vitest + React Testing Library)
import { render } from '@testing-library/react';
import ConferbotWidget from './ConferbotWidget';

test('loads the widget script once and starts the bot', () => {
  window.ConferbotWidget = jest.fn();
  render(<ConferbotWidget botId="test-bot" />);
  const script = document.getElementById('conferbot-js');
  expect(script.src).toContain('widget.min.js');
  script.onload();
  expect(window.ConferbotWidget).toHaveBeenCalledWith('test-bot', 'live_chat', undefined);
});

In end-to-end tests (Playwright or Cypress), wait for the conferbot-widget element to appear on the page. If the bubble does not show in a real browser, check the console for a blocked script (a Content Security Policy must allow cdn.conferbot.com), confirm the bot ID, and check that the current URL is not in the dashboard's hidden pages list.

Production Checklist

Before deploying your chatbot-integrated React application to production, verify each item on this checklist.

Performance

  • Chatbot script loads asynchronously (async script tag)
  • The widget loads from the CDN, not your bundle
  • Core Web Vitals show no regression (run Lighthouse before/after)
  • Chatbot initializes after first meaningful paint, not during critical path
  • Content Security Policy allows cdn.conferbot.com

Functionality

  • Widget appears on correct routes and is hidden on excluded routes
  • Conversation persists across route navigation (widget does not remount)
  • User context is passed correctly (test with authenticated and anonymous users)
  • Hidden pages and device rules are set in the dashboard
  • The loader is mounted once, outside the routes
  • Works in React Strict Mode without duplicate widgets

Styling

  • Widget matches brand colors, typography, and border radius
  • Dark mode and light mode both work correctly
  • Widget does not overlap with navigation, CTAs, or critical content
  • Mobile responsiveness is verified on actual devices (not just browser simulation)
  • Z-index is high enough to float above all page elements including modals

SSR and Build

  • No SSR hydration errors in browser console
  • Dynamic import or mounted-state pattern is in place for SSR frameworks
  • Production build completes without chatbot-related warnings
  • Source maps do not expose chatbot configuration or API keys

Accessibility

  • Chat trigger button has proper aria-label
  • Chat window is keyboard navigable (Tab, Enter, Escape to close)
  • Screen readers announce new messages
  • Focus management is correct (focus moves to chat on open, returns to trigger on close)

Security

  • Chatbot script loaded from HTTPS CDN only
  • No sensitive data (API keys, user tokens) exposed in client-side chatbot configuration
  • Content Security Policy (CSP) headers allow chatbot script and WebSocket domains
  • User input is sanitized by the chatbot platform (verify XSS protection)

This checklist ensures your chatbot integration is production-ready across performance, functionality, styling, SSR, accessibility, and security dimensions. For ongoing monitoring, track the chatbot's impact on your Core Web Vitals scores monthly and review conversation analytics weekly during the first month post-launch. For a comprehensive chatbot performance monitoring framework, see our chatbot analytics and metrics guide.

Share this article:

Was this article helpful?

Ready to build your chatbot?

Join the businesses. Deploy on website, WhatsApp, and 11 more channels in minutes. Free forever plan available.

No credit cardNo coding13+ channels
Start Building Free

Get chatbot insights delivered weekly

Join 5,000+ professionals getting actionable AI chatbot strategies, industry benchmarks, and product updates.

🎯Automate this with a free chatbot

Build and deploy in 10 minutes. No coding needed.

❓FAQ

How to Embed a Chatbot in a React App FAQ

Everything you need to know about chatbots for how to embed a chatbot in a react app.

🔍
Popular:

Create a small component that adds the Conferbot widget script once (checking for an existing script ID) and calls window.ConferbotWidget with your bot ID in the script's onload. Render it once at the root of your app, outside your routes, so it loads on every page and keeps the conversation across navigation.

No. The web widget loads from Conferbot's CDN with a script tag, which keeps it out of your bundle and lets browsers cache it. A ten-line loader component gives you the same lifecycle control a package would. The native mobile SDKs, including React Native, are separate and install from GitHub.

Render the loader component outside your router's Routes, at the app root. The script is added once and the widget stays on the page across client-side navigation. To hide it on specific pages, use the hidden pages setting in the Conferbot dashboard instead of unmounting the component.

Load it only in the browser. In Next.js use the Script component with strategy afterInteractive and call window.ConferbotWidget in onLoad; in other frameworks, the useEffect-based loader is already SSR-safe because effects never run on the server.

Yes. Pass a user object with id, name and email (and any other fields) as the third argument to ConferbotWidget, plus customData for values such as plan or account ID. The widget reads them when it starts, so load it after your auth state is known.

Not if the loader checks for its script ID before adding the script. Strict Mode runs effects twice in development, and the ID check makes the second run a no-op, so only one widget is created.

About the Author

Content & Engineering

The Conferbot team writes about building, deploying, and improving AI chatbots.

View all articles
Skip the blank canvas
Start from one of 250+ free chatbot templates for lead generation, support, e-commerce, and 20+ industries - customize and launch in minutes.
Browse free templates

Related Articles

Omnichannel Platform

One Chatbot,
Every Channel

Your chatbot works seamlessly across WhatsApp, Messenger, Slack, and 6 more platforms. Build once, deploy everywhere.

View All Channels
Conferbot
online
Hi! How can I help you today?
I need pricing info
Conferbot
Active now
Welcome! What are you looking for?
Book a demo
Sure! Pick a time slot:
#support
Conferbot
New ticket from Sarah: "Can't access dashboard"
Auto-resolved. Password reset link sent.