Skip to content

Install guides / React

Install the SupportHQ widget in a React app

In a React single-page app the widget is loaded once with an effect at the root of the tree: append the CDN script, call init when it loads, and call destroy on unmount. The SupportHQ dashboard generates this component for you.

Because the SPA never reloads the page, one mount at the root is all that is needed. Route changes inside the app do not affect the launcher.

Requirements: Works with any React 16.8+ app: Vite, Create React App, Remix, or a custom setup.

Steps

  1. 1

    Copy the React snippet from SupportHQ

    In the SupportHQ dashboard open your project, go to Integrations, choose Web chat, switch the framework selector to React, and copy the component.

  2. 2

    Add the effect at the root

    Put the useEffect in your root component (App.tsx) or a small SupportHQWidget component rendered once from the root. Do not render it inside routed pages.

  3. 3

    Keep the cleanup

    The returned cleanup calls window.SupportHQWidget?.destroy(). Keep it: it prevents duplicate launchers during hot reload and in Strict Mode.

  4. 4

    Run and check

    Start the dev server. The launcher should appear once the app has rendered.

Where it goes: The root component, rendered once. For Remix, the root route component.

The snippet

Replace YOUR_PROJECT_ID, or copy the ready-made version from Integrations, Web chat in your dashboard.

import { useEffect } from 'react'

export default function App() {
  useEffect(() => {
    const script = document.createElement('script')
    script.src = 'https://cdn.supporthq.app/widget/latest/supporthq-widget.js'
    script.async = true
    script.onload = () => window.SupportHQWidget?.init({
      projectId: 'YOUR_PROJECT_ID',
    })
    document.body.appendChild(script)
    return () => { window.SupportHQWidget?.destroy() }
  }, [])

  return <>{/* your app */}</>
}

Things that go wrong on React

  • Rendering the effect inside a routed page mounts and destroys the widget on every navigation. Keep it at the root.
  • React Strict Mode runs effects twice in development. The destroy() cleanup makes that safe; without it you get two launchers in dev.
  • If your app uses a Content Security Policy, allow cdn.supporthq.app for scripts and api.supporthq.app for connections.
  • For TypeScript, the window.SupportHQWidget type is declared by the widget; if your build complains, add a small global declaration with init, destroy, open, and close.

Verify it works

  1. Open the app. The launcher should appear once, and the Network tab should show supporthq-widget.js loading from the CDN.
  2. Navigate inside the app. The launcher should persist without duplicating.
  3. Ask a question your knowledge base covers and confirm it replies from your content. Ask something it does not cover and confirm it hands off.
  4. Check the SupportHQ inbox for the test conversation.

FAQ

Can I pass user details to the conversation?

Yes. Pass a metadata object to init (for example the page, plan, or an internal user ID). It appears on the conversation in the SupportHQ inbox so your team has context on handoff.

Where do I find my project ID?

In the SupportHQ dashboard, open your project, go to Integrations, and choose Web chat. The embed code shown there already contains your project ID and any options you set (theme color, position, required fields). Copy it from there instead of typing it.

Will the widget slow my site down?

The script loads from a CDN. Place it at the end of the body, or use the async pattern shown for React and Next.js, and it will not block your page from rendering. Your content paints first.

Can I put the widget inside the page instead of a floating bubble?

Yes. Add a container element and pass mode: "embedded" and, if needed, container: "#your-id" to init. The chat renders inside that element at the width and height you set.