4lejandrito/next-plausible

Simple integration for https://nextjs.org and https://plausible.io analytics

TypeScript

709

256 commits

updated Apr 3, 2026

See the code

README

Next-Plausible · npm version

Simple integration for https://nextjs.org and https://plausible.io analytics.

See it in action at https://next-plausible.vercel.app, and this commit for a real world example.

Important: If you're using a version of next lower than 11.1.0 please use next-plausible@2 to avoid type checking errors (see https://github.com/4lejandrito/next-plausible/issues/25).

Upgrading from v3? See the migration guide.

Usage

Include the Analytics Script

To enable Plausible analytics in your Next.js app you'll need to expose the Plausible context, <PlausibleProvider />, at the top level of your application inside _app.js.

First, find your site-specific script URL in your Plausible dashboard (it looks like https://plausible.io/js/pa-XXXXX.js).

// pages/_app.js
import PlausibleProvider from 'next-plausible'

export default function MyApp({ Component, pageProps }) {
  return (
    <PlausibleProvider src="https://plausible.io/js/pa-XXXXX.js">
      <Component {...pageProps} />
    </PlausibleProvider>
  )
}

If you want to enable Plausible analytics only on a single page you can wrap the page in a PlausibleProvider component:

// pages/home.js
import PlausibleProvider from 'next-plausible'

export default Home() {
  return (
    <PlausibleProvider src="https://plausible.io/js/pa-XXXXX.js">
      <h1>My Site</h1>
      {/* ... */}
    </PlausibleProvider>
  )
}

If you are using the app directory use PlausibleProvider inside the root layout:

// app/layout.js
import PlausibleProvider from 'next-plausible'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <PlausibleProvider src="https://plausible.io/js/pa-XXXXX.js">
          {children}
        </PlausibleProvider>
      </body>
    </html>
  )
}

PlausibleProvider Props

NameDescription
srcThe site-specific script URL from your Plausible dashboard, e.g. https://plausible.io/js/pa-XXXXX.js. Not required when using withPlausibleProxy.
initOptions passed to plausible.init(). See below for available options.
enabledUse this to explicitly decide whether or not to render script. If not passed the script will be rendered in production environments (checking NODE_ENV and VERCEL_ENV).
integrityOptionally define the subresource integrity attribute for extra security.
scriptPropsOptionally override any of the props passed to the script element. See example.

init Options

These are passed directly to plausible.init():

NameDescription
customPropertiesSet custom properties as an object or function.
endpointSet a custom tracking endpoint. When using the proxy this is set automatically.
fileDownloadsTrack only certain file types as downloads, e.g. { fileExtensions: ['pdf'] }.
hashBasedRoutingSet to true to enable hash-based routing.
autoCapturePageviewsSet to false to disable automatic pageview events.
captureOnLocalhostSet to true to enable localhost tracking.

Proxy the Analytics Script

To avoid being blocked by adblockers plausible recommends proxying the script. To do this you need to wrap your next.config.js with the withPlausibleProxy function:

const { withPlausibleProxy } = require('next-plausible')

module.exports = withPlausibleProxy({
  src: 'https://plausible.io/js/pa-XXXXX.js',
})({
  // ...your next js config, if any
  // Important! it is mandatory to pass a config object, even if empty
})

This will set up the necessary rewrites and configure PlausibleProvider to use the local proxy URLs automatically. When the proxy is active, src is not required:

<PlausibleProvider>...</PlausibleProvider>

Optionally you can override the local paths for the proxied script and API endpoint:

const { withPlausibleProxy } = require('next-plausible')

module.exports = withPlausibleProxy({
  src: 'https://plausible.io/js/pa-XXXXX.js',
  scriptPath: '/yourpath/script.js',
  apiPath: '/yourpath/api/event',
})({
  // ...your next js config, if any
  // Important! it is mandatory to pass a config object, even if empty
})

By default the script is served from /js/script.js and the API endpoint from /api/event, matching Plausible's recommended proxy paths.

