Docs

Next.js Integration Guide

Add Heyo live chat to your Next.js app with support for App Router and Pages Router.

This guide shows you how to add Heyo to your Next.js application. Compatible with both App Router (Next.js 13+) and Pages Router.

Installation

App Router (Next.js 13+)

Install the SDK:

npm install @heyo.so/js

Create a client component components/chat-widget.tsx:

'use client';

import { useEffect } from 'react';
import HEYO from '@heyo.so/js'; // or: import { HEYO } from '@heyo.so/js'

export const ChatWidget = () => {
  useEffect(() => {
    HEYO.init({ projectId: 'YOUR_PROJECT_ID' });
  }, []);

  return null;
};

Then add it to your app/layout.tsx:

import { ChatWidget } from '@/components/chat-widget';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        {children}
        <ChatWidget />
      </body>
    </html>
  );
}

Option 2: Script Tag in Layout

Add the Heyo script to app/layout.tsx:

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <head>
        <script
          src="https://heyo.so/embed/script"
          defer
          data-project-id="YOUR_PROJECT_ID"
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

Pages Router

Option 1: JavaScript SDK

Install the SDK and create a client component as shown above, then add to pages/_app.tsx:

import { ChatWidget } from '@/components/chat-widget';

export default function App({ Component, pageProps }) {
  return (
    <>
      <Component {...pageProps} />
      <ChatWidget />
    </>
  );
}

Option 2: Script Tag in Document

Add the script to pages/_document.tsx:

import { Html, Head, Main, NextScript } from 'next/document';

export default function Document() {
  return (
    <Html lang="en">
      <Head>
        <script
          src="https://heyo.so/embed/script"
          defer
          data-project-id="YOUR_PROJECT_ID"
        />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

TypeScript Support

Heyo works seamlessly with TypeScript. Install the SDK for full type safety:

npm install @heyo.so/js
// Both import styles work
import HEYO from '@heyo.so/js';
// or: import { HEYO } from '@heyo.so/js';

HEYO.init({ projectId: 'YOUR_PROJECT_ID' });

Advanced Usage

Dynamic Widget Control

Control the widget based on routes or user state:

'use client';

import { useEffect } from 'react';
import { usePathname } from 'next/navigation';

export const ChatWidget = () => {
  const pathname = usePathname();

  useEffect(() => {
    // Hide chat on checkout pages
    if (pathname?.includes('/checkout')) {
      window.HEYO?.hide();
    } else {
      window.HEYO?.show();
    }
  }, [pathname]);

  useEffect(() => {
    HEYO.init({ projectId: 'YOUR_PROJECT_ID' });
  }, []);

  return null;
};

Pass Server Data to Widget

Use server components to pass data to the chat widget:

// app/layout.tsx
import { ChatWidget } from '@/components/chat-widget';
import { getUser } from '@/lib/auth';

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const user = await getUser();

  return (
    <html lang="en">
      <body>
        {children}
        <ChatWidget user={user} />
      </body>
    </html>
  );
}

// components/chat-widget.tsx
'use client';

import { useEffect } from 'react';
import HEYO from '@heyo.so/js'; // or: import { HEYO } from '@heyo.so/js'

export const ChatWidget = ({ user }: { user: any }) => {
  useEffect(() => {
    HEYO.init({
      projectId: 'YOUR_PROJECT_ID',
      user: user
        ? {
            name: user.name,
            email: user.email,
          }
        : undefined,
    });
  }, [user]);

  return null;
};

Performance Optimization

Lazy Loading

For optimal performance, lazy load the chat widget:

'use client';

import dynamic from 'next/dynamic';

const ChatWidget = dynamic(() => import('@/components/chat-widget'), {
  ssr: false,
});

export default ChatWidget;

Core Web Vitals

Heyo is optimized to have minimal impact on your Core Web Vitals:

  • Loads asynchronously with defer
  • Minimal bundle size
  • No render-blocking resources

Best Practices

  • Add Heyo to your root layout for site-wide availability
  • Use client components when you need programmatic control
  • Leverage Next.js routing to show/hide chat on specific pages
  • Pass user context for personalized support experiences

Troubleshooting

Script not loading in production

Ensure the script tag is in the <head> of your document, not in a component that might be conditionally rendered.

Hydration mismatch

If using the script tag in a client component, you may see hydration warnings. Use the SDK method instead.

Widget not persisting across routes

Make sure Heyo is initialized in your root layout, not in individual pages.

Next Steps