npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@actovision/facebook-conversion-api-nextjs

v0.1.0

Published

Next.js integration for Meta's Conversions API (CAPI). App Router + Pages Router route handlers, Meta Pixel script loader, browser fbEvent() helper with automatic Pixel + CAPI deduplication, FacebookCapiClient with full parameter coverage (user_data, app_

Downloads

48

Readme

@actovision/facebook-conversion-api-nextjs

Next.js integration for Meta's Conversions API. Supports App Router and Pages Router. Fully self-contained — talks to the Meta Graph API directly, no companion package required.

  • Server-side CAPI handler (App Router and Pages Router)
  • Browser helper fbEvent() that fires the pixel + the server event with matching eventId for automatic deduplication
  • Meta Pixel <Script> loader and a pageview provider for each router
  • Full parameter coverage: every standard event, every user_data field (including madid, anon_id, ctwa_clid, ig_account_id, ig_sid, page_id, page_scoped_user_id), app_data for app-source events, referrer_url, LDU/CCPA, test events, deduplication
  • Auto-detects cf-connecting-ip / x-real-ip / x-forwarded-for, Referer, and reconstructs fbc from fbclid when the _fbc cookie is absent
  • Defaults to Graph API v22.0 — configurable via apiVersion
  • Zero runtime dependencies — only next + react peers

Install

pnpm add @actovision/facebook-conversion-api-nextjs
# peers: next >= 16, react >= 19 — node >= 22

Environment

FB_ACCESS_TOKEN=<your server-only CAPI token>
NEXT_PUBLIC_FB_PIXEL_ID=<your pixel id>

App Router setup

1. Mount the pixel script + provider in your root layout

// app/layout.tsx
import { FBPixelScript, FBPixelProvider } from '@actovision/facebook-conversion-api-nextjs/components'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <FBPixelScript pixelId={process.env.NEXT_PUBLIC_FB_PIXEL_ID!} />
        <FBPixelProvider>{children}</FBPixelProvider>
      </body>
    </html>
  )
}

2. Add the server route

// app/api/fb-events/route.ts
import { createFbEventsRouteHandler } from '@actovision/facebook-conversion-api-nextjs/server'

export const { POST } = createFbEventsRouteHandler({
  accessToken: process.env.FB_ACCESS_TOKEN!,
  pixelId: process.env.NEXT_PUBLIC_FB_PIXEL_ID!,
})

3. Fire events from client components

'use client'
import { fbEvent } from '@actovision/facebook-conversion-api-nextjs/client'

export function BuyButton() {
  return (
    <button
      onClick={() =>
        fbEvent({
          eventName: 'Purchase',
          emails: ['[email protected]'],
          value: 99.99,
          currency: 'USD',
        })
      }
    >
      Buy
    </button>
  )
}

Pages Router setup

// pages/_app.tsx
import {
  FBPixelScript,
  FBPixelProviderPages,
} from '@actovision/facebook-conversion-api-nextjs/components'

export default function App({ Component, pageProps }) {
  return (
    <>
      <FBPixelScript pixelId={process.env.NEXT_PUBLIC_FB_PIXEL_ID!} />
      <FBPixelProviderPages>
        <Component {...pageProps} />
      </FBPixelProviderPages>
    </>
  )
}
// pages/api/fb-events.ts
import { createFbEventsApiHandler } from '@actovision/facebook-conversion-api-nextjs/server'

export default createFbEventsApiHandler({
  accessToken: process.env.FB_ACCESS_TOKEN!,
  pixelId: process.env.NEXT_PUBLIC_FB_PIXEL_ID!,
})

Client-side fbEvent() works identically.

Standard events

Every Meta standard event is supported. fbEvent() fires both the browser pixel and the server event with the same eventId for automatic deduplication. Event names are case-sensitive — use the names exactly as shown.

'use client'
import { fbEvent } from '@actovision/facebook-conversion-api-nextjs/client'

// Purchase — completed transaction
fbEvent({
  eventName: 'Purchase',
  emails: ['[email protected]'],
  phones: ['+1 555 123 4567'],
  value: 99.99,
  currency: 'USD',
  order_id: 'ORDER-12345',
  contents: [{ id: 'sku-1', quantity: 1, item_price: 99.99 }],
  content_ids: ['sku-1'],
  content_type: 'product',
})

// AddToCart — user added an item to cart
fbEvent({
  eventName: 'AddToCart',
  content_ids: ['sku-1'],
  contents: [{ id: 'sku-1', quantity: 1, item_price: 49.99 }],
  content_type: 'product',
  value: 49.99,
  currency: 'USD',
})

// InitiateCheckout — user started checkout
fbEvent({
  eventName: 'InitiateCheckout',
  content_ids: ['sku-1', 'sku-2'],
  num_items: 2,
  value: 79.98,
  currency: 'USD',
})

// AddPaymentInfo — user entered payment info
fbEvent({
  eventName: 'AddPaymentInfo',
  value: 79.98,
  currency: 'USD',
})

