Skip to main content

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

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 });
});
Pass undefined, not an empty string

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:

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 sessionStorage was 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

  1. Create a tracking link and a test partner in the Selgeo dashboard.
  2. Visit your site via the tracking link: https://your-site.com/?ref=YOUR_TEST_REF
  3. Verify the click ID in the browser console:
    __selgeo.getClickId() // Should return a UUID
  4. Trigger your checkout flow. The click_id should be passed to your backend.
  5. Complete the payment using Stripe test card 4242 4242 4242 4242.
  6. Check the Selgeo dashboard -- the conversion should appear attributed to the test partner.
FeaturePayment LinksCheckout Sessions
Backend code requiredNoYes (create session)
Frontend code requiredNoYes (read click_id)
Supports subscriptionsYesYes
Supports one-time paymentsYesYes
Supports embedded checkoutNoYes
Custom checkout flowNoYes

If you only need a simple buy button and do not customize the checkout flow, Stripe Payment Links is the simpler option.

Next steps