INTEGRATIONS

Next.js + Shoutjar

Add testimonial widgets to your Next.js app. Script tag embed or React component. SSR compatible. Minimal bundle impact.

Works with App Router & Pages Router
SSR compatible
TypeScript support
N
Next.js
Shoutjar

Method 1: Script Tag Embed

The fastest way to add Shoutjar to Next.js. Works with both App Router and Pages Router.

N
App Router (app/)

Add the script in your root layout:

app/layout.tsx
import Script from 'next/script'

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://cdn.shoutjar.com/widget.js"
          strategy="lazyOnload"
        />
      </body>
    </html>
  )
}

Then add the widget HTML wherever you need it:

app/page.tsx
export default function Home() {
  return (
    <main>
      <h1>Welcome</h1>
      <div
        data-shoutjar-widget="YOUR_WIDGET_ID"
        data-shoutjar-style="carousel"
      />
    </main>
  )
}

P
Pages Router (pages/)

Add script in _app.tsx or _document.tsx:

pages/_app.tsx
import Script from 'next/script'

export default function App({ Component, pageProps }) {
  return (
    <>
      <Component {...pageProps} />
      <Script
        src="https://cdn.shoutjar.com/widget.js"
        strategy="lazyOnload"
      />
    </>
  )
}

Script Loading Strategies

lazyOnloadLoads after page is interactive (recommended)
afterInteractiveLoads immediately after hydration
beforeInteractiveLoads before hydration (not recommended for widgets)

Method 2: React Component

For better control and TypeScript support, use our React wrapper.

Install

Terminal
npm install @shoutjar/react
# or
yarn add @shoutjar/react
# or
pnpm add @shoutjar/react

Basic Usage

components/Testimonials.tsx
import { ShoutjarWidget } from '@shoutjar/react'

export default function Testimonials() {
  return (
    <ShoutjarWidget
      widgetId="YOUR_WIDGET_ID"
      style="carousel"
    />
  )
}

With Options

components/Testimonials.tsx
import { ShoutjarWidget } from '@shoutjar/react'

export default function Testimonials() {
  return (
    <ShoutjarWidget
      widgetId="YOUR_WIDGET_ID"
      style="grid"
      theme="dark"
      maxItems={6}
      showRating={true}
      className="my-custom-class"
    />
  )
}

TypeScript

Full TypeScript support included:

components/Testimonials.tsx
import { ShoutjarWidget, WidgetStyle, WidgetTheme } from '@shoutjar/react'

interface Props {
  style?: WidgetStyle  // 'grid' | 'carousel' | 'marquee' | 'badge' | 'single'
  theme?: WidgetTheme  // 'light' | 'dark' | 'auto'
}

export default function Testimonials({ style = 'carousel', theme = 'auto' }: Props) {
  return (
    <ShoutjarWidget
      widgetId={process.env.NEXT_PUBLIC_SHOUTJAR_WIDGET_ID!}
      style={style}
      theme={theme}
    />
  )
}

Server-Side Rendering (SSR)

Shoutjar works seamlessly with Next.js server rendering, static generation, and ISR.

Client Component Directive

If using the React component in App Router, add 'use client':

components/Testimonials.tsx
'use client'

import { ShoutjarWidget } from '@shoutjar/react'

export default function Testimonials() {
  return <ShoutjarWidget widgetId="YOUR_WIDGET_ID" />
}

Dynamic Import (Optional)

For code splitting:

components/Testimonials.tsx
import dynamic from 'next/dynamic'

const ShoutjarWidget = dynamic(
  () => import('@shoutjar/react').then(mod => mod.ShoutjarWidget),
  { ssr: false, loading: () => <div>Loading testimonials...</div> }
)

export default function Testimonials() {
  return <ShoutjarWidget widgetId="YOUR_WIDGET_ID" />
}

Static Generation

Widgets work fine with Static Site Generation (SSG). They hydrate client-side after the page loads.

ISR Compatible

Shoutjar updates independently of your Next.js build. New testimonials appear without redeploying.

Configuration Options

Environment Variables

.env.local
NEXT_PUBLIC_SHOUTJAR_WIDGET_ID=your_widget_id
Usage
<ShoutjarWidget
  widgetId={process.env.NEXT_PUBLIC_SHOUTJAR_WIDGET_ID!}
/>

Widget Props

PropTypeDefaultDescription
widgetIdstringrequiredYour Shoutjar widget ID
stylestring'carousel'Widget style: grid, carousel, marquee, badge, single
themestring'auto'Color theme: light, dark, auto
maxItemsnumberundefinedMaximum testimonials to show
showRatingbooleantrueShow star ratings
showSourcebooleantrueShow source icons (Twitter, G2, etc.)
classNamestringundefinedCustom CSS class

