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.
-
Pick the file for your router: the root
app/layout.tsxon the App Router, orpages/_app.tsxon the Pages Router — either way the loader is installed once for all routes. -
Import
Scriptfromnext/scriptand add the tag from the matching snippet below. -
Swap
pub_your_site_keyfor 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.
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.
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.