The Web Ratings

Next.js

Integrate with Next.js App Router or Pages Router

Step 1: Add the Script

Do not add to root layout

Do not add the script to your root app/layout.tsx or pages/_app.tsx — this loads the widget on every page, including public pages, and the auto-prompt will fire for anonymous visitors.

Instead, add it to your authenticated layout (e.g., app/(dashboard)/layout.tsx or a layout that wraps your logged-in area).

App Router (app directory)

Create or update your authenticated layout (e.g., app/(dashboard)/layout.tsx):

import Script from 'next/script';

export default function DashboardLayout({ children }) {
  return (
    <>
      <Script
        src="https://cdn.thewebratings.com/twr.min.js"
        strategy="afterInteractive"
      />
      {children}
    </>
  );
}

Pages Router

Add to a layout component that wraps your authenticated pages (not _app.tsx):

import Script from 'next/script';

function DashboardLayout({ children }) {
  return (
    <>
      <Script
        src="https://cdn.thewebratings.com/twr.min.js"
        strategy="afterInteractive"
      />
      {children}
    </>
  );
}

Step 2: Initialize in Component

App Router Example

'use client';
import { useEffect } from 'react';

export default function DashboardPage() {
  useEffect(() => {
    if (typeof window !== 'undefined' && window.TheWebRatings) {
      window.TheWebRatings
        .init({
          apiKey: process.env.NEXT_PUBLIC_TWR_API_KEY || 'your-api-key',
          debug: true
        })
        .then(() => console.log('TheWebRatings ready'))
        .catch((err) => console.error('Initialization failed:', err));
    }
  }, []);

  const openFeedback = () => {
    // Pass logged-in user (e.g. from session or auth context)
    window.TheWebRatings?.open('[email protected]', 'User Name');
  };

  return <button onClick={openFeedback}>Leave a Review</button>;
}

Pages Router Example

import { useEffect } from 'react';

export default function DashboardPage() {
  useEffect(() => {
    if (typeof window !== 'undefined' && window.TheWebRatings) {
      window.TheWebRatings
        .init({ apiKey: process.env.NEXT_PUBLIC_TWR_API_KEY || 'your-api-key' })
        .catch((err) => console.error('Initialization failed:', err));
    }
  }, []);

  return (
    <button onClick={() => window.TheWebRatings?.open('[email protected]', 'User Name')}>
      Leave a Review
    </button>
  );
}

Environment Variables

Add to .env.local:

NEXT_PUBLIC_TWR_API_KEY=your-api-key

Custom Hook (Optional)

Create hooks/useTheWebRatings.ts:

import { useEffect, useState } from 'react';

export function useTheWebRatings(apiKey: string) {
  const [ready, setReady] = useState(false);

  useEffect(() => {
    if (typeof window === 'undefined' || !window.TheWebRatings) return;
    window.TheWebRatings.init({ apiKey }).then(() => setReady(true)).catch(console.error);
  }, [apiKey]);

  const showWidget = (userEmail: string, userName?: string) => {
    if (ready) window.TheWebRatings?.open(userEmail, userName);
  };

  return { ready, showWidget };
}

Use it:

const { ready, showWidget } = useTheWebRatings(process.env.NEXT_PUBLIC_TWR_API_KEY!);
const user = useUser(); // your auth

return (
  <button onClick={() => showWidget(user.email, user.name)} disabled={!ready}>
    Leave a Review
  </button>
);

Tips

  • Always check typeof window !== 'undefined' for SSR safety
  • Use process.env.NEXT_PUBLIC_* for client-side environment variables
  • Initialize once in your authenticated layout, not in every component — and not in the root layout
  • The strategy="afterInteractive" ensures the script loads after page hydration