Skip to main content

Stripe Metadata

If you create Stripe Checkout Sessions via the API, you can pass the click_id in the Stripe metadata field using the key aff_click_id. Selgeo reads this metadata from Stripe webhooks and attributes the conversion to the referring partner.

API Version: v1

When to use this approach

Use Stripe metadata when:

  • You want to pass the click_id alongside your own client_reference_id value (which Checkout also supports, but metadata gives you more flexibility).
  • You create Checkout Sessions but want to use client_reference_id for your own purposes.
Direct Payment Intents and Subscriptions not supported

Selgeo processes metadata on checkout.session.completed and invoice.paid webhook events. If you create Payment Intents directly, their metadata is not available to Selgeo. If you create Subscriptions directly (without Checkout), Stripe stores the metadata at invoice.subscription_details.metadata, not invoice.metadata, so Selgeo cannot read the aff_click_id. Use the Conversion API instead, or create subscriptions via Stripe Checkout (which supports mode: 'subscription').

client_reference_id vs metadata

For Stripe Checkout Sessions, you can use either client_reference_id (simpler, covered in Stripe Checkout) or metadata.aff_click_id (covered here). Both work. If you already use client_reference_id for your own internal tracking, use metadata instead.

The flow

┌────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Browser │ │ Your Server │ │ Selgeo API │
│ │ │ │ │ │
│ 1. Snippet │ │ │ │ │
│ stores │ │ │ │ │
│ click_id │ │ │ │ │
│ │ │ │ │ │
│ 2. Frontend │─────>│ 3. Create Stripe │ │ │
│ sends │ │ object with │ │ │
│ clickId to │ │ metadata: │ │ │
│ backend │ │ aff_click_id │ │ │
│ │ │ │ │ │
│ │ │ │ │ 4. Stripe webhook │
│ │ │ │ │ fires → │
│ │ │ │ │ Selgeo reads │
│ │ │ │ │ aff_click_id │
│ │ │ │ │ from metadata │
│ │ │ │ │ → attributes │
│ │ │ │ │ conversion │
└────────────────┘ └──────────────────┘ └──────────────────┘

The metadata key

Selgeo looks for the click_id in Stripe metadata under the key:

aff_click_id

This key is checked on Checkout Session objects (via checkout.session.completed) and on Invoice objects (via invoice.paid).

Implementation

Step 1: Read the click ID on the frontend

const clickId = __selgeo.getClickId();

Step 2: Send it to your backend

Include the clickId in your API request body, form data, or however you pass data to your server:

const clickId = __selgeo.getClickId();

const response = await fetch('/api/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
planId: 'plan_pro',
clickId: clickId,
}),
});

Step 3: Pass it in Stripe metadata

Payment Intents

warning

Direct Payment Intents are not supported for Stripe metadata attribution. Selgeo only processes checkout.session.completed and invoice.paid webhook events. For custom payment flows that use Payment Intents directly, use the Conversion API to report conversions server-side.

Direct Subscriptions

warning

Setting metadata.aff_click_id on stripe.subscriptions.create() does not work. Stripe does not copy subscription metadata to invoice.metadata -- it stores it at invoice.subscription_details.metadata, which Selgeo does not currently read. For subscription billing, use Stripe Checkout with mode: 'subscription' (shown below), or report conversions via the Conversion API.

Checkout Sessions (metadata approach)

If you prefer to use metadata instead of client_reference_id on Checkout Sessions:

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',
// Use client_reference_id for your own tracking
client_reference_id: 'my_internal_ref_123',
// Use metadata for Selgeo attribution
metadata: {
aff_click_id: clickId || '',
},
});

res.json({ url: session.url });
});

How Selgeo processes metadata

For checkout.session.completed events, Selgeo checks for the click_id in this order:

  1. client_reference_id on the Checkout Session (if present and is a valid UUID).
  2. metadata.aff_click_id on the Checkout Session.

If both are present, client_reference_id takes priority. This means you can safely set both without conflict -- Selgeo will use whichever it finds first.

For invoice.paid events (initial invoices without a preceding Checkout Session), Selgeo checks metadata.aff_click_id and metadata.aff_promo_code directly on the invoice object.

Recurring subscriptions

For subscriptions created via Checkout (mode: 'subscription'), you only need to pass aff_click_id when creating the Checkout Session. Selgeo attributes the initial conversion from the checkout.session.completed event and automatically attributes subsequent invoice payments (renewals) to the same partner by matching the Stripe Customer ID. You do not need to pass the click_id again on renewals.

Empty values

If the visitor was not referred by a partner (clickId is null), you can either:

  • Omit the key entirely -- do not include aff_click_id in metadata.
  • Pass an empty string -- aff_click_id: ''. Selgeo ignores empty strings.

Both approaches are safe. The Stripe object is created normally, and Selgeo treats it as a non-referred conversion.

Testing

  1. Create a tracking link and a test partner in the Selgeo dashboard.
  2. Visit your site via the tracking link to register a click.
  3. Trigger your payment flow -- the click_id should be passed to your backend and included in Stripe metadata as aff_click_id.
  4. Complete the payment using Stripe test card 4242 4242 4242 4242.
  5. Check the Selgeo dashboard -- verify the conversion appears and is attributed to the test partner.

Verifying metadata in Stripe

You can confirm the metadata was set correctly in the Stripe Dashboard:

  1. Find the Checkout Session.
  2. Scroll down to the Metadata section.
  3. Verify aff_click_id contains the expected UUID.

Comparison of attribution methods

MethodStripe objectKeyBest for
client_reference_idCheckout Session onlyclient_reference_idSimple Checkout integrations
metadata.aff_click_idCheckout Sessionmetadata.aff_click_idWhen client_reference_id is already used for other purposes
Payment Link auto-rewritePayment Link URLclient_reference_id (query param)Zero-backend Stripe Payment Links

Next steps