REVENUE ATTRIBUTION
Stripe
Connect Stripe with a restricted API key — Attrifast sets up event delivery automatically — and pass the visitor ID into your Checkout Sessions so every payment is attributed to its channel.
Connecting Stripe lets Attrifast turn checkout.session.completed events into attributed orders: each payment is linked to the visitor who made it and the channel that brought them.
Requirements
- The tracker installed and receiving pageviews — attribution works forward from when tracking starts.
- A Pro subscription (Stripe connect is a Pro feature — there's a 7-day free trial).
- You create Stripe Checkout Sessions server-side (Checkout is how payments get linked to visitors — see below).
Step 1 — Connect your Stripe account
Create a restricted API key
In Stripe → Developers → API keys, create a restricted key with two permissions:
- Account information: Read — how Attrifast identifies your Stripe account
- Webhook Endpoints: Write — lets Attrifast set up event delivery for you
Leave everything else at its default and copy the rk_live_… value.
Paste it in onboarding
In Attrifast onboarding, step 3 "Attribute revenue (optional)", section "1. Connect Stripe", paste the key and click Connect. Connecting requires the website owner role.
What happens when you connect
Attrifast verifies the key, reads your account ID, and creates a webhook endpoint on your Stripe account (subscribed to checkout.session.completed) — you don't configure anything in the Stripe dashboard. You can see the endpoint under Stripe → Developers → Webhooks. Reconnecting replaces it and disconnecting removes it — if you've already rolled the key when you disconnect, the removal can't complete, so delete the endpoint manually in Stripe.
Your key is stored with the connection and is not used to read payment data. To revoke access, disconnect (DELETE /api/stripe/connect/:websiteId) and roll the key in Stripe.
Step 2 — Link payments to visitors
The Attrifast tracker keeps its visitor ID in localStorage under the key _rp_vid. To attribute a payment, pass that ID into the Checkout Session as client_reference_id — that's the only field you need:
On your payment page, read the visitor ID and send it to your server:
const visitorId = localStorage.getItem('_rp_vid');
// include visitorId in your create-checkout request
When creating the Checkout Session server-side:
const session = await stripe.checkout.sessions.create({
mode: 'payment', // or 'subscription'
client_reference_id: visitorId, // ← links the payment to the visitor
line_items: [ /* … */ ],
success_url: 'https://yoursite.com/thanks',
});
Payments without a client_reference_id (or with one that doesn't match a tracked visitor) still count toward revenue totals — they just can't be attributed to a channel.
What gets counted
| Stripe event | What Attrifast does |
|---|---|
checkout.session.completed | Creates an order (deduplicated per session), links it to the visitor via client_reference_id, attributes it using the 7-day last non-direct click model |
| Everything else | Not delivered to Attrifast — payments made outside Stripe Checkout aren't captured yet, and refunds/disputes are not subtracted, so revenue is gross |
Limitations
- Checkout only — payments that don't go through Stripe Checkout (raw PaymentIntents, invoices) aren't captured yet.
- Subscription renewals aren't captured — renewal charges don't carry the Checkout Session's fields, so today you'll see the first payment of a subscription, not recurring revenue. A subscription that starts with a free trial produces a $0 order at checkout.
- Matching is by visitor ID only. Attrifast deliberately doesn't guess by customer email.
- Not retroactive — payments made before connecting are not imported.
- One Stripe account connects to one Attrifast website (and vice versa).
- No currency conversion — amounts are summed as-is across currencies. If you charge in multiple currencies, revenue totals mix them.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
| "This key cannot read your Stripe account…" | The key is missing Account information: Read. Add it (or create a fresh key with both permissions) and retry. |
| "This key cannot create webhook endpoints…" | The key is missing Webhook Endpoints: Write. Add it and retry. |
| 403 "A subscription is required…" | Stripe connect is Pro-only — start the 7-day free trial and retry. |
| "Website not found or access denied" | Only the website owner can connect or disconnect Stripe — team members can't. |
| "Could not set up Stripe event delivery…" persists after retrying | Stripe caps accounts at 16 webhook endpoints. Delete unused endpoints under Stripe → Developers → Webhooks, then reconnect. |
| "This Stripe account is already connected to another site." | The account is attached to a different Attrifast website. Disconnect it there first, then reconnect. |
| Payments never appear at all | Check Stripe → Developers → Webhooks: the Attrifast endpoint should exist and show successful deliveries. If it's missing, reconnect; if deliveries fail, contact us. |
| Orders appear but show "Unknown visitor" / Direct | client_reference_id was missing or didn't match a tracked visitor. Confirm your payment page reads localStorage.getItem('_rp_vid') and your server passes it through. |
| An order shows Direct despite a known campaign click | The buyer's last non-Direct session was more than 7 days before payment — expected under the attribution model. Check the AI-influenced (30-day) figure for longer journeys. |