Signals Docs
Installation

Next.js

The @pixelfox/next package for App Router projects.

Install

npm install @pixelfox/next
# or: bun add @pixelfox/next

Add the script (App Router)

Drop SignalsScript into your root layout - it renders a next/script tag with afterInteractive strategy:

// app/layout.tsx
import { SignalsScript } from "@pixelfox/next";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <SignalsScript
          apiKey={process.env.NEXT_PUBLIC_SIGNALS_KEY!}
          host={process.env.NEXT_PUBLIC_SIGNALS_HOST}
        />
      </body>
    </html>
  );
}

Client-side navigations are tracked automatically - the SDK wraps the History API, so App Router route changes produce $pageview events without any extra code.

Track from components

Use the useSignals hook in client components. Calls made before the tag loads are safely dropped (the hook is a no-op until window.signals exists):

"use client";
import { useSignals } from "@pixelfox/next";

export function BuyButton({ productId, price }: { productId: string; price: number }) {
  const { track } = useSignals();
  return (
    <button
      onClick={() =>
        track("product_added_to_cart", {
          product_id: productId,
          price,
          currency: "USD",
        })
      }
    >
      Add to cart
    </button>
  );
}

Identify the customer at login/checkout so anonymous history gets stitched:

const { identify } = useSignals();
identify(user.id, { email: user.email });

Provider variant

If you prefer context over a layout-level script, wrap your app in SignalsProvider - it injects the script itself and provides the same API via context:

<SignalsProvider apiKey={process.env.NEXT_PUBLIC_SIGNALS_KEY!}>
  {children}
</SignalsProvider>

Gotchas

  • The API key is public by design (it identifies, not authenticates, your site) - the backend enforces your allowed origins list from Settings.
  • track/identify are client-side only. For ad-blocker-proof purchase tracking, POST to /v1/ingest from a Route Handler or server action - see the ingest API reference.

On this page