Stripe Checkout
If you create Stripe Checkout Sessions on your server, you need to pass the click_id from the browser to your backend and include it as client_reference_id when creating the session. Selgeo reads this value from the Stripe webhook and attributes the conversion to the referring partner.
API Version: v1
Prerequisites
- The Selgeo snippet is installed on your website (Snippet Setup)
- You create Stripe Checkout Sessions on your backend
- Your Stripe account is connected to Selgeo in the dashboard (Settings > Stripe)
How it works
┌────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Browser │ │ Your Server │ │ Selgeo API │
│ │ │ │ │ │
│ 1. Visitor │ │ │ │ │
│ arrives via │ │ │ │ │
│ ?ref=abc123 │ │ │ │ │
│ │ │ │ │ │
│ 2. Snippet │─────>│ │─────>│ Registers click │
│ registers │ │ │ │ Returns click_id │
│ click │<─────│ │<─────│ │
│ │ │ │ │ │
│ 3. User clicks │─────>│ 4. Create │ │ │
│ "Subscribe" │ │ Checkout │ │ │
│ (sends │ │ Session with │ │ │
│ clickId) │ │ client_ref_id │ │ │
│ │ │ │ │ │
│ 5. Redirect to │<─────│ │ │ │
│ Stripe │ │ │ │ │
│ Checkout │ │ │ │ │
│ │ │ │ │ │
│ 6. Customer │ │ │ │ │
│ pays │ │ │ │ │
│ │ │ │ │ │
│ │ │ │ │ 7. Stripe webhook │
│ │ │ │ │ includes │
│ │ │ │ │ client_ref_id │
│ │ │ │ │ → Selgeo │
│ │ │ │ │ attributes │
└────────────────┘ └──────────────────┘ └──────────────────┘
Implementation
Step 1: Read the click ID on the frontend
After the snippet has loaded and captured a referral click, the click_id is available via:
const clickId = __selgeo.getClickId();
This returns a UUID string (e.g., "f47ac10b-58cc-4372-a567-0e02b2c3d479") or null if no referral click was recorded.
Step 2: Send the click ID to your backend
Include the click_id when your frontend requests a Checkout Session from your server:
const clickId = __selgeo.getClickId();
const response = await fetch('/api/create-checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
priceId: 'price_xxx',
clickId: clickId,
}),
});
const { url } = await response.json();
window.location.href = url;
Step 3: Pass it as client_reference_id when creating the Checkout Session
- JavaScript (Node.js)
- Python
- PHP
const stripe = require('stripe')('sk_test_YOUR_STRIPE_KEY');
app.post('/api/create-checkout', async (req, res) => {
const { priceId, clickId } = req.body;
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{ price: priceId, quantity: 1 }],
success_url: 'https://your-site.com/success',
cancel_url: 'https://your-site.com/cancel',
// Pass the click_id so Selgeo can attribute this conversion
client_reference_id: clickId || undefined,
});
res.json({ url: session.url });
});
import stripe
stripe.api_key = "sk_test_YOUR_STRIPE_KEY"
@app.route("/api/create-checkout", methods=["POST"])
def create_checkout():
data = request.get_json()
price_id = data["priceId"]
click_id = data.get("clickId")
session = stripe.checkout.Session.create(
mode="subscription",
line_items=[{"price": price_id, "quantity": 1}],
success_url="https://your-site.com/success",
cancel_url="https://your-site.com/cancel",
# Pass the click_id so Selgeo can attribute this conversion
client_reference_id=click_id if click_id else None,
)
return jsonify({"url": session.url})
$stripe = new \Stripe\StripeClient('sk_test_YOUR_STRIPE_KEY');
$data = json_decode(file_get_contents('php://input'), true);
$priceId = $data['priceId'];
$clickId = $data['clickId'] ?? null;
$session = $stripe->checkout->sessions->create([
'mode' => 'subscription',
'line_items' => [['price' => $priceId, 'quantity' => 1]],
'success_url' => 'https://your-site.com/success',
'cancel_url' => 'https://your-site.com/cancel',
// Pass the click_id so Selgeo can attribute this conversion
'client_reference_id' => $clickId,
]);
echo json_encode(['url' => $session->url]);
If there is no click_id (the visitor was not referred by a partner), pass undefined (JavaScript), None (Python), or null (PHP) for client_reference_id. Do not pass an empty string -- Stripe will store it as the literal value "", which Selgeo cannot match to a click.
Embedded Checkout
If you use Stripe Embedded Checkout instead of redirect-based Checkout, the flow is the same. You still create a Checkout Session on your server with client_reference_id and pass the client_secret to the frontend:
- JavaScript (Node.js)
app.post('/api/create-checkout', async (req, res) => {
const { priceId, clickId } = req.body;
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{ price: priceId, quantity: 1 }],
ui_mode: 'embedded',
return_url: 'https://your-site.com/success?session_id={CHECKOUT_SESSION_ID}',
// Same as redirect Checkout -- pass the click_id here
client_reference_id: clickId || undefined,
});
res.json({ clientSecret: session.client_secret });
});
Selgeo reads client_reference_id from the Stripe webhook regardless of whether you use redirect or embedded Checkout.
Handling the null case
When __selgeo.getClickId() returns null, it means one of:
- The visitor did not arrive via a partner referral link.
- The visitor's
sessionStoragewas cleared (e.g., they closed and reopened the tab). - The snippet has not loaded yet (e.g., async loading is still in progress).
In all cases, you should still create the Checkout Session normally -- just omit client_reference_id. The conversion will proceed as a non-referred sale:
const clickId = __selgeo.getClickId();
// Always create the checkout, regardless of whether clickId exists
const response = await fetch('/api/create-checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
priceId: 'price_xxx',
clickId: clickId, // null is fine -- your backend should handle it
}),
});
Testing
- Create a tracking link and a test partner in the Selgeo dashboard.
- Visit your site via the tracking link:
https://your-site.com/?ref=YOUR_TEST_REF - Verify the click ID in the browser console:
__selgeo.getClickId() // Should return a UUID
- Trigger your checkout flow. The
click_idshould be passed to your backend. - Complete the payment using Stripe test card
4242 4242 4242 4242. - Check the Selgeo dashboard -- the conversion should appear attributed to the test partner.
Comparison with Payment Links
| Feature | Payment Links | Checkout Sessions |
|---|---|---|
| Backend code required | No | Yes (create session) |
| Frontend code required | No | Yes (read click_id) |
| Supports subscriptions | Yes | Yes |
| Supports one-time payments | Yes | Yes |
| Supports embedded checkout | No | Yes |
| Custom checkout flow | No | Yes |
If you only need a simple buy button and do not customize the checkout flow, Stripe Payment Links is the simpler option.
Next steps
- Stripe Metadata -- use Checkout Session metadata instead of
client_reference_id - Conversion API -- for non-Stripe conversions
- Test Mode -- detailed guide for testing