Guides·Intermediate

Stripe Webhook Integration

Connect Stripe to Attro for automatic conversion tracking. Step-by-step webhook setup with code examples.

7 minLast updated June 13, 2026

Prerequisites

  • Stripe account with checkout or payment links
  • Attro organization created
  • Access to Stripe Dashboard webhooks section

Stripe integration is the backbone of Attro's conversion tracking for web purchases. When a customer completes a payment through an affiliate link, Attro automatically records the conversion and calculates commissions - no manual work required.

This guide covers the complete Stripe setup, including webhook configuration, attribution passing, and handling different payment scenarios like subscriptions.

How It Works

  1. Customer clicks an affiliate's tracking link
  2. Attro sets a first-party cookie with the click ID
  3. Customer completes purchase on your site
  4. Stripe sends a webhook event to Attro
  5. Attro matches the click ID and records the conversion
  6. Commission is calculated based on your offer settings

Why webhooks? Webhooks provide real-time, server-to-server communication. Unlike client-side tracking, they can't be blocked by ad blockers and are more reliable.

1

Create Webhook Endpoint in Stripe

First, you'll add Attro's webhook URL to your Stripe account.

Navigate to Webhooks

  1. Log into your Stripe Dashboard
  2. Click "Developers" in the left sidebar
  3. Select "Webhooks"
  4. Click "Add endpoint"

Configure the Endpoint

Enter the following details:

Endpoint URL:

https://get-attro.com/api/webhooks/stripe

Events to subscribe:

  • checkout.session.completed - For Stripe Checkout purchases
  • invoice.paid - For subscription renewals
  • charge.succeeded - For direct charges

Select Your Events

  1. Click "Select events"
  2. Search for each event name
  3. Check the checkbox next to each
  4. Click "Add events"
  5. Click "Add endpoint" to save

Tip: Start with checkout.session.completed if you're using Stripe Checkout. Add the others as needed for your payment flows.

2

Configure Webhook Secret

The webhook signing secret allows Attro to verify that events genuinely come from Stripe, not a malicious third party.

Get Your Signing Secret

  1. In Stripe Webhooks, click on your new endpoint
  2. Find "Signing secret" in the endpoint details
  3. Click "Reveal" to show the secret
  4. Copy the value (starts with whsec_)

Add to Attro

  1. In Attro, go to Settings → Integrations
  2. Find the Stripe section
  3. Paste your signing secret
  4. Click "Save"
# Your signing secret looks like this:
whsec_1234567890abcdefghijklmnopqrstuvwxyz

# Never commit this to your code repository!

Security: The signing secret should be kept confidential. Attro stores it encrypted and uses it only for webhook verification.

3

Pass Affiliate Attribution in Metadata

For Attro to attribute a conversion to the correct affiliate, you need to pass the click ID from the tracking cookie to Stripe.

Option 1: Stripe Checkout Session

When creating a Checkout Session, include the click ID in metadata:

// Server-side: Creating a Stripe Checkout Session
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

app.post('/create-checkout', async (req, res) => {
  // Get the click ID from the request (passed from client)
  const { clickId } = req.body;

  const session = await stripe.checkout.sessions.create({
    line_items: [
      {
        price: 'price_1234567890',
        quantity: 1,
      },
    ],
    mode: 'subscription', // or 'payment' for one-time
    success_url: 'https://yourapp.com/success',
    cancel_url: 'https://yourapp.com/cancel',

    // Pass attribution data in metadata
    metadata: {
      rd_click_id: clickId || '',
    },

    // For subscriptions, also add to subscription_data
    subscription_data: {
      metadata: {
        rd_click_id: clickId || '',
      },
    },
  });

  res.json({ url: session.url });
});

Option 2: Payment Links

If using Stripe Payment Links, you can pass the click ID as a URL parameter:

// Construct payment link with client_reference_id
const paymentLinkUrl = 'https://buy.stripe.com/your_link_id';
const clickId = getAttroClickId(); // Function defined below

const urlWithAttribution = `${paymentLinkUrl}?client_reference_id=${clickId}`;

// Redirect customer to this URL
window.location.href = urlWithAttribution;

Option 3: Direct Charges

For PaymentIntent or direct charges:

const paymentIntent = await stripe.paymentIntents.create({
  amount: 9900,
  currency: 'usd',
  metadata: {
    rd_click_id: clickId,
  },
});
4

Read the Click ID from Cookie

When users click affiliate tracking links, Attro sets a first-party cookie. Here's how to read it on your site.

