Docs menu

Install StageWhisper in Next.js

Next.js has a first-class home for third-party scripts: next/script. Its <Script> component renders the StageWhisper loader tag for you and forwards custom data-* attributes — and a nonce, if you set one — to the rendered <script> tag, so the install is one component in one file.

Prerequisites

  • A StageWhisper site created in the dashboard.
  • Your app’s origin on the site’s origin allowlist — enable the localhost toggle if you’re testing locally.

Install with next/script

Use strategy="afterInteractive" — it’s the default, and the right choice here: the script loads client-side after some hydration, which is exactly when a feedback widget should arrive.

  1. Pick the file for your router: the root app/layout.tsx on the App Router, or pages/_app.tsx on the Pages Router — either way the loader is installed once for all routes.
  2. Import Script from next/script and add the tag from the matching snippet below.
  3. Swap pub_your_site_key for the public site key shown on your site’s install page in the dashboard.

App Router

Place the <Script> in the root app/layout.tsx so it loads once for every route in your app.

App Router — 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://cdn.stagewhisper.co/loader.js"
          data-sw-key="pub_your_site_key"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}

Pages Router

On the Pages Router, the once-for-all-routes home is pages/_app.tsx.

Pages Router — pages/_app.tsx
import Script from "next/script";
import type { AppProps } from "next/app";

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <Script
        src="https://cdn.stagewhisper.co/loader.js"
        data-sw-key="pub_your_site_key"
        strategy="afterInteractive"
      />
      <Component {...pageProps} />
    </>
  );
}

Why not beforeInteractive?

beforeInteractive is reserved for critical scripts that must execute before any Next.js modules run — and it has to live in the root layout (App Router) or _document (Pages Router). A feedback widget gains nothing from loading that early, and it would compete with hydration for bandwidth and main-thread time. Stick with afterInteractive.

Running a strict Content Security Policy? <Script> forwards a nonce prop to the rendered tag, and the Content Security Policy guide covers the exact directives and where the nonce goes.

Client-side navigation

Route changes via <Link> or the router are handled automatically — the widget re-evaluates your URL rules whenever Next.js updates history state, so a single install covers every route with no extra wiring.

Verify

Refresh your app, then watch the site’s install status in the dashboard — it flips the moment the first ping arrives.

Widget not showing up? Head to Troubleshooting for the usual suspects — blocked origins, CSP, localhost, and stale config.