# Stripe end to end (https://www.getfounderhq.com/docs/analytics/recipes/stripe-end-to-end)

Go from no Stripe connection to a payment that shows the channel that
brought the buyer. About 20 minutes, once.

<Callout title="Before you start">
  You need a FounderHQ brand with the [web SDK](/analytics/sdks/web) installed
  on your pricing page, and a Stripe account you can open the dashboard for. New
  to the SDK? Start with [Quickstart: Web
  (snippet)](/analytics/getting-started/quickstart-web-snippet).
</Callout>

Revenue attribution needs two halves, and one half alone tells you nothing:

1. **The Stripe connection** tells FounderHQ that you were paid.
2. **The checkout metadata** tells FounderHQ who to thank.

Do them in that order.

## 1. Connect Stripe

Follow [Connect Stripe](/analytics/revenue/connect-stripe). In short, you:

- Open **Settings → Integrations → Revenue** and choose your brand.
- Choose Stripe for the brand.
- Leave **Connect with Stripe** selected and approve access on Stripe's page.
  Your revenue appears in seconds.

Prefer not to authorize FounderHQ? Paste a read-only key instead. Your revenue
appears within a few minutes, and the first connection can see about the last
30 days. The manual webhook option remains available on the same screen.

Keep the environments matched. Test and live revenue use separate
connections.

## 2. Pick the path that matches your checkout

Now carry the visitor's IDs into the payment. How you do that depends on
how you charge. Pick one row, and follow that page.

| Which Stripe setup do you have?                              | You will                                                              | Page                                                                             |
| ------------------------------------------------------------ | --------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| Buyers click a Stripe-hosted Payment Link or a Pricing Table | Put a minted token in `client_reference_id`                           | [Stripe Payment Links](/analytics/revenue/connect-stripe/payment-links)          |
| Your server creates Checkout Sessions                        | Put metadata on the session, and on the subscription or PaymentIntent | [Stripe Checkout API](/analytics/revenue/connect-stripe/checkout-api)            |
| You built your own payment form on PaymentIntents            | Put metadata on the PaymentIntent                                     | [Stripe PaymentIntent API](/analytics/revenue/connect-stripe/payment-intent-api) |

Not sure which one you have? Look at what the buyer sees. A checkout page
on `stripe.com` or `buy.stripe.com` is the first row. Your own card form
is the third row. Anything else your server creates is the second row.

Two paths in one product, for example a Payment Link for a lifetime deal
and Checkout Sessions for plans? Follow both pages. They do not conflict.

## 3. Keep renewals attributed

A Checkout Session describes one purchase. Its metadata does not travel to
next year's renewal.

Put the same metadata on the object that renews as well: the subscription
for subscriptions, the PaymentIntent for one-time payments. FounderHQ also
binds the Stripe customer and subscription on the first payment, so a
renewal with no metadata still resolves to the same contact.

FounderHQ works out a renewal's channel from the contact's touches at the
time of the renewal, then freezes it. Nothing later rewrites a payment.
See [checkout metadata and payment links](/analytics/revenue/checkout-metadata-and-payment-links).

## Verify

1. In FounderHQ, open **Settings → Integrations → Revenue**. The Stripe
   connection shows **Connected**.
2. Open your pricing page in a browser, and start a checkout.
3. In Stripe, open the object you created. It shows `fhq_anonymous_id` and
   `fhq_session_id`, or the link URL carries `client_reference_id`.
4. Pay with a Stripe test card, on a test connection.
5. In FounderHQ, open Revenue. The payment shows the channel that brought
   the buyer, under **Introduced by** and **Closed by**.

If you chose the manual webhook, Stripe shows a `200` response for the
delivery. That is the signal FounderHQ accepted the event.

## Troubleshoot

### The payment arrives, but with no channel

The Stripe connection works and the metadata half does not. Open the Stripe
object and look for the two IDs. Empty IDs mean the visitor denied consent, or
the buyer never loaded a page that runs the SDK.

### The payment does not arrive at all

Open **Settings → Integrations → Revenue**, then open the Stripe connection.
Reconnect Stripe if access was revoked, choose **Sync now** for a read-only
key, or inspect the delivery response for a manual webhook. The messages and
what each one means are on [Connect Stripe](/analytics/revenue/connect-stripe).

### Payments do not show up

FounderHQ records live payments. Make sure your key or webhook endpoint is a
live one — Stripe test-mode activity is not tracked.
