Log in to Tier
Tier is a pricing model system that reduces the effort and risks of managing your application's pricing and packaging.
Much more information is available in the docs, but these steps will get you started.
Table of Contents
- Setting Up Tier
- Define a Pricing Model
- Integrate with Tier
- Get Paid
- Beyond Quickstart Guides: Iterating on Pricing Plans
- We're here to help
Setting Up Tier
The best way to interact with Tier is by using an SDK. But if you are using a language that is not fully supported, don't worry! We are eager to add more, and the API surface is small. Get in touch, and we'll do whatever it takes to get you supported.
Node.js
Get the Node.js SDK by running:
npm install @tier.run/sdk
This will give you a tier
command line client, and the library
that you can use in your application.
Go
Get the Go SDK by running:
go get tier.run/client/tier
Add the following to your imports list:
import (
"tier.run/client/tier"
)
Sign Up for Tier
Create an account at https://app.tier.run using your GitHub or Google account.
Tier will automatically create team accounts for your authorized GitHub or Google organizations, as well as a "solo org" for your individual account.
Create a Token for API Access
You can mint a token to save in the TIER_KEY
environment variable.
Tokens are associated with the organization or solo account that creates them.
Define a Pricing Model
The Pricing Model defines the single source of truth that allows everything else in your pricing ecosystem to be nimble while preserving safety.
Create your model by writing a pricing.json
file, and running:
tier push pricing.json
You can start by modeling your actual application's pricing model, of course, or you can use this very simple example:
{
"plans": {
"plan:welcome@0": {
"features": {
"feature:test": {
"tiers": [{}]
}
}
}
}
}
The pricing model can contain as many versions of as many plans
as you like. Whenever you want to make changes to a plan, just
create a file with the new version of the plan, and run tier push
again.
(Visual plan builder UI coming soon!)
Integrate with Tier
There are two pieces here. The first is telling Tier whenever an account org should be assigned to a plan, and the second is telling Tier about usage.
Assigning Orgs to Plans
Whenever a user signs up for your app, add them to a Plan, which appends to their schedule.
import {TierClient} from '@tier.run/sdk'
import type {OrgName, PlanName} from '@tier.run/sdk'
const tier = TierClient.fromEnv()
// Put this logic wherever you currently handle sign-ups
export const onUserSignUp = async (account: User, plan: PlanName) => {
// this appends a new phase to the org's schedule, with the
// specified plan name, like `plan:welcome@0`
await tier.appendPhase(`org:${account.id}`, plan)
}
Also call this method when an org changes their plan, by upgrading/downgrading, etc.
Handling Usage
When checking whether a user is allowed to consume some feature,
use the tierClient.can()
method. When the feature is consumed,
call tierClient.report()
to add it to their bill.
if (await tier.can('org:acme', 'feature:foo')) {
consumeOneFoo('acme')
await tier.report('org:acme', 'feature:foo')
} else {
// suggest they buy a bigger plan, maybe?
showUpgradePlanUX('acme')
}
Get Paid
Go to the Account page to set up your Stripe account, get the client-side code to safely collect payment methods and attach them to your customer accounts, and so on.
Collect Payment Info
Add the tier.js
browser client to every page on your site.
This loads Stripe asynchronously, which ensures that you benefit
from their bot detection magic.
<script src="https://app.tier.run/tier.js"></script>
Then, on the server, get a StripeOptions
object with the Tier
SDK:
const stripeOptions = await tier.stripeOptions(`org:${org_id}`);
And pass that to the front-end to load the payment entry form:
<form id="payment-form">
<div id="payment-element"></div>
<button type="submit">Submit</button>
<div id="payment-error"></div>
</form>
<script>
// use the Tier browser client to do the browser bits
Tier.paymentForm(<%- JSON.stringify(stripeOptions) %>, {
form: '#payment-form',
payment: '#payment-element',
error: '#payment-error',
})
</script>
Attaching Payment Method to Customer
When Stripe redirects them back to your site, finish the process
by calling tier.stripeSetup(org, setup_intent)
.
if (request.searchParams.has("setup_intent")) {
await tier.stripeSetup(`org:${org}`, searchParams.get("setup_intent"));
}
If this raises an error, you can show that to the user, or
redirect them to the er.redirect_to_url.url
if it's set.
(Usually this means that the user has to authorize something,
their card was denied, or some other problem.)
Beyond Quickstart Guides: Iterating on Pricing Plans
If you ever want to add a new plan, just edit the pricing.json
file to add a new version of a plan, and push it live.
Anyone on the old plans will keep on with their existing plan
unless you explicitly call tier.appendPhase()
at some point to
upgrade them to the new version. All the instrumentation in your
code can stay untouched.
Safe, zero-refactoring pricing iteration.
We're here to help
We want you to be successful with this!
Get in touch and let us know where you're getting stuck.
Or if you're not getting stuck, then just come brag about it.
You can also learn more by checking out the docs.