> ## Documentation Index
> Fetch the complete documentation index at: https://docs.datalyr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Stripe Webhooks

> Send Stripe checkout and subscription events to ad platforms with automatic attribution matching

# Stripe Webhooks

Connect Stripe webhooks to automatically track purchases and subscriptions as conversion events. DATALYR matches customers to their original ad click using email-based identity resolution.

## What You'll Learn

* How to configure Stripe webhooks
* Supported Stripe events
* Email attribution matching
* Testing and verification

## Before You Start

* [ ] DATALYR tracking script installed on your website
* [ ] Email capture with `datalyr.identify(email, { email })` before checkout
* [ ] Admin access to Stripe Dashboard
* [ ] Active workspace in DATALYR

## Supported Events

DATALYR processes these Stripe webhook events:

| Stripe Event                    | DATALYR Event | Description                    |
| ------------------------------- | ------------- | ------------------------------ |
| `checkout.session.completed`    | `purchase`    | One-time payment completed     |
| `customer.subscription.created` | `subscribe`   | New subscription started       |
| `invoice.payment_succeeded`     | `purchase`    | Recurring subscription payment |

## How Attribution Works

When a customer completes a Stripe checkout:

1. Stripe sends webhook with `customer_email` to DATALYR
2. DATALYR queries events table: "Find visitor\_id where email matches"
3. DATALYR retrieves original attribution (fbclid, gclid, UTMs)
4. Event is created with `source: 'stripe'` and attribution data
5. Conversion rules fire postbacks to Meta, Google, TikTok

<Note>
  Attribution only works if you call `datalyr.identify(email, { email })` before the customer reaches Stripe checkout. The email must be captured in a DATALYR event first.
</Note>

## Step 1: Get Webhook URL

1. Log in to DATALYR dashboard
2. Navigate to **Sources** tab
3. Click **Webhooks** tab
4. Click **Stripe** card
5. Copy your webhook URL

The URL format is:

```
https://webhooks.datalyr.com/stripe/YOUR_WORKSPACE_ID
```

## Step 2: Configure Stripe Webhook

### Add Webhook Endpoint

