← All articles

How to add a support widget to a Next.js or React app

Adding a third-party widget to a React app is where a lot of teams accidentally tank their Core Web Vitals — a synchronous script in the wrong place blocks hydration. The good news: a support widget should be the last thing that loads, and React gives you clean ways to do exactly that. Here’s how to add one to Next.js (App Router and Pages Router) and to a plain React app.

Next.js — App Router (app/)

Use next/script with strategy="lazyOnload" so the widget loads after the page is interactive. Add it once in your root layout:

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

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://app.simplesupport.uk/widget/widget.js"
          data-key="your-api-key"
          strategy="lazyOnload"
        />
      </body>
    </html>
  );
}

lazyOnload is the key: the support button isn’t above-the-fold and doesn’t need to block anything.

Next.js — Pages Router (pages/)

Same idea in pages/_app.tsx:

import Script from "next/script";

export default function App({ Component, pageProps }) {
  return (
    <>
      <Component {...pageProps} />
      <Script
        src="https://app.simplesupport.uk/widget/widget.js"
        data-key="your-api-key"
        strategy="lazyOnload"
      />
    </>
  );
}

Plain React (Vite, CRA, etc.)

No next/script? Inject the script once on mount and guard against double-loading (important with React 18 Strict Mode, which mounts effects twice in dev):

import { useEffect } from "react";

export function SupportWidget() {
  useEffect(() => {
    if (document.querySelector("script[data-key][src*='widget.js']")) return;
    const s = document.createElement("script");
    s.src = "https://app.simplesupport.uk/widget/widget.js";
    s.setAttribute("data-key", "your-api-key");
    s.async = true;
    document.body.appendChild(s);
  }, []);
  return null;
}

Render <SupportWidget /> once near the root of your tree.

A note for SPAs

The widget mounts a single floating button and manages its own DOM, so it survives client-side route changes — you don’t need to re-initialise it on navigation. Load it once, leave it alone.

Keep your API key public-safe

The data-key is a publishable widget key, scoped to creating tickets from your authorised domain — it’s meant to live in client code, like a Stripe publishable key. Set your domain in the dashboard so the key only works from your site.

That’s the whole integration: one script, loaded lazily, and every support request from your app becomes a tracked ticket. Start free — 100 tickets a month, no credit card.

Start free — no credit card

Add a ticket system to your website in one line of code. Free forever for 100 tickets/month.

Contact Us

Have a question or need help? Send us a message.

One quick step — enter your invitation code

To start your trial, enter an invitation code. Anyone already on a paid plan can share one with you — they get a fresh one every week from their dashboard. No one to ask? .