Stripe Billing
If you bill your customers through Stripe, you can wire up OpenPartner attribution without
emitting op.event() calls from your app. OpenPartner listens to your Stripe webhooks and
maps customer.subscription.created / invoice.paid events into the attribution pipeline
automatically.
What you’ll need
- A Stripe account (the same one you use for billing customers)
- The OpenPartner browser SDK already initialized on your marketing pages
- Access to your Stripe Dashboard to add a webhook endpoint
1. Add the webhook endpoint in Stripe
In your Stripe Dashboard → Developers → Webhooks → Add endpoint.
- Endpoint URL:
https://api.your-openpartner-host.com/webhooks/stripe(for the OpenPartner-hosted version:https://api.openpartner.dev/webhooks/stripe) - Events to send:
checkout.session.completedcustomer.subscription.createdinvoice.paid
Copy the Signing secret Stripe shows you and set it as STRIPE_WEBHOOK_SECRET in your
OpenPartner environment.
2. Pass the referral on Stripe Checkout
In your checkout-session creation code, set client_reference_id to the visitor’s referral
token. The OpenPartner browser SDK exposes it as op.getReferral():
import { OpenPartner } from '@openpartner/sdk';
const op = OpenPartner.init({ apiUrl: 'https://api.openpartner.dev' });
// When the user clicks "Subscribe":const session = await fetch('/api/create-checkout-session', { method: 'POST', body: JSON.stringify({ referral: op.getReferral(), }),});Then on your server, drop it into the Stripe Checkout session:
const session = await stripe.checkout.sessions.create({ mode: 'subscription', line_items: [{ price: 'price_xxx', quantity: 1 }], client_reference_id: req.body.referral ?? undefined, success_url: 'https://yourapp.com/welcome', cancel_url: 'https://yourapp.com/pricing',});That’s it. No op.identify() call needed for Stripe-billed customers — the
client_reference_id rides through Stripe to our webhook, and we stitch the attribution
on checkout.session.completed.
What happens under the hood
- A visitor clicks
yoursite.com/?cref=PARTNER_REF. The OpenPartner SDK captures the ref and stashes it in localStorage. - The visitor completes a Stripe Checkout. Your server passes
client_reference_id: op.getReferral()to Stripe. - Stripe fires
checkout.session.completedto OpenPartner with theclient_reference_idand the new Stripe customer ID attached. - OpenPartner stitches an Identity row linking the click to the Stripe customer, then emits
a
signupEvent. Attribution runs automatically. - Every subsequent
invoice.paidfrom Stripe is mapped to a revenue event for the same customer and attributed to the same partner — for the lifetime of the subscription.
When to use the SDK path instead
The Stripe Billing flow only covers events Stripe knows about: subscription creation,
recurring invoices, and Checkout sessions. If you want to track non-Stripe events
(demo_booked, trial_started, custom milestones), or you bill through Paddle / Chargebee /
Lemon Squeezy / your own server, use the SDK event API:
op.event('demo_booked', { dealValue: 5000 });The two paths coexist — you can use Stripe Billing for revenue events and the SDK for custom milestones.
Troubleshooting
Conversions aren’t attributing.
- Check Stripe Dashboard → Webhooks → your endpoint → Recent deliveries. You should see
checkout.session.completedevents with 200 responses. - Verify the
client_reference_idis present on the Checkout session. If it’s empty, the visitor either didn’t arrive via a partner link or the SDK didn’t initialize before checkout creation.
Multiple signup events for the same customer.
- If you have both
customer.createdandcheckout.session.completedconfigured AND you setopenpartner_user_idin customer metadata yourself, you’ll get two signup events. Pick one path — for the Stripe Billing flow, justcheckout.session.completedis enough.
invoice.paid events aren’t attributing.
- The first
invoice.paidin a subscription usually arrives within seconds ofcheckout.session.completed. If the order is reversed, OpenPartner falls back to a database-side Identity lookup so attribution still works — but if it persists, check that the customer’s metadata was successfully backfilled (Stripe Dashboard → Customer → Metadata should showopenpartner_user_id).