1. Log in to [Stripe Dashboard](https://dashboard.stripe.com)
2. Navigate to **Developers** → **Webhooks**
3. Click **Add endpoint**
4. Paste your DATALYR webhook URL
5. Click **Select events**

### Select Events

Choose these events to listen to:

* `checkout.session.completed`
* `customer.subscription.created`
* `invoice.payment_succeeded` (optional, for recurring payments)

### Get Signing Secret

After creating the webhook:

1. Click on the webhook endpoint
2. Click **Reveal** next to Signing secret
3. Copy the secret (starts with `whsec_`)
4. Return to DATALYR webhook setup modal
5. Paste the signing secret
6. Click **Save**

DATALYR stores the secret to verify webhook signatures and prevent spoofing.

## Step 3: Verify Setup

### Test with Stripe CLI

If you have Stripe CLI installed:

```bash theme={null}
# Forward webhooks to DATALYR
stripe listen --forward-to https://webhooks.datalyr.com/stripe/YOUR_WORKSPACE_ID

# Trigger test checkout
stripe trigger checkout.session.completed
```

### Test with Real Checkout

1. Create a test product in Stripe
2. Visit your site with ad parameters: `yoursite.com?fbclid=test123`
3. Call `datalyr.identify('test@example.com', { email: 'test@example.com' })`
4. Complete Stripe checkout with the same email
5. Check DATALYR Event Stream

You should see:

* A `purchase` event with `source: 'stripe'`
* Attribution data (fbclid, visitor\_id) from original session
* Event value matching Stripe amount

## Step 4: Create Conversion Rules

After verifying webhook events are created, set up conversion rules to fire events to ad platforms.

### Example: Meta Purchase Event

1. Navigate to **Integrations** → **Conversion Rules**
2. Click **Create Rule**
3. Configure rule:

**Trigger:**

* Event Name: `purchase`
* Event Source: `stripe`

**Action:**

* Platform: Meta Ads
* Event Type: `Purchase`

**Value Mapping:**

* Use event value from webhook

Now when Stripe sends a checkout.session.completed webhook, DATALYR will fire a Purchase event to Meta with the original fbclid.

## Event Data Structure

Stripe webhooks create events with this structure:

```json theme={null}
{
  "event_id": "stripe_cs_abc123",
  "workspace_id": "uuid",
  "event_name": "purchase",
  "source": "stripe",

  "visitor_id": "original_visitor_id",
  "user_id": "customer@example.com",
  "fbclid": "original_fbclid",
  "gclid": "original_gclid",

  "value": 99.00,
  "currency": "USD",

  "event_data": {
    "session_id": "cs_abc123",
    "customer_id": "cus_abc123",
    "payment_intent": "pi_abc123",
    "mode": "payment",
    "status": "paid"
  }
}
```

## Attribution Match Rate

DATALYR's email-based attribution achieves:

* **95%+ match rate** when email is captured before checkout
* **90%+ match rate** for cross-device (mobile ad → desktop purchase)
* **85%+ match rate** for 30+ day attribution windows

### Maximize Match Rate

Capture email early in the customer journey:

```javascript theme={null}
// When user submits email form (before Stripe)
document.getElementById('email-form').addEventListener('submit', function(e) {
  const email = document.getElementById('email').value;

  datalyr.identify(email, {
    email: email
  });
});

// Or on page load if user is logged in
if (currentUser) {
  datalyr.identify(currentUser.email, {
    email: currentUser.email,
    name: currentUser.name
  });
}
```

## Value Calculation

DATALYR automatically converts Stripe amounts:

* **Checkout sessions:** `amount_total / 100` (Stripe uses cents)
* **Subscriptions:** Monthly value calculated from billing interval
  * Annual: `amount / 100 / 12`
  * Monthly: `amount / 100`
  * One-time: `amount / 100`

## Deduplication

Stripe may send the same webhook multiple times (retries). DATALYR uses Cloudflare KV to deduplicate:

1. Extract `event.id` from webhook
2. Check if `workspace_id:event_id` exists in KV
3. If exists, return 200 OK but skip processing
4. If new, process and store in KV

This prevents double-counting conversions.

## Security

DATALYR verifies all Stripe webhooks using signature validation:

1. Extract `Stripe-Signature` header
2. Verify signature matches webhook secret
3. Reject invalid signatures with 401 Unauthorized

Your signing secret is encrypted and stored securely in DATALYR's database.

## Troubleshooting

### Events have no attribution data

**Symptoms:** Stripe events appear in Event Stream but fbclid/gclid are null

**Cause:** Email was not captured with `datalyr.identify()` before checkout

**Solution:**

1. Add `datalyr.identify(email, { email })` on email capture forms
2. Ensure identify call happens before Stripe checkout redirect
3. Test by checking Event Stream for identify events with the same visitor\_id

### Webhooks not appearing in Event Stream

**Symptoms:** Stripe checkout completes but no event in DATALYR

**Cause:** Webhook URL not configured or signing secret incorrect

**Solution:**

1. Check Stripe Dashboard → Webhooks → verify endpoint is active
2. Click webhook endpoint → check for delivery errors
3. Verify signing secret in DATALYR matches Stripe
4. Test with Stripe CLI to see error details

### Signature verification failed

**Symptoms:** Stripe Dashboard shows webhook delivery failures with 401 errors

**Cause:** Signing secret mismatch or not saved in DATALYR

**Solution:**

1. Get signing secret from Stripe webhook endpoint
2. Return to DATALYR webhook setup modal
3. Paste and save the signing secret
4. Trigger new test event

### Wrong event value

**Symptoms:** Event value in DATALYR doesn't match Stripe amount

**Cause:** Currency conversion or subscription interval calculation

**Solution:**

1. Check `event_data.amount_total` in Event Stream
2. Verify currency is correct (DATALYR uses uppercase)
3. For subscriptions, check billing interval in `event_data.interval`
4. Contact support if amounts are incorrect

## What Happens Next

After webhook events are created:

1. **Postback Worker** checks for matching conversion rules
2. Rules filtered by `trigger_event_source: 'stripe'`
3. Conversions fire to Meta, Google, TikTok with original attribution
4. Ad platforms receive events with fbclid/gclid for optimization

## Stripe Revenue Analytics (Separate Feature)

Webhook attribution is separate from Stripe Revenue Analytics:

**Webhooks (This Feature):**

* Real-time conversion tracking
* Fires events to ad platforms
* No OAuth required

**Revenue Analytics:**

* Dashboard metrics (MRR, ARR, churn)
* Requires API key connection
* Periodic data sync

To set up Revenue Analytics, navigate to **Sources** → **Revenue Sources** → **Stripe**.

## Next Steps

* [Create conversion rules for Stripe events](/integrations/conversion-rules)
* [Set up Superwall webhooks](/integrations/superwall)
* [Set up RevenueCat webhooks](/integrations/revenuecat)
* [Monitor webhook events in Event Stream](/features/event-stream)
