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
- Install p.js on your site.
- Connect Polar with an Organization Access Token in Settings → Integrations → Polar.
- 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_id←window.xpmetric.vxpm_session_id←window.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.