Polar revenue attribution

Pass XPmetric visitor IDs into Polar Checkout Session metadata for revenue-by-channel reporting.

Connect Polar in Settings → Integrations, then pass XPmetric visitor IDs into Checkout Session metadata.

Prerequisites

  1. Install p.js on your site.
  2. Connect Polar with an Organization Access Token in Settings → Integrations → Polar.
  3. Create checkout sessions via the Polar API — static Checkout Links cannot carry per-visitor metadata.

Metadata keys

Use the same keys as Stripe:

  • xpm_visitor_idwindow.xpmetric.v
  • xpm_session_idwindow.xpmetric.s

Server route (Next.js + @polar-sh/sdk):

// app/api/checkout/route.ts — create a Polar Checkout Session server-side
import { Polar } from "@polar-sh/sdk";
import { NextResponse } from "next/server";

const polar = new Polar({
  accessToken: process.env.POLAR_ACCESS_TOKEN!,
  // server: "sandbox", // uncomment for Polar sandbox
});

export async function POST(req: Request) {
  const { productId, xpm_visitor_id, xpm_session_id } = await req.json();

  const checkout = await polar.checkouts.create({
    products: [productId],
    metadata: {
      xpm_visitor_id: xpm_visitor_id || "",
      xpm_session_id: xpm_session_id || "",
    },
    successUrl: `${process.env.NEXT_PUBLIC_APP_URL}/thanks?checkout_id={CHECKOUT_ID}`,
  });

  return NextResponse.json({ url: checkout.url });
}

Client checkout call:

// Client — forward XPmetric visitor IDs when starting checkout
const visitorId = window.xpmetric?.v || "";
const sessionId = window.xpmetric?.s || "";

const res = await fetch("/api/checkout", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    productId: "YOUR_POLAR_PRODUCT_ID",
    xpm_visitor_id: visitorId,
    xpm_session_id: sessionId,
  }),
});

const { url } = await res.json();
window.location.href = url;

XPmetric sync reads these keys from order metadata after connect.

@polar-sh/nextjs

If you use the Next.js adapter, pass metadata as a URL-encoded JSON query param on your checkout handler route — see the Polar settings panel in XPmetric for the exact snippet.

Verify

Complete a sandbox or live checkout, then check the site dashboard revenue chart and Channels → Revenue view after sync.