# Attribute Stripe Checkout payments

> Pass the MetricRaven visitor ID into Stripe Checkout Session metadata so each payment links to its visit.

Source: https://metricraven.com/docs/stripe-checkout  
Markdown: https://metricraven.com/docs/stripe-checkout.md  
Section: Revenue

When your server creates a Checkout Session, copy the visitor ID into its metadata. Works for hosted and embedded Checkout, one-time and subscription mode.

First connect Stripe so payments are imported: see [Connect Stripe](https://metricraven.com/docs/stripe).

## Set it up

1. **Send the visitor ID with the checkout request**

   Read it in the browser and include it in the request to your own checkout endpoint:

   ```javascript title="Browser"
   // When the visitor clicks your checkout button.
   async function startCheckout(plan) {
     const response = await fetch("/api/checkout", {
       method: "POST",
       headers: { "Content-Type": "application/json" },
       body: JSON.stringify({ plan, visitorId: window.analytics?.getVisitorId() ?? null }),
     });
     const { url } = await response.json();
     window.location.assign(url);
   }
   ```

2. **Add metadata to the Checkout Session**

   Put the keys on the session and on the object Stripe creates from it: `payment_intent_data.metadata` for one-time payments, `subscription_data.metadata` for subscriptions. Then renewals carry the same attribution.

   ```javascript title="One-time payment (mode: payment)"
   // In your existing server-side checkout handler.
   // stripe is your initialized Stripe client; visitorId came from your browser.
   const attribution = {
     metricraven_visitor_id: visitorId || "",
     metricraven_user_id: authenticatedUser.id,
     metricraven_plan: "pro",
   };
   const session = await stripe.checkout.sessions.create({
     mode: "payment",
     line_items: [{ price: "YOUR_STRIPE_PRICE_ID", quantity: 1 }],
     success_url: "https://example.com/success",
     cancel_url: "https://example.com/pricing",
     metadata: attribution,
     payment_intent_data: { metadata: attribution },
   });
   ```

   ```javascript title="Subscription (mode: subscription)"
   // Subscription checkout uses subscription_data instead of payment_intent_data.
   const attribution = {
     metricraven_visitor_id: visitorId || "",
     metricraven_user_id: authenticatedUser.id,
     metricraven_plan: "pro_monthly",
   };
   const session = await stripe.checkout.sessions.create({
     mode: "subscription",
     line_items: [{ price: "YOUR_RECURRING_STRIPE_PRICE_ID", quantity: 1 }],
     success_url: "https://example.com/success",
     cancel_url: "https://example.com/pricing",
     metadata: attribution,
     subscription_data: { metadata: attribution },
   });
   ```

   For a guest checkout without an account, leave out `metricraven_user_id`.

3. **Identify signed-in users (recommended)**

   Calling [Identify](https://metricraven.com/docs/identify-users) when a user signs in links later payments to them by `metricraven_user_id`, even if the visitor ID was missing at checkout.

> **Verify it works**
>
> Make a live payment, wait for the next sync (or choose **Sync now** in **Settings → Integrations**), then find it in **Revenue**. Open **Visitors** for that day: the buyer's journey shows the payment after their visits.

## Metadata keys

| Metadata key | What it does |
| --- | --- |
| metricraven_visitor_id | The value of `window.analytics.getVisitorId()` in the buyer's browser. Links the payment to that visit and its traffic source. Anything that isn't a MetricRaven visitor ID is ignored. |
| metricraven_user_id | Your own user ID. If you call [Identify](https://metricraven.com/docs/identify-users) with the same ID, the payment joins that user's visits even without a visitor ID. |
| metricraven_plan | Optional plan name shown with the payment. Subscription invoices fall back to the price ID. |
| metricraven_renewal | Optional `"true"` for a repeat payment. Ignored for subscription invoices, where Stripe's billing reason decides. |

## Details

- Session metadata alone also works for one-time payments: MetricRaven looks the session up from the PaymentIntent when the PaymentIntent has no MetricRaven keys. Subscription renewals need `subscription_data.metadata`.
- `getVisitorId()` can return `null` before the tracker's first request finishes. Send `null` and rely on the user ID, or wait for the `analytics:visitor` event.
- Metadata is read when MetricRaven imports the charge, usually within a minute or two of the payment. Set it when you create the object; adding it after the import doesn't change that payment.
- Once one payment from a Stripe customer is linked, that customer's later payments (renewals, upgrades) are linked to the same visitor and user, and their earlier unlinked payments are filled in.
- MetricRaven does not read `client_reference_id`, the customer's email, custom checkout fields or UTM parameters on Stripe links. Only the metadata keys above link a payment to a visit.
- Only live-mode payments are imported. Test-mode payments never appear in MetricRaven.
