By default, Partnero uses customer-based attribution — a customer is permanently linked to one partner, and all their transactions generate commissions for that partner.
Transaction-based attribution changes this. Instead of looking at who the customer belongs to, Partnero looks for a partner_key in the payment metadata to decide which partner should receive the commission. This means the same customer can generate commissions for different partners on different transactions.
When to use this
- A marketplace where the same buyer purchases from different sellers, each represented by a different partner
- A SaaS platform where customers can be upsold by different agencies, and each agency should earn commission on the deals they close
- A business where the referring partner is tracked at the payment level (e.g., stored in Stripe charge metadata) rather than at the customer level
Setting up
- Go to Program Settings → Edit program
- Find Commission attribution model
- Select Transaction-based
- Save
This setting only affects how new incoming transactions are attributed. Existing customers and commissions are not modified.
How it works
When a payment webhook arrives (or an API call is made), Partnero checks for a partner_key field in the payment metadata before any other customer lookup.
- Read
partner_key from payment metadata
- Find the partner matching that key
- Find or create a customer record linked to that specific partner
- Calculate commission for that partner
If no partner_key is found, Partnero falls back to the standard customer-based attribution logic.
Customer records
To support the same real-world customer being linked to multiple partners, Partnero creates separate customer records with a composite identifier:
{customer_id}__pkey_{partner_identifier}
For example, Stripe customer cus_123 attributed to partner PARTNER_A becomes stripe_cus_123__pkey_PARTNER_A. This happens automatically — no action required on your part.
Examples
Imagine Stripe customer cus_123 making three separate purchases over time.
Partner key is present
| Charge | partner_key in metadata | Result |
|---|
| First charge | PARTNER_A | New customer created, linked to Partner A. Commission → Partner A |
| Second charge | PARTNER_B | Separate customer record created for Partner B. Commission → Partner B |
| Third charge | PARTNER_A | Existing customer record found. Commission → Partner A (no new record) |
Each partner gets commission only for the transactions that carry their key. The same Stripe customer generated commissions for two different partners.
No partner key or invalid key
| Charge | partner_key in metadata | Result |
|---|
| Charge with no key | (empty) | Falls back to standard customer-based attribution. If the customer is already linked to a partner, that partner gets the commission. |
| Charge with invalid key | INVALID_KEY | Partner not found. Falls back to standard customer-based attribution. |
Transaction-based attribution is additive — it only changes behavior when a valid partner_key is present. All existing attribution methods (referral links, promotion codes, customer matching) continue to work as a fallback.
Integration guides
Stripe
Add partner_key to the metadata of charges, subscriptions, invoices, or the Stripe customer object. Partnero checks all of these locations.
Checkout Session:
const session = await stripe.checkout.sessions.create({
line_items: [{ price: 'price_xxx', quantity: 1 }],
mode: 'payment',
success_url: 'https://yoursite.com/success',
cancel_url: 'https://yoursite.com/cancel',
metadata: {
partner_key: 'PARTNER_A'
}
});
Subscription:
const subscription = await stripe.subscriptions.create({
customer: 'cus_123',
items: [{ price: 'price_xxx' }],
metadata: {
partner_key: 'PARTNER_A'
}
});
One-time charge:
const charge = await stripe.charges.create({
amount: 9999,
currency: 'usd',
customer: 'cus_123',
metadata: {
partner_key: 'PARTNER_A'
}
});
Stripe customer metadata (applies to all future charges for this customer unless overridden per charge):
await stripe.customers.update('cus_123', {
metadata: {
partner_key: 'PARTNER_A'
}
});
Partnero checks metadata in this order: charge/invoice metadata → subscription metadata → Stripe customer metadata. A partner_key on a specific charge overrides one set on the customer.
Paddle
Add partner_key to the custom_data object on transactions or subscriptions.
Paddle.Checkout.open({
items: [{ priceId: 'pri_xxx', quantity: 1 }],
customData: {
partner_key: 'PARTNER_A'
}
});
Or server-side:
curl https://api.paddle.com/transactions \
-H "Authorization: Bearer YOUR_PADDLE_KEY" \
-d '{
"items": [{"price_id": "pri_xxx", "quantity": 1}],
"custom_data": {
"partner_key": "PARTNER_A"
}
}'
WooCommerce
Add partner_key to the order meta data. This can be done via a plugin, custom code, or the WooCommerce REST API.
curl https://yourstore.com/wp-json/wc/v3/orders \
-u consumer_key:consumer_secret \
-d '{
"meta_data": [
{
"key": "partner_key",
"value": "PARTNER_A"
}
]
}'
Chargebee
Partnero reads the partner key from the Chargebee customer custom fields cf_partnero_partner or cf_referral_code. Set these fields on the customer in Chargebee, and Partnero will use them for per-transaction attribution when transaction-based mode is enabled.
API
When using the Partnero API directly, include the partner field in your transaction request. The customer is automatically created and linked to that partner.
curl https://api.partnero.com/v1/transactions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"partner": {
"key": "PARTNER_A"
},
"customer": {
"key": "customer_123",
"email": "[email protected]"
},
"key": "invoice_789",
"amount": 99.99,
"action": "sale"
}'
With transaction-based attribution via the API, you don’t need to create the customer separately — it’s created automatically when the transaction is recorded.
Where partner_key is read from
| Integration | Metadata location |
|---|
| Stripe | Charge metadata → invoice/subscription metadata → Stripe customer metadata |
| Paddle | Transaction or subscription custom_data |
| WooCommerce | Order meta_data |
| Chargebee | Customer fields cf_partnero_partner or cf_referral_code |
| API | partner field in request body |
Next steps