# Stripe Webhook / API Revenue Attribution Recipe

Stitch subscription and payment events with marketing campaigns using Stripe metadata and webhook listener configurations.

Beta — test mode. Stripe revenue ingestion is a webhook adapter you configure yourself, not a native Stripe app, and it is still test-mode beta. Stripe test-mode events are ignored by design, so confirm the conversions land with a real low-value live purchase (then refund it).

## Who This Is For

This recipe is for developers and founders running SaaS or subscription-based sites on Stripe who want to link user checkouts, paid subscriptions, and order amounts back to marketing channels (like Google Ads clicks or organic referrers).

**Key Terms Defined:**

- **Webhook** — a server-to-server HTTP message sent by Stripe to SourceTrack whenever a billing event occurs.
- **Signing secret** — the value Stripe shows for your webhook endpoint; SourceTrack uses it to confirm each event really came from your Stripe account.
- **Checkout Session** — Stripe's system for collecting payment details and managing customer transactions.
- **Visitor ID (st_aid)** — the anonymous tracking identifier that maps the customer's click journey.

## What You Will Set Up

You will configure your backend server code to retrieve the visitor ID from local storage (or a browser cookie) and pass it into Stripe's checkout session metadata. You will then set up a webhook endpoint inside Stripe to forward completed checkout session events to SourceTrack.

**Integration notice:** This setup is an API and webhook integration recipe. SourceTrack does not provide an official Stripe Dashboard extension or marketplace plugin. You must configure metadata forwarding in your billing system code and set up webhooks manually in your Stripe Dashboard.

## Which Stripe Method Are You Using?

Pick the entry that matches how your site takes payment. You can use more than one.

- **Payment Links (`buy.stripe.com`):** add the SourceTrack tracker to the page that holds the link. On the standard install, the tracker adds `client_reference_id` to the link when a visitor clicks it, if tracking is allowed for that visitor. A link that already has its own `client_reference_id` is left as it is, and the cookieless install does not add it. Then do Step 2 below.
- **Checkout Sessions created by your backend:** do Step 1 and Step 2 below.
- **Payment Intents without Checkout:** this webhook does not read `payment_intent.succeeded`, so it does not record these sales. Use the Offline Conversions API linked under Next Step.

## Steps: Stripe Integration

### Step 1: Forward Visitor ID in Stripe Metadata

When creating a Stripe Checkout Session on your backend, read the visitor ID (stored in the browser as `st_aid`) from the client's request payload and pass it as `client_reference_id` or inside the `metadata` block as `anonymous_id` or `visitor_id`.

```
// Example of passing st_aid in Stripe Checkout Session creation (Node.js backend)
const session = await stripe.checkout.sessions.create({
  payment_method_types: ['card'],
  line_items: [{ price: 'price_H5gg...', quantity: 1 }],
  mode: 'subscription',
  success_url: 'https://yoursite.com/success',
  cancel_url: 'https://yoursite.com/cancel',

  // Method A: Pass directly as client_reference_id (Recommended)
  client_reference_id: req.body.st_aid,

  // Method B: Pass inside metadata object
  metadata: {
    anonymous_id: req.body.st_aid
  }
});
```

### Step 2: Configure Stripe Webhook

Route event messages from Stripe directly to the SourceTrack ingestion URL:

1. Log in to your **Stripe Dashboard** and navigate to **Developers → Webhooks**.
2. Click **Add Endpoint**.
3. Enter your customized webhook endpoint URL:
   https://api.srctk.com/api/webhooks/stripe/YOUR_SITE_KEY
   Replace `YOUR_SITE_KEY` with the Site Key found under settings in your dashboard.
4. Under **Select events to listen to**, add:
    - `checkout.session.completed`
    - `refund.created`
    - `checkout.session.async_payment_succeeded` — required if you accept delayed payment methods (ACH, SEPA debit, Klarna, bank debits)
    - `checkout.session.async_payment_failed` — recommended with the above (SourceTrack ignores it safely; nothing is booked until settlement)
5. Click **Add Endpoint**.

Refunds are recorded as negative conversions and automatically net your revenue by source — subscribe to `refund.created`.

Card and instant checkout payments book on `checkout.session.completed` when `payment_status` is already `paid`. Delayed methods complete the session with `payment_status: unpaid` first — SourceTrack waits for `checkout.session.async_payment_succeeded` before recording revenue. Without that event subscribed, those sales never appear.

To secure your webhook, save the Stripe Webhook signing secret (starts with `whsec_`) in your SourceTrack dashboard under **Integrations → Stripe settings**. SourceTrack uses it to confirm that each event really came from your Stripe account.

## How to Verify It Worked

1. Make a real, low-value **live** purchase through your own checkout (use a visit that came from a tagged link, so it has a source), then refund it. Refunds net out of your revenue by source automatically.
2. In your Stripe Dashboard under **Developers → Webhooks**, inspect the event logs for `checkout.session.completed`.
3. Verify that the webhook request returned a HTTP `200 OK` response.
4. Verify that the transaction data (revenue and site metadata) appears attributed in the **Event Debugger** of your SourceTrack dashboard.

Stripe test-mode events (`livemode: false`, including Stripe’s “Send test webhook”) are ignored by design: Stripe still sees `200 OK`, but nothing is recorded as revenue, so a test-mode payment will never appear in the Event Debugger.

## Common Mistakes

- **Incorrect Webhook Event Types:** Stripe triggers a variety of events like `payment_intent.succeeded`. SourceTrack parses `checkout.session.completed`, `checkout.session.async_payment_succeeded`, `refund.created`, and subscription lifecycle events; other events are safely ignored. If you use ACH/SEPA/Klarna and only subscribe to `checkout.session.completed`, revenue will not be recorded when those payments settle.
- **Unmatched Metadata Key:** If you use custom names like `metadata.st_aid`, SourceTrack will not read it. Stick to `client_reference_id` or `metadata.anonymous_id`.
- **Missing Stripe Signing Secret:** If you omit the signing secret under Settings, webhook payload signature checks will fail, returning a `400 Bad Request`.

## Next Step

Stripe setup is complete! Go to the [Offline Conversions API](https://www.sourcetrack.ai/developers/offline-conversions) to learn how to register custom offline sales or updates directly from your server.
