Stripe Checkout

Set up revenue attribution with Stripe Checkout sessions.

Stripe Checkout

Stripe Checkout is the most common way to accept payments with Stripe. This guide shows how to pass EngageTrack visitor and session IDs through checkout session metadata so that revenue is attributed to the correct traffic source.

How It Works

  1. A visitor lands on your site and the EngageTrack SDK generates a visitor ID and session ID (stored in browser storage, accessible via the SDK's JavaScript API)
  2. When the visitor clicks "Buy", your client-side code reads these IDs and sends them to your server, which includes them in the metadata field of stripe.checkout.sessions.create()
  3. After payment, Stripe sends a checkout.session.completed webhook to EngageTrack
  4. EngageTrack reads the metadata from the webhook and attributes the revenue to the visitor's traffic source

Step 1: Pass Visitor & Session IDs to Your Server

Node.js / Express

import Stripe from "stripe";
 
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
 
app.post("/create-checkout", async (req, res) => {
	// Receive visitor/session IDs from the client request body
	const { engagetrack_visitor_id, engagetrack_session_id } = req.body;
 
	const session = await stripe.checkout.sessions.create({
		mode: "payment",
		line_items: [
			{
				price: "price_xxxxxxxxxxxxx",
				quantity: 1,
			},
		],
		metadata: {
			engagetrack_visitor_id: engagetrack_visitor_id || "",
			engagetrack_session_id: engagetrack_session_id || "",
		},
		success_url: "https://yoursite.com/success",
		cancel_url: "https://yoursite.com/cancel",
	});
 
	res.json({ url: session.url });
});

Next.js App Router (Route Handler)

import { NextRequest, NextResponse } from "next/server";
import Stripe from "stripe";
 
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
 
export async function POST(request: NextRequest) {
	// Receive visitor/session IDs from the client request body
	const { price_id, engagetrack_visitor_id, engagetrack_session_id } =
		await request.json();
 
	const session = await stripe.checkout.sessions.create({
		mode: "payment",
		line_items: [
			{
				price: price_id,
				quantity: 1,
			},
		],
		metadata: {
			engagetrack_visitor_id: engagetrack_visitor_id ?? "",
			engagetrack_session_id: engagetrack_session_id ?? "",
		},
		success_url: "https://yoursite.com/success",
		cancel_url: "https://yoursite.com/cancel",
	});
 
	return NextResponse.json({ url: session.url });
}

Next.js Pages Router (API Route)

import type { NextApiRequest, NextApiResponse } from "next";
import Stripe from "stripe";
 
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
 
export default async function handler(
	req: NextApiRequest,
	res: NextApiResponse,
) {
	// Receive visitor/session IDs from the client request body
	const { engagetrack_visitor_id, engagetrack_session_id } = req.body;
 
	const session = await stripe.checkout.sessions.create({
		mode: "payment",
		line_items: [
			{
				price: "price_xxxxxxxxxxxxx",
				quantity: 1,
			},
		],
		metadata: {
			engagetrack_visitor_id: engagetrack_visitor_id ?? "",
			engagetrack_session_id: engagetrack_session_id ?? "",
		},
		success_url: "https://yoursite.com/success",
		cancel_url: "https://yoursite.com/cancel",
	});
 
	res.json({ url: session.url });
}

Client-Side: Read and Send the IDs

On the client, read the IDs from the SDK and include them when calling your checkout endpoint:

const visitorId = window.engagetrack?.getVisitorId() || "";
const sessionId = window.engagetrack?.getSessionId() || "";
 
const response = await fetch("/create-checkout", {
	method: "POST",
	headers: { "Content-Type": "application/json" },
	body: JSON.stringify({
		price_id: "price_xxxxxxxxxxxxx",
		engagetrack_visitor_id: visitorId,
		engagetrack_session_id: sessionId,
	}),
});
 
const { url } = await response.json();
window.location.href = url;

The metadata keys must be exactly engagetrack_visitor_id and engagetrack_session_id. EngageTrack will not recognize other key names.

Step 2: Set Up the Webhook in Stripe

Add the EngageTrack webhook URL to your Stripe dashboard:

  1. Go to Stripe Dashboard → Developers → Webhooks
  2. Click Add endpoint
  3. Enter the webhook URL:
https://api.engagetrack.net/api/v1/webhooks/revenue/stripe/{YOUR_SITE_PUBLIC_ID}
  1. Under Events to send, select:
    • checkout.session.completed
    • invoice.payment_succeeded (for subscriptions)
    • charge.refunded (to track refunds)
  2. Click Add endpoint

Replace {YOUR_SITE_PUBLIC_ID} with your site's public ID, found in Site Settings → General.

Make sure you are adding the webhook to the correct Stripe mode (live vs test). For testing, add the webhook to your test mode dashboard.

Step 3: Test with Stripe CLI

Use the Stripe CLI to forward webhooks to EngageTrack during development:

# Install Stripe CLI (macOS)
brew install stripe/stripe-cli/stripe
 
# Login to your Stripe account
stripe login
 
# Forward webhooks to EngageTrack
stripe listen --forward-to https://api.engagetrack.net/api/v1/webhooks/revenue/stripe/{YOUR_SITE_PUBLIC_ID}

Then trigger a test event:

stripe trigger checkout.session.completed \
  --add checkout_session:metadata[engagetrack_visitor_id]=test_visitor_123 \
  --add checkout_session:metadata[engagetrack_session_id]=test_session_456

Subscriptions

For subscription checkouts, the same approach works. Use mode: "subscription" and EngageTrack will track both the initial payment and recurring invoices:

const session = await stripe.checkout.sessions.create({
	mode: "subscription",
	line_items: [
		{
			price: "price_xxxxxxxxxxxxx", // recurring price
			quantity: 1,
		},
	],
	metadata: {
		engagetrack_visitor_id: visitorId,
		engagetrack_session_id: sessionId,
	},
	subscription_data: {
		metadata: {
			engagetrack_visitor_id: visitorId,
			engagetrack_session_id: sessionId,
		},
	},
	success_url: "https://yoursite.com/success",
	cancel_url: "https://yoursite.com/cancel",
});

Pass the metadata in both the top-level metadata and subscription_data.metadata. The top-level metadata is used for the initial checkout event, while the subscription metadata is carried forward to all future invoice events.

Verify

After completing the setup:

  1. Open your site in a browser and visit a page with the EngageTrack SDK installed
  2. Check that visitor and session IDs are available by running window.engagetrack.getVisitorId() in the browser console
  3. Complete a test purchase using Stripe test card 4242 4242 4242 4242
  4. Go to your EngageTrack dashboard → Revenue tab
  5. You should see the test payment appear within a few seconds, attributed to the traffic source of your visit

If the payment does not appear, check:

  • The webhook URL is correct and uses your site's public ID
  • The webhook is receiving events (Stripe Dashboard → Webhooks → select endpoint → view recent deliveries)
  • The metadata keys are spelled correctly (engagetrack_visitor_id, not engagetrackVisitorId)