// ViewContent — user viewed a product / content page
fbEvent({
  eventName: 'ViewContent',
  content_ids: ['sku-1'],
  content_name: 'Running Shoes',
  content_category: 'Footwear',
  content_type: 'product',
  value: 49.99,
  currency: 'USD',
})

// Search — user performed a search
fbEvent({
  eventName: 'Search',
  search_string: 'running shoes',
  content_ids: ['sku-1', 'sku-2'],
  content_category: 'Footwear',
})

// Lead — form / quote submission
fbEvent({
  eventName: 'Lead',
  emails: ['[email protected]'],
  phones: ['+1 555 000 1111'],
  content_name: 'Newsletter Signup',
  value: 0,
  currency: 'USD',
})

// CompleteRegistration — account created
fbEvent({
  eventName: 'CompleteRegistration',
  emails: ['[email protected]'],
  content_name: 'Free Plan',
  status: 'completed',
  value: 0,
  currency: 'USD',
})

// Subscribe — paid subscription started
fbEvent({
  eventName: 'Subscribe',
  emails: ['[email protected]'],
  value: 9.99,
  currency: 'USD',
  predicted_ltv: 120,
})

// StartTrial — free trial activated
fbEvent({
  eventName: 'StartTrial',
  emails: ['[email protected]'],
  value: 0,
  currency: 'USD',
  predicted_ltv: 120,
})

// AddToWishlist — user saved item to wishlist
fbEvent({
  eventName: 'AddToWishlist',
  content_ids: ['sku-1'],
  value: 49.99,
  currency: 'USD',
})

// FindLocation — looked up a physical business location
fbEvent({ eventName: 'FindLocation', content_name: 'Downtown Store' })

// Schedule — booked an appointment
fbEvent({
  eventName: 'Schedule',
  emails: ['[email protected]'],
  content_name: 'Consultation',
})

// SubmitApplication — applied for product/service
fbEvent({
  eventName: 'SubmitApplication',
  emails: ['[email protected]'],
  value: 0,
  currency: 'USD',
})

// Donate — donation completed
fbEvent({
  eventName: 'Donate',
  emails: ['[email protected]'],
  value: 25,
  currency: 'USD',
})

// Contact — initiated contact (support, sales, etc.)
fbEvent({ eventName: 'Contact', emails: ['[email protected]'] })

// PageView — usually auto-fired by FBPixelProvider. Call manually only for
// virtual page transitions your provider can't detect:
fbEvent({ eventName: 'PageView' })

Need a custom event? Pass any string for eventName — typed as EventName = StandardEventName | (string & {}).

How deduplication works

fbEvent() generates a single eventId, fires fbq('track', name, payload, { eventID }) on the client, waits a short moment (default 250 ms), then POSTs the same eventId to /api/fb-events. Meta collapses the two deliveries into one attributed event.

API reference

Client

| Symbol | Description | | --- | --- | | fbEvent(options) | Fire pixel + server event. Returns { eventId, serverResponse }. | | fbPageView() | Standard pixel PageView (client-only). |

Server

| Symbol | Description | | --- | --- | | createFbEventsRouteHandler(opts) | App Router. Returns { POST } for app/api/fb-events/route.ts. | | createFbEventsApiHandler(opts) | Pages Router. Default export for pages/api/fb-events.ts. | | signalsFromRequest, signalsFromNodeRequest | Pull IP, UA, _fbp, _fbc from a request. | | buildServerEvent | Build a ServerEvent from a flat payload — useful if you write your own handler. |

Both factory handlers accept every FacebookCapiClientOptions plus:

  • actionSource — default for action_source (default 'website')
  • apiVersion — Graph API version (default 'v22.0')
  • testEventCode — Meta Test Events tab code; removed in production
  • timeoutMs / retries — network tuning (defaults 10 s / 2 retries on 5xx)
  • transformEvent — last-chance mutator before sending
  • debug — echo the payload + Meta response in the HTTP response body

App events (action_source: 'app')

Pass appData on either the client fbEvent() call or the server ServerEvent:

fbEvent({
  eventName: 'Purchase',
  value: 9.99,
  currency: 'USD',
  appData: {
    advertiserTrackingEnabled: 1,           // iOS ATT consent
    applicationTrackingEnabled: 1,
    extinfo: ['i2', 'com.example.app', '1.0', '1', '17.0', 'iPhone15,2', 'en_US', 'PST', 'Verizon', 390, 844, 3, 6, 8, 128],
    vendorId: 'vid-...',
  },
})

Landing-page fbclid capture

When a user arrives from an ad without the _fbc cookie yet being set (e.g. no Pixel on the landing page), the server handler reconstructs fbc as fb.1.{nowMs}.{fbclid} from the request URL. No action required.

Components

| Symbol | Description | | --- | --- | | <FBPixelScript pixelId nonce? strategy? /> | Inline Meta Pixel init via next/script. | | <FBPixelProvider> | App Router — fires PageView on pathname/searchParams change. | | <FBPixelProviderPages> | Pages Router — fires PageView on routeChangeComplete. |

License

MIT © 2026 Actovision.

Free to use in commercial and open-source projects. The license text must be included in copies or substantial portions of the software.