Install Pengo on Next.js and React
Add the Pengo chat widget to a Next.js app with the Script component in your root layout, or to any React single-page app through index.html.
On this page
Pengo works in single-page apps without any extra setup. You load the snippet once in your app’s root, and the widget follows your router from page to page. This guide covers the Next.js App Router, the Pages Router and plain React apps.
#Next.js (App Router)
-
Open your root layout,
app/layout.tsx(orapp/layout.js). -
Import
Scriptfromnext/scriptat the top of the file. -
Add the Pengo
Scriptinside the<body>element, after{children}.import Script from 'next/script'; // In your layout.tsx <body>: <Script id="pengo-chat" strategy="afterInteractive"> {` window.pengo = window.pengo || function() { (window.pengo.q = window.pengo.q || []).push(arguments); }; window.pengo.propertyId = 'YOUR_PROPERTY_ID'; window.pengo.q = window.pengo.q || []; var s = document.createElement('script'); s.async = true; s.src = 'https://app.pengo.chat/embed.js'; document.head.appendChild(s); `} </Script>The
afterInteractivestrategy loads it once the page is interactive, so it never delays your first render. -
Save, then run your app or deploy. The chat bubble appears in the corner on every route.
Because it’s in the root layout, the widget loads once and stays mounted as visitors move between pages.
#Pages Router
If your app uses the pages directory, add the same Script element to pages/_app.tsx (or pages/_app.js), next to your <Component {...pageProps} />, so it’s part of every page.
#React single-page apps
For React apps built with Vite, Create React App or a similar tool, you don’t need any React code. Paste the HTML snippet into the HTML file your app is served from:
- Vite:
index.htmlin the project root - Create React App:
public/index.html
Put it just above the closing </body> tag:
<!-- Pengo Widget -->
<script>
(function() {
// A stub, so pengo('identify', …) and other calls work before the widget has loaded.
window.pengo = window.pengo || function() { (window.pengo.q = window.pengo.q || []).push(arguments); };
window.pengo.propertyId = 'YOUR_PROPERTY_ID';
window.pengo.q = window.pengo.q || [];
var script = document.createElement('script');
script.async = true;
script.src = 'https://app.pengo.chat/embed.js?v=2';
var firstScript = document.getElementsByTagName('script')[0];
firstScript.parentNode.insertBefore(script, firstScript);
})();
</script> Then rebuild and deploy.
#Client-side navigation
You don’t need to do anything when your router changes pages. Pengo listens for client-side navigation (the browser’s pushState, replaceState and back/forward events). On each route change it:
- records a page view, so your team sees the page the visitor is on
- checks your page rules again, such as the pages the launcher shows on, proactive messages and auto-open
The chat stays open, with the conversation in place, while the visitor moves around your app.
#Signed-in users
If your app has accounts, you can tell Pengo who’s chatting so conversations follow them across devices. Call pengo('identify', ...) with a hash computed on your server, and pengo('shutdown') when they sign out. Identity verification has ready-made React and Next.js code.
For everything else you can do from code, such as opening the chat from your own button, see the JavaScript API.
#Check that it works
Open your deployed app and look for the bubble, then confirm that Pengo has detected the install. Verify your installation walks through it. If your site sends a Content Security Policy, that page also lists the hosts to allow.
#Other platforms
Common questions
Do I need to reload the widget when the route changes?
No. Pengo notices client-side navigation on its own and keeps the chat open across route changes.
Is there an npm package?
No. Pengo installs with a script, so there's nothing to add to your dependencies.
Was this guide helpful?
Your answer helps us improve it.
Sorry about that. or contact support, and we'll fix the guide.