Custom Styling

className prop
<ShoutjarWidget
  widgetId="YOUR_WIDGET_ID"
  className="border rounded-lg shadow-lg"
/>

CSS variables for theming:

globals.css
:root {
  --shoutjar-primary: #3B82F6;
  --shoutjar-background: #F9FAFB;
  --shoutjar-text: #111827;
}

Performance & Bundle Size

Script Tag Method

Bundle impactZero
Load time~15KB gzipped
StrategyAfter interactive

React Component

Bundle impact~3KB gzipped
Tree-shakeableYes
DependenciesNone (peer deps only)

Best Practices

1

Use lazyOnload for script tag -- don't block initial render

2

Dynamic import for pages where testimonials are below the fold

3

Single widget instance per page when possible

4

Environment variables -- don't hardcode widget IDs

Core Web Vitals

Shoutjar widgets are designed to not impact:

LCP

Loads after main content

FID

Non-blocking JavaScript

CLS

Fixed dimensions, no layout shift

Common Next.js Patterns

Landing Page Hero

import { ShoutjarWidget } from '@shoutjar/react'

export function Hero() {
  return (
    <section className="py-20">
      <h1>Your Product</h1>
      <p>Your value proposition</p>
      <button>Get Started</button>
      <ShoutjarWidget
        widgetId="YOUR_WIDGET_ID"
        style="badge"
        className="mt-4"
      />
    </section>
  )
}

Pricing Page Trust

import { ShoutjarWidget } from '@shoutjar/react'

export default function Pricing() {
  return (
    <main>
      <PricingTable />
      <section className="mt-16">
        <h2>What Our Customers Say</h2>
        <ShoutjarWidget
          widgetId="YOUR_WIDGET_ID"
          style="grid"
          maxItems={6}
        />
      </section>
    </main>
  )
}

Footer Social Proof Bar

import { ShoutjarWidget } from '@shoutjar/react'

export function Footer() {
  return (
    <footer>
      <ShoutjarWidget
        widgetId="YOUR_WIDGET_ID"
        style="marquee"
        className="border-t"
      />
    </footer>
  )
}

Where Testimonials Come From

Shoutjar pulls in reviews from multiple platforms into one unified widget

Social Media

  • Twitter/X
  • LinkedIn
  • Reddit
  • Hacker News

Manual Entry

  • API or dashboard
  • Add testimonials programmatically
  • Or enter them manually

Auto-Discovery

Shoutjar monitors mentions of your product across the web -- even untagged tweets and Reddit threads.

All sources display in one unified widget -- no multiple integrations needed.

API Access (Optional)

For advanced use cases, fetch testimonials directly via API and render them in Server Components.

API Helper

lib/shoutjar.ts
export async function getTestimonials(widgetId: string) {
  const res = await fetch(
    `https://api.shoutjar.com/v1/widgets/${widgetId}/testimonials`,
    {
      headers: {
        'Authorization': `Bearer ${process.env.SHOUTJAR_API_KEY}`
      },
      next: { revalidate: 3600 }
    }
  )
  return res.json()
}

Use in Server Components

app/page.tsx
import { getTestimonials } from '@/lib/shoutjar'

export default async function Home() {
  const testimonials = await getTestimonials('YOUR_WIDGET_ID')

  return (
    <main>
      {testimonials.map(t => (
        <div key={t.id}>
          <p>{t.content}</p>
          <span>{t.author}</span>
        </div>
      ))}
    </main>
  )
}

Frequently Asked Questions

Does it work with App Router?

Yes. Both script tag and React component work with Next.js 13+ App Router. Use 'use client' directive for the React component.

Does it work with Pages Router?

Yes. Works the same way -- add script in _app.tsx and use widget anywhere.

Is it SSR compatible?

Yes. Widgets render client-side after hydration. No SSR errors. Works with SSG and ISR.

What's the bundle size impact?

Script tag: 0KB (external). React component: ~3KB gzipped.

Can I customize styling?

Yes. Use className prop, CSS variables, or configure in Shoutjar dashboard.

Will it affect my Core Web Vitals?

No. Designed for minimal impact -- lazy loading, no layout shift, non-blocking.

Can I use multiple widgets on one page?

Yes. Each widget can have different styles and configurations.

Is TypeScript supported?

Yes. Full type definitions included with the React package.

Works With Other Platforms Too

Use Shoutjar anywhere you build

Add Social Proof to Your Next.js App

Script tag or React component. SSR compatible. TypeScript support. Ship in 5 minutes.

Get Started Free
Works with App Router & Pages Router
TypeScript support
Free plan available