FeedbackJar

Next.js Installation

Integrate FeedbackJar into your Next.js application.

App Router (Next.js 13+)

Add Script to Root Layout

In your app/layout.tsx:

tsx
import Script from 'next/script';

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

        <Script
          src="https://cdn.feedbackjar.com/sdk.js"
          strategy="afterInteractive"
        />
        <Script id="feedbackjar-init" strategy="afterInteractive">
          {`window.fj.init('${process.env.NEXT_PUBLIC_FEEDBACKJAR_ID}');`}
        </Script>
      </body>
    </html>
  );
}

Environment Variables

Add to .env.local:

bash
NEXT_PUBLIC_FEEDBACKJAR_ID=your_widget_id

Pages Router (Next.js 12 and below)

Add to _app.tsx

tsx
import Script from 'next/script';
import type { AppProps } from 'next/app';

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

      <Script
        src="https://cdn.feedbackjar.com/sdk.js"
        strategy="afterInteractive"
      />
      <Script id="feedbackjar-init" strategy="afterInteractive">
        {`window.fj.init('${process.env.NEXT_PUBLIC_FEEDBACKJAR_ID}');`}
      </Script>
    </>
  );
}

User Identification with Server Components

Sign identity on your API (Auto-login), then pass the full payload into a client component. Unsigned id/email only personalizes the widget — see User Identification.

tsx
'use client';

import { useEffect } from 'react';

type IdentifyPayload = {
  id: string;
  email: string;
  firstName?: string;
  lastName?: string;
  organizationId: string;
  signature: string;
  timestamp: number;
};

export function FeedbackJarIdentify({
  payload,
}: {
  payload: IdentifyPayload | null;
}) {
  useEffect(() => {
    if (!window.fj) return;
    if (!payload?.signature) {
      window.fj.identify(null);
      return;
    }
    window.fj.identify(payload);
  }, [payload]);

  return null;
}

Use it in your layout after loading the signed payload from your backend:

tsx
import { FeedbackJarIdentify } from './FeedbackJarIdentify';
import { getFeedbackJarIdentifyPayload } from '@/lib/feedbackjar';

export default async function RootLayout({ children }) {
  const payload = await getFeedbackJarIdentifyPayload();

  return (
    <html>
      <body>
        {children}
        <FeedbackJarIdentify payload={payload} />
      </body>
    </html>
  );
}

Route-Specific Configuration

Show widget only on specific routes:

tsx
'use client';

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

export function FeedbackJarControl() {
  const pathname = usePathname();

  useEffect(() => {
    if (!window.fj) return;

    // Hide on auth pages
    if (pathname.startsWith('/auth')) {
      window.fj.setWidgetEnabled(false);
    } else {
      window.fj.setWidgetEnabled(true);
    }
  }, [pathname]);

  return null;
}