Notes:

  • Proxying will only work if you serve your site using next start. Statically generated sites won't be able to rewrite the requests.

  • If you are self hosting plausible, use your instance URL as src.

  • Bear in mind that tracking requests will be made to the same domain, so cookies will be forwarded. See https://github.com/4lejandrito/next-plausible/issues/67. If this is an issue for you, from next@13.0.0 you can use middleware to strip the cookies like this:

    import { NextResponse } from 'next/server'
    
    export function middleware(request) {
      const requestHeaders = new Headers(request.headers)
      requestHeaders.set('cookie', '')
      return NextResponse.next({
        request: {
          headers: requestHeaders,
        },
      })
    }
    
    export const config = {
      matcher: '/proxy/api/event',
    }
    

Send Custom Events

Plausible supports custom events as described at https://plausible.io/docs/custom-event-goals. This package provides the usePlausible hook to safely access the plausible function like this:

import { usePlausible } from 'next-plausible'

export default function PlausibleButton() {
  const plausible = usePlausible()

  return (
    <>
      <button onClick={() => plausible('customEventName')}>Send</button>

      <button
        id="foo"
        onClick={() =>
          plausible('customEventName', {
            props: {
              buttonId: 'foo',
            },
          })
        }
      >
        Send with props
      </button>
    </>
  )
}

If you use Typescript you can type check your custom events like this:

import { usePlausible } from 'next-plausible'

type MyEvents = {
  event1: { prop1: string }
  event2: { prop2: string }
  event3: never
}

const plausible = usePlausible<MyEvents>()

Only those events with the right props will be allowed to be sent using the plausible function.

Developing

  • npm run build will generate the production scripts under the dist folder.
nextjs
plausible
plausible-analytics

4lejandrito/next-plausible

Simple integration for https://nextjs.org and https://plausible.io analytics

TypeScript

709

256 commits

updated Apr 3, 2026

See the code

README

Next-Plausible · npm version

Simple integration for https://nextjs.org and https://plausible.io analytics.

See it in action at https://next-plausible.vercel.app, and this commit for a real world example.

Important: If you're using a version of next lower than 11.1.0 please use next-plausible@2 to avoid type checking errors (see https://github.com/4lejandrito/next-plausible/issues/25).

Upgrading from v3? See the migration guide.

Usage

Include the Analytics Script

To enable Plausible analytics in your Next.js app you'll need to expose the Plausible context, <PlausibleProvider />, at the top level of your application inside _app.js.

First, find your site-specific script URL in your Plausible dashboard (it looks like https://plausible.io/js/pa-XXXXX.js).

// pages/_app.js
import PlausibleProvider from 'next-plausible'

export default function MyApp({ Component, pageProps }) {
  return (
    <PlausibleProvider src="https://plausible.io/js/pa-XXXXX.js">
      <Component {...pageProps} />
    </PlausibleProvider>
  )
}

If you want to enable Plausible analytics only on a single page you can wrap the page in a PlausibleProvider component:

// pages/home.js
import PlausibleProvider from 'next-plausible'

export default Home() {
  return (
    <PlausibleProvider src="https://plausible.io/js/pa-XXXXX.js">
      <h1>My Site</h1>
      {/* ... */}
    </PlausibleProvider>
  )
}

If you are using the app directory use PlausibleProvider inside the root layout:

// app/layout.js
import PlausibleProvider from 'next-plausible'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <PlausibleProvider src="https://plausible.io/js/pa-XXXXX.js">
          {children}
        </PlausibleProvider>
      </body>
    </html>
  )
}

PlausibleProvider Props

NameDescription
srcThe site-specific script URL from your Plausible dashboard, e.g. https://plausible.io/js/pa-XXXXX.js. Not required when using withPlausibleProxy.
initOptions passed to plausible.init(). See below for available options.
enabledUse this to explicitly decide whether or not to render script. If not passed the script will be rendered in production environments (checking NODE_ENV and VERCEL_ENV).
integrityOptionally define the subresource integrity attribute for extra security.
scriptPropsOptionally override any of the props passed to the script element. See example.

