Next.js revenue attribution

Step-by-step guide for attributing revenue in Next.js applications.

Back to revenue attribution

1. Install the pixel

Add the attribu.tech tracking script to your root layout. If you've already done this, skip to step 2.

// app/layout.tsx
import Script from "next/script";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>{children}</body>
      <Script
        defer
        data-website-id="YOUR_SITE_ID"
        data-domain="yourdomain.com"
        src="https://attribu.tech/js/script.js"
        strategy="afterInteractive"
      />
    </html>
  );
}

See the full Next.js installation guide for Pages Router setup and advanced options.

2. Connect Stripe

Go to Settings > Revenue in your attribu.tech dashboard and paste your Stripe restricted API key. This lets attribu.tech read charges and link them to visitors.

See Connect Stripe for detailed instructions on creating a restricted key.

3. Pass cookies in checkout

This is the key step. When creating a Stripe Checkout Session on the server, read the attribu.tech cookies and pass them as metadata:

// app/api/checkout/route.ts
import { cookies } from "next/headers";
import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

export async function POST(req: Request) {
  const { priceId } = await req.json();
  const cookieStore = await cookies();

  const session = await stripe.checkout.sessions.create({
    mode: "payment", // or "subscription"
    line_items: [{ price: priceId, quantity: 1 }],
    success_url: `${process.env.NEXT_PUBLIC_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing`,
    metadata: {
      attribu_visitor_id: cookieStore.get("attribu_visitor_id")?.value || "",
      attribu_session_id: cookieStore.get("attribu_session_id")?.value || "",
    },
  });

  return Response.json({ url: session.url });
}
The metadata field must be on the Checkout Session itself, not on the line item or product. attribu.tech reads session-level metadata from the Stripe webhook.

4. Next.js 15+ note

In Next.js 15 and later, cookies() is asynchronous and must be awaited. The example above already uses await cookies(). If you're on Next.js 14, you can remove the await:

// Next.js 14 (synchronous cookies)
const cookieStore = cookies();
That's it. Once a payment goes through, the charge appears in your attribu.tech dashboard attributed to the traffic source that brought the visitor. No email matching or identity resolution needed.

What's next

Copied