Modeling your SaaS business with Products and Prices
Tags: stripe, payment, saas, tutorial
Published: 2022-08-04 15:58:00

{% youtube https://www.youtube.com/watch?v=1RwPB3sqzKc %}

As we learned in [the primer](https://dev.to/stripe/a-primer-for-collecting-recurring-payments-with-stripe-4mik), [Products](https://stripe.com/docs/api/products) and [Prices](https://stripe.com/docs/api/prices) are core resources for many Stripe integrations. They’re closely associated with Checkout Sessions, Invoices, Payment Links, Subscriptions, and the new Orders API.

Now, you’ll learn how to create and manage Products and Prices so that you’ll be able to take advantage of the customer portal, embeddable pricing tables, up-sells, and more.

At the end I’ll share a shortcut for scaffolding a good-better-best value based SaaS business model using a [Stripe CLI fixture](https://stripe.com/docs/cli/fixtures), so stay tuned (or just scroll to the bottom). 

**Working with products and prices**
You can create and update products and prices in the Dashboard or through the API. You really only need to create new Products and Prices when setting up a new integration or if you launch a new product offering. In this article, we’ll use the Stripe CLI to make API calls. 

- Some advanced use cases, like [creating](https://stripe.com/docs/products-prices/manage-prices#ad-hoc-prices) [ad-hoc prices](https://stripe.com/docs/products-prices/manage-prices#ad-hoc-prices), require you to use the API. If you have a large number of products and prices or if you’re building a custom integration with Elements, you need to use the API.
- Use the Dashboard to create and manage products and prices, if you want to avoid writing code or if you only have a few products and prices. Set up your pricing model in test mode and click the “Copy to live mode” button on the product details page.


![Copy to live mode from the product detail view.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gexsf5x4n43lgt9mpp6.png)


**What is a Product?**
Products describe the specific goods or services you offer to your customers. I tend to use the terms “level”, “tier”, and “plan” all to represent the Product that a customer is purchasing. If you’re working on a much older Stripe integration, you may also see a Plan object. Plan is a legacy object that is replaced with the newer and more flexible Price object, so you should avoid using Plans and instead use Prices.

A Product requires a name, and can optionally have several other attributes like description, images, and more. Most SaaS pricing tables display a list of features that are included for a given subscription level. You can specify a list of features related to a Product.

If you’re a SaaS platform you might have *basic* and *premium* tiers. Both basic and premium would be modeled as separate products if they offer unique attributes or features. You may also require a set-up fee or one-time training service. One-time fees are also configured as Products — we’ll cover one-time fees in the next article.


Products can also have an associated tax-code. There are several related to SaaS and they are used with Stripe Tax to derive the correct taxes to apply. 
Each Product must have one (or more) related Prices, and a Price represents much more than the amount.


![Screenshot showing the enterprise Product in a pricing table and how it relates to an enterprise Product in the Stripe dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qwkjp7hqxsc3cebiq6q8.png)
 


**What is a Price?**
When you think of “price” you probably think of a number for how much something costs. In Stripe, a Price is a little more than just an amount. Prices encapsulate how much and how often the customer will pay (with a given currency).

Prices can have a fixed `unit_amount` or can use tiers. Tiers in this case are not related to good-better-best SaaS tiers, but a separate graduated pricing model where the cost is fixed for the first X, then a little less for Y, and even less for Z.  If you’re curious about tiered pricing for graduated or volume based pricing, please check out the [Stripe documentation](https://stripe.com/docs/products-prices/pricing-models#model-usage-based-pricing-on-stripe) for more information. 

We’ll model our SaaS pricing with fixed `unit_amount`. Prices for Subscriptions are recurring and you must specify an interval like `month` or `year` for how frequently the customer will be charged.

If using Stripe Tax, you’ll also want to specify the `tax_behavior` for the Price to determine whether the tax is already included in the amount (`inclusive`), or if tax should be added (`exclusive`).


![Screenshot showing the enterprise Product's price in a pricing table and how it relates to an enterprise Product's price in the Stripe dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qwpngirp0c7lylyilmxk.png)
 

**Why modeling your pricing correctly matters**
Certain features of Stripe expect your pricing to be modeled in a specific way. For instance, [customer portal settings](https://dashboard.stripe.com/test/settings/billing/portal) expect that each pricing level has a separate product with its own prices at their given recurring intervals. 


![Screenshot of the product selection for a customer portal configuration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxhe1pqo9mjbzua7jkpl.png)
 


Also, if you want to enable upsells from monthly to annual, directly in Checkout, pricing must be modeled in a specific way. 


![Screenshot showing upsell configuration for prices in the Stripe dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y43ic7lavwi45rlulpco.png)
 


Lastly, getting the modeling of your business right ensures it’ll play nicely with the new [embeddable pricing table](https://stripe.com/docs/payments/checkout/pricing-table).


![Screenshot of the embeddable pricing table creation flow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vr1h00czuj5zbkhww7jy.png)
 

**Modeling pricing for a SaaS application**
Most software-as-a-service platforms offer different pricing depending on the value created for the customer. Imagine we’re starting a new subscription-based business. 

At first we’ll focus on keeping the business model very simple and only offer monthly subscriptions for a single price.  We’ll need 1 product and 1 price which we can create with the Stripe CLI:

```
stripe products create --name "Startup" --description "The essentials for when you're just getting started."
```

The output of that command is the JSON for the newly created Product which will include an ID that looks like “prod_abc123.” We’ll use that ID to create related Price:


```
stripe prices create --product prod_abc123 --unit-amount 500 -d "recurring[interval]=month" --currency USD --tax-behavior=exclusive
```

This is the simplest way to store products and prices that we’ll use later to set up subscriptions. Starting with monthly plans is great, but we know that by also offering an annual plan, we’ll get better predictability, more cashflow, and lower accounting costs because we only need to reconcile once per year instead of monthly. The service we offer will be exactly the same, the customer will just have two options now to either pay once per month or once per year. We can persuade customers to opt for annual pricing by providing a small discount over a monthly subscription.

Now we’re faced with a decision: Create a new Price for the existing Product? Or create a new Product and a new Price for the annual plan?

The answer is: **create a new Price for the** ***existing*** **Product.** Since the feature set and value offered on the annual plan is the same as the monthly plan we should create a new *Price.*


```
stripe prices create --product prod_KcyHvtjwKmIAQx --unit-amount 5000 -d "recurring[interval]=year" --currency USD --tax-behavior=exclusive
```

With this single Product, we now have two price points where customers can subscribe to pay monthly or annually.

This unlocks the first benefit to proper modeling: upsells. Since we want to encourage users to purchase the annual plan, we can update the monthly Price and set it to *upsell* to the annual Price.

**Note**: Configuring upsells is not supported with the API and is dashboard only. If you’d like to use the API for upsells, we’d love to learn more about your use case, so please get in touch: [@cjav_dev](https://twitter.com/cjav_dev)!


This is what customers see when they Subscribe:


![Upsell in Checkout](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ikqlgxtluswk675xtf1.png)
 


As the product improves and gains traction with more sophisticated customers, we’ll need to realign the value of the offering with the price charged. One way to do this is to increase prices for all new customers. We’ll talk about how to experiment with price changes using lookup keys in a future piece. For now, we want to start offering differentiated service for our customers of different segments. We’ll create a new enterprise tier that includes dedicated support, a feature set that fits nicely with what the larger customers need.

Since this new offering will include different **value** for the customer, we want to create a new Product with its own Price. We also want to offer enterprise customers the option of paying monthly or annually. Let’s create a new product and its monthly and annual prices.



```
stripe products create --name "Business" --description "For businesses looking to achieve maximum efficiency and time savings."
```


```
stripe prices create --product prod_abcdef --unit-amount 3200 -d "recurring[interval]=month" --currency USD --tax-behavior=exclusive
```

```
stripe prices create --product prod_abcdef --unit-amount 32000 -d "recurring[interval]=year" --currency USD --tax-behavior=exclusive
```

One last consideration is currency. If we want to offer customers the ability to pay in a different currency than the one configured for existing prices, then we’ll need to create new Prices for the existing Products. For example, we may want to create a 28 EUR Price and a 280 EUR price for our monthly and annual plans so that our European customers can pay with EUR instead of USD.
You can follow this same pattern for a third, fourth, or fifth tier.

You can also use [this fixture](https://gist.github.com/cjavilla-stripe/fdafc2666e634742b4fec2db03b34e72) file with the Stripe CLI to quickly scaffold some example products and prices:


```
stripe fixtures value-based-saas-pricing-seed.json
```

In the next article, we’ll cover some common questions like how to model setup fees or mid-billing-cycle one time fees.


## About the author
![CJ Avilla](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jkrntdknq78taumwp4qv.png)
 


[CJ Avilla](https://cjav.dev) ([@cjav_dev](https://twitter.com/cjav_dev)) is a Developer Advocate at Stripe, a Ruby on Rails developer, and a [YouTuber](https://www.youtube.com/CJAvilla). He loves learning and teaching new programming languages and web frameworks. When he’s not at his computer, he’s spending time with his family or on a bike ride 🚲.