Connect to customers

Revenue analytics is in beta

Revenue analytics is currently works best for:

  1. Small to medium-sized companies
  2. Companies with subscription models (mostly SaaS)

If you process more than 20,000 transactions per month, or your revenue comes primarily from one-off payments rather than recurring subscriptions, revenue analytics may feel less useful, slower, or provide less insight than expected.

PostHog automatically connects revenue data to persons and groups when you use revenue events. For data warehouse sources, you need to map the connection manually.

Step 1: Add metadata when creating new customers

Search your codebase for where you create Stripe customers (e.g. stripe.Customer.create or equivalent) and add the posthog_person_distinct_id metadata field.

customer = stripe.Customer.create(
email=user.email,
metadata={"posthog_person_distinct_id": user.posthog_distinct_id},
)

Step 2: Tag existing customers via charges, subscriptions, or invoices

For customers created before you added the metadata in step 1, you don't need to update the customer object directly. Instead, pass posthog_person_distinct_id as metadata on any charge, subscription, or invoice tied to that customer. PostHog automatically resolves it from the most recently created child object.

Add the metadata to whichever Stripe call you already make. Here are the most common patterns:

Subscriptions

stripe.Subscription.create(
customer=user.stripe_customer_id,
items=[{"price": "price_xxx"}],
metadata={"posthog_person_distinct_id": user.posthog_distinct_id},
)

One-off charges (payment intents)

stripe.PaymentIntent.create(
amount=1000,
currency="usd",
customer=user.stripe_customer_id,
metadata={"posthog_person_distinct_id": user.posthog_distinct_id},
)

Stripe Checkout

Pass the metadata in the checkout session's subscription_data or payment_intent_data depending on your checkout mode. Also set client_reference_id to your internal user ID so you can look up the distinct ID.

# For recurring (subscription) checkout
session = stripe.checkout.Session.create(
mode="subscription",
client_reference_id=user.id,
subscription_data={
"metadata": {"posthog_person_distinct_id": user.posthog_distinct_id},
},
# ... other params
)
# For one-time payment checkout
session = stripe.checkout.Session.create(
mode="payment",
client_reference_id=user.id,
payment_intent_data={
"metadata": {"posthog_person_distinct_id": user.posthog_distinct_id},
},
# ... other params
)

How does this work? PostHog looks for posthog_person_distinct_id in the metadata of subscriptions, charges, and invoices tied to each Stripe customer. If the customer object doesn't have the metadata directly, PostHog uses the value from the most recently created child object.

Once this is connected you'll be able to properly see who your top customers are in the Top customers dashboard.

You'll also get access to the persons_revenue_analytics and groups_revenue_analytics tables in the data warehouse. This is a simple map of person_id/group_key to what their all-time revenue is.

SQL
-- Count the number of persons with revenue greater than 1,000,000
SELECT COUNT(*)
FROM persons_revenue_analytics
WHERE amount > 1000000

Community questions

Was this page useful?

Questions about this page? or post a community question.