Most SaaS founders know Stripe metadata exists. Most use it inconsistently - a few fields here, different naming on different objects, gaps where data should be. And most have no way to actually analyze it, so the discipline of populating it fades over time.
The result: months or years of subscription data with almost no business context attached to it. You know what customers paid. You don't know where they came from, what segment they're in, or why the ones who churned were different from the ones who stayed.
This guide is about fixing that - practically. What fields to create, how to set them consistently, and what becomes possible when your metadata is clean and complete.
What Stripe Metadata Actually Is
Stripe metadata is a key-value store you can attach to almost any Stripe object. Customers, subscriptions, invoices, payment intents, charges, products - all of them support a metadata field that accepts up to 50 key-value pairs, each key up to 40 characters and each value up to 500 characters.
It's Stripe's way of letting you extend their data model with your own business context. Stripe stores it, preserves it, returns it in API responses, and keeps it attached to the object for as long as the object exists.
What Stripe does not do is analyze it for you. That's the gap this guide helps you close.
How to Set Metadata in Stripe
There are four main places where metadata gets written to Stripe objects. Using all four - consistently - is what makes the data usable.
1. At Customer Creation (Checkout Sessions and API)
The most reliable way to attach acquisition context to a customer is at the moment they sign up. If you use Stripe Checkout, you can pass metadata through the Checkout Session and it flows onto the resulting customer and subscription automatically.
const session = await stripe.checkout.sessions.create({
customer_email: email,
metadata: {
utm_source: params.utm_source || '',
utm_medium: params.utm_medium || '',
utm_campaign: params.utm_campaign || '',
acquisition_source: params.ref || 'direct',
plan_type: 'saas',
},
// ...
});
If you create customers directly via the API (outside of Checkout), pass metadata in the same call:
const customer = await stripe.customers.create({
email: email,
metadata: {
user_id: user.id,
acquisition_source: source,
company_size: company_size,
industry: industry,
},
});
The principle: capture context at the moment it exists. Acquisition source is easiest to record at signup. Company size is easiest to record when the user fills out their profile. Trying to backfill these later is possible but painful.
2. At Subscription Creation
Some context belongs on the subscription rather than the customer - especially context that might change if a customer upgrades, downgrades, or takes out a second subscription.
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: priceId }],
metadata: {
plan_type: 'annual',
trial_source: 'product_led',
coupon_applied: couponCode || '',
sales_rep: salesRepId || '',
},
});
If a customer upgrades and you create a new subscription, the new subscription's metadata reflects the new context. The customer-level metadata stays constant.
3. Updating Metadata After the Fact
You can update metadata on any object at any time. This is useful for enrichment: adding company size after a customer fills out their profile, updating sales rep when a deal is assigned, adding segment classification after an initial sync.
await stripe.customers.update(customerId, {
metadata: {
company_size: 'enterprise',
industry: 'fintech',
account_manager: 'sarah.jones',
},
});
The caveat: updates only affect new API responses. They don't retroactively change the values that existed at earlier points in time. For analytics purposes, what matters is that the metadata is correct now - because your current segmentation analysis uses current values.
4. Via Stripe Dashboard (No Code)
For small-scale updates or manual enrichment, you can edit metadata directly in the Stripe Dashboard. Open any customer, subscription, or payment record, scroll to the metadata section, and add or edit key-value pairs inline.
This is fine for individual records but doesn't scale. For systematic metadata - especially acquisition data - the API approach is the only reliable path.
What Fields Every SaaS Should Track
These are the fields that unlock the most valuable analysis. You don't need all of them from day one - but the earlier you start, the more historical data you'll have to work with.
On the Customer Object
acquisition_source
Where did this customer first hear about you? Values like organic, paid_search, referral, product_hunt, podcast, direct. This is the most valuable single field for understanding which marketing channels produce high-LTV customers vs. low-retention ones.
utm_source / utm_medium / utm_campaign
If you run paid acquisition or track marketing campaigns, pass UTM parameters through to Stripe at signup. Most teams capture them in a cookie or URL parameter during the checkout flow and write them to Stripe when the customer is created. Once they're in Stripe, you can slice MRR and churn by campaign with no additional tooling.
company_size
For B2B SaaS: solo, smb, mid_market, enterprise, or headcount ranges like 1-10, 11-50, 51-200, 200+. The difference in churn rate and LTV between solo users and 50-person teams is usually significant - but you can't measure it without this field.
industry
Useful when you serve multiple verticals. Reveals which industries have the best retention, which convert fastest from trial, and which have the highest ARPU. Use a consistent, bounded value set - not free text.
sales_rep
For sales-led or hybrid GTM: which rep or team member closed this account. Lets you track retention and LTV by rep - which is often the most actionable data a sales leader doesn't have.
signup_country / region
Where is the customer located? Useful for international expansion analysis and identifying which geographies are growing fastest.
On the Subscription Object
plan_type
monthly, annual, or lifetime. Separate from the Stripe price - this is the categorization that tells you whether annual-plan customers churn less than monthly (they almost always do).
trial_source
How did this customer enter a trial? product_led, sales_demo, freemium_upgrade. Each path tends to produce different conversion and retention patterns.
coupon_code / discount_applied
Whether a discount was used at signup. Customers who enter on a discount often behave differently over time - higher initial conversion, sometimes higher churn at renewal when the discount expires.
sales_rep (if different from customer-level)
If the subscription was sold or assisted by a specific rep, even if the customer wasn't directly created by that rep.
Naming Conventions That Keep Metadata Usable
Inconsistent naming is what kills metadata over time. If some customers have utm_source and others have UTM_Source or source or Source, your analytics will fragment the data across three or four values that mean the same thing.
A few rules that prevent this:
Use snake_case consistently. Stripe field names use snake_case. Your metadata keys should too. acquisition_source, not AcquisitionSource or acquisitionsource.
Define a fixed value set for categorical fields. company_size should have five possible values that you define once and document. Not free text where one customer has "50 people" and another has "~50 employees."
Empty string vs. missing key. Decide upfront: do you write an empty string "" when a value isn't known, or do you omit the key entirely? Consistency matters here because your analytics tool will treat these differently.
Document your schema. Put the list of fields, their allowed values, and where they get written in a shared doc or your codebase. Metadata schemas decay when only one engineer knows what the fields mean.
The Analysis That Becomes Possible
With clean, consistent metadata, a set of questions becomes answerable that most SaaS analytics tools simply can't touch.
Which acquisition channel has the best LTV?
Slice LTV (or average subscription length, or 6-month revenue per customer) by utm_source or acquisition_source. The result often shows dramatic differences - organic search customers outretaining paid social customers by 2x is common. This directly informs where to allocate acquisition spend.
Does annual vs. monthly plan type affect churn?
Group churn rate by plan_type. Annual subscribers almost always churn less - but by how much, and whether the difference justifies the pricing premium, requires actual data.
Which sales rep's deals retain the longest?
Filter LTV and renewal rate by sales_rep. If one rep's deals consistently churn after 90 days and another's retain for 24 months, that's not a product problem - it's a qualification or expectation-setting problem that shows up in the data first.
Are discounted customers more likely to cancel?
Compare churn rate between customers with coupon_applied set vs. empty. If the answer is yes, you can price promotions more carefully or add success checkpoints before renewal.
Which industries have the highest ARPU?
Group ARPU by industry. The segment where customers pay the most and churn the least is often not the segment you're marketing hardest to - and this analysis reveals it.
What to Do If Your Metadata Is Incomplete
Most Stripe accounts have partial metadata - some fields on some customers, gaps everywhere else.
Don't wait for perfect data before you start. Partial metadata is still useful. If 60% of your customers have acquisition_source set, you can analyze that 60% and note the caveat. The remaining 40% can often be inferred or enriched manually for your top accounts.
Enrich forward, not backward. Focus on making sure every new customer gets the fields you care about. For historical customers, prioritize enriching your highest-value accounts - the ones where getting the segment right matters most for retention conversations.
Start with one field. If you're not using metadata at all today, pick the single most valuable dimension for your business - probably acquisition_source - and add it to your signup flow this week. One consistent field is worth more than ten inconsistent ones.
Analyzing Stripe Metadata Without Writing SQL
Once your metadata is in Stripe, the next problem is querying it. Stripe's dashboard lets you filter individual records by metadata, but it can't aggregate - you can't ask "what is churn rate by acquisition_source" from within Stripe.
The traditional answer is SQL: export the data, write queries, build charts manually. Chartsy is the alternative: connect your Stripe account and it automatically indexes every metadata field it finds. From there, you ask questions in plain English - "Show MRR by utm_source for the last 12 months" or "What is the churn rate by company_size?" - and get a chart in seconds.
Any chart you build with metadata dimensions can be saved to your dashboard and updates automatically with every sync. Your metadata-based segments become living views of your business - not one-off exports.
FAQ
How many metadata fields should I add to Stripe?
Start with three to five fields that directly answer your most important business questions. More is not better - ten inconsistently populated fields are less useful than three that are always complete. Add fields only when you have a specific question they'll answer.
Can I add metadata to existing Stripe customers?
Yes. You can update metadata on any customer, subscription, or invoice at any time via the API or directly in the Stripe Dashboard. The caveat is that updates are not retroactive - analytics tools see the current value, not historical values at past points in time.
What's the difference between Stripe metadata and custom fields?
Stripe metadata is a flexible key-value store you control - you define the keys and values. Stripe also has some structured custom fields (like customer description or address), but metadata is more flexible and is where most business-specific tagging happens.
Do UTM parameters automatically flow into Stripe?
No - Stripe doesn't capture UTM parameters from the browser. You need to explicitly read them from the URL or a cookie in your frontend and pass them to the Stripe API when creating the customer or Checkout Session. Once you write that code once, UTM data flows automatically for every subsequent signup.
Can I use Stripe metadata with Chartsy without writing any code?
If your metadata is already in Stripe, yes - Chartsy indexes it automatically when you connect your account, no code required. The code is only needed to get metadata into Stripe in the first place (which usually happens in your signup flow). If you haven't set up metadata yet, Stripe's documentation covers how to add it to your integration.

Written by
Chartsy TeamThe Chartsy Team writes guides, product updates, and resources to help SaaS and eCommerce founders make sense of their metrics, without SQL or spreadsheets.
Chartsy