init Options

These are passed directly to plausible.init():

NameDescription
customPropertiesSet custom properties as an object or function.
endpointSet a custom tracking endpoint. When using the proxy this is set automatically.
fileDownloadsTrack only certain file types as downloads, e.g. { fileExtensions: ['pdf'] }.
hashBasedRoutingSet to true to enable hash-based routing.
autoCapturePageviewsSet to false to disable automatic pageview events.
captureOnLocalhostSet to true to enable localhost tracking.

Proxy the Analytics Script

To avoid being blocked by adblockers plausible recommends proxying the script. To do this you need to wrap your next.config.js with the withPlausibleProxy function:

const { withPlausibleProxy } = require('next-plausible')

module.exports = withPlausibleProxy({
  src: 'https://plausible.io/js/pa-XXXXX.js',
})({
  // ...your next js config, if any
  // Important! it is mandatory to pass a config object, even if empty
})

This will set up the necessary rewrites and configure PlausibleProvider to use the local proxy URLs automatically. When the proxy is active, src is not required:

<PlausibleProvider>...</PlausibleProvider>

Optionally you can override the local paths for the proxied script and API endpoint:

const { withPlausibleProxy } = require('next-plausible')

module.exports = withPlausibleProxy({
  src: 'https://plausible.io/js/pa-XXXXX.js',
  scriptPath: '/yourpath/script.js',
  apiPath: '/yourpath/api/event',
})({
  // ...your next js config, if any
  // Important! it is mandatory to pass a config object, even if empty
})

By default the script is served from /js/script.js and the API endpoint from /api/event, matching Plausible's recommended proxy paths.

Notes:

  • Proxying will only work if you serve your site using next start. Statically generated sites won't be able to rewrite the requests.

  • If you are self hosting plausible, use your instance URL as src.

  • Bear in mind that tracking requests will be made to the same domain, so cookies will be forwarded. See https://github.com/4lejandrito/next-plausible/issues/67. If this is an issue for you, from next@13.0.0 you can use middleware to strip the cookies like this:

    import { NextResponse } from 'next/server'
    
    export function middleware(request) {
      const requestHeaders = new Headers(request.headers)
      requestHeaders.set('cookie', '')
      return NextResponse.next({
        request: {
          headers: requestHeaders,
        },
      })
    }
    
    export const config = {
      matcher: '/proxy/api/event',
    }
    

Send Custom Events

Plausible supports custom events as described at https://plausible.io/docs/custom-event-goals. This package provides the usePlausible hook to safely access the plausible function like this:

import { usePlausible } from 'next-plausible'

export default function PlausibleButton() {
  const plausible = usePlausible()

  return (
    <>
      <button onClick={() => plausible('customEventName')}>Send</button>

      <button
        id="foo"
        onClick={() =>
          plausible('customEventName', {
            props: {
              buttonId: 'foo',
            },
          })
        }
      >
        Send with props
      </button>
    </>
  )
}

If you use Typescript you can type check your custom events like this:

import { usePlausible } from 'next-plausible'

type MyEvents = {
  event1: { prop1: string }
  event2: { prop2: string }
  event3: never
}

const plausible = usePlausible<MyEvents>()

Only those events with the right props will be allowed to be sent using the plausible function.

Developing

  • npm run build will generate the production scripts under the dist folder.
nextjs
plausible
plausible-analytics

Project health

Overall

2.8/10

Maintained

0/10

Code review

0/10
OpenSSF Scorecard

Latest release

4.0.0 · Apr 3, 2026

Releases this year

2

Significant stargazers

Leo Ostera

945 followers · starred Oct 2023

Guilherme Oenning

421 followers · starred Aug 2022

Juho Vepsäläinen

2,224 followers · starred Sep 2024

Andrey Okonetchnikov

1,089 followers · starred Sep 2024