JavaScript (Browser)

// Get Attro click ID from cookie
function getAttroClickId() {
  const cookies = document.cookie.split(';');
  for (const cookie of cookies) {
    const [name, value] = cookie.trim().split('=');
    if (name === 'rd_click_id') {
      return decodeURIComponent(value);
    }
  }
  return null;
}

// Usage: Pass to your checkout API
const clickId = getAttroClickId();
if (clickId) {
  // Include in your checkout request
  fetch('/create-checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ clickId }),
  });
}

React Hook

import { useEffect, useState } from 'react';

function useAttroClickId() {
  const [clickId, setClickId] = useState<string | null>(null);

  useEffect(() => {
    const cookies = document.cookie.split(';');
    for (const cookie of cookies) {
      const [name, value] = cookie.trim().split('=');
      if (name === 'rd_click_id') {
        setClickId(decodeURIComponent(value));
        break;
      }
    }
  }, []);

  return clickId;
}

// Usage in component
function CheckoutButton() {
  const clickId = useAttroClickId();

  const handleCheckout = async () => {
    const response = await fetch('/api/checkout', {
      method: 'POST',
      body: JSON.stringify({ clickId }),
    });
    // ... handle response
  };

  return <button onClick={handleCheckout}>Checkout</button>;
}

Server-Side (Next.js)

// pages/api/checkout.ts or app/api/checkout/route.ts
import { cookies } from 'next/headers';

export async function POST(request: Request) {
  const cookieStore = await cookies();
  const clickId = cookieStore.get('rd_click_id')?.value;

  // Use clickId when creating Stripe session
  const session = await stripe.checkout.sessions.create({
    // ...
    metadata: {
      rd_click_id: clickId || '',
    },
  });

  return Response.json({ url: session.url });
}
5

Verify Webhook Connection

Test that your webhook integration is working correctly before going live.

Stripe CLI Testing (Development)

Use the Stripe CLI to forward webhooks to your local environment:

# Install Stripe CLI
brew install stripe/stripe-cli/stripe

# Login to your Stripe account
stripe login

# Forward webhooks to local
stripe listen --forward-to localhost:3000/api/webhooks/stripe

# The CLI will show you a webhook signing secret for testing
# Use this in your local environment

# In another terminal, trigger a test event
stripe trigger checkout.session.completed

Production Testing

  1. Click an affiliate tracking link (use incognito mode)
  2. Complete a purchase using Stripe test mode
  3. Check Attro admin → Conversions
  4. Verify the conversion shows with correct affiliate

Check Webhook Logs

In Stripe Dashboard → Webhooks → Your endpoint, you can see:

  • Recent webhook deliveries
  • Response status codes
  • Request/response bodies
  • Retry attempts for failed deliveries

Troubleshooting: If webhooks fail, check: 1) Signing secret matches, 2) Endpoint URL is correct, 3) Your server returns 200 status.

6

Handle Recurring Payments

For subscription products, you'll want to track both initial purchases and renewals.

Commission on Initial Purchase

The checkout.session.completed event fires when a customer first subscribes. This captures the initial conversion.

Commission on Renewals

The invoice.paid event fires on each renewal. To track these:

  1. Ensure you added rd_click_id to subscription_data.metadata
  2. Subscribe to invoice.paid events
  3. Configure recurring commissions in your offer settings

Offer Settings for Subscriptions

In Attro, configure how recurring commissions work:

  • First Payment Only - Commission on initial purchase only
  • Lifetime - Commission on every renewal forever
  • Fixed Period - Commission for a set number of months (e.g., 12)
// Example: $99/month subscription, 20% commission, 12-month recurring

// Month 1 (initial): $99 × 20% = $19.80 commission
// Month 2-12 (renewals): $99 × 20% = $19.80 each
// Month 13+: No commission (exceeded 12-month period)

// Total potential commission: $19.80 × 12 = $237.60

Handling Upgrades & Downgrades

Subscription changes (upgrades, downgrades) trigger new invoice.paid events. The commission is calculated on the prorated amount or new price, depending on your Stripe configuration.

Integration Complete

Your Stripe integration is now configured for automatic conversion tracking. Every purchase that includes a valid click ID will be attributed to the correct affiliate.

Quick Reference

  • Webhook URL: https://get-attro.com/api/webhooks/stripe
  • Cookie Name: rd_click_id
  • Metadata Key: rd_click_id

Next Steps

Questions? Contact us at [email protected].

Need help with integration?

Our support team is here to help you get set up.