Plan Management
This guide covers everything you need to know about implementing and managing membership plans with Memberstack. All paid plans are processed through Stripe, ensuring secure and reliable payments.
Before You Start
Create and configure your plans in the Memberstack dashboard under "Plans" before implementing them in your code. Important:
- Free plans use Plan IDs (starts with "pln_")
- Paid plans use Price IDs (starts with "prc_")
- Connect your Stripe account for paid plans
- Create plans in the dashboard (Plans → New Plan)
Testing Your Plans
To test your plans without real charges:
- Enable test mode in your Memberstack DevTools, then copy your public key (it starts with "pk_sb_").
- Test mode has its own set of Plan IDs and Price IDs - make sure to use the correct ones
- Use Stripe's test card: 4242 4242 4242 4242 (exp: any future date, CVC: any 3 digits)
- Remember to switch back to live mode and update IDs for production
Free Plans
Free plans are a great way to offer basic access to your platform or provide a trial experience. They can be implemented without Stripe integration.
Fetching Available Plans
First, let's see how to retrieve all available plans:
// Get available plans
async function getAvailablePlans() {
try {
return await memberstack.getPlans();
} catch (error) {
console.error("Couldn't get plans:", error);
return [];
}
}Fetching a Single Plan
Use getPlan() to look up one plan by its ID. This is a public read — no login
required. It resolves to { data: plan }, and throws plan-not-found if the ID doesn't exist.
// Get details for one specific plan by ID
async function getPlanDetails(planId) {
try {
const { data: plan } = await memberstack.getPlan({ planId });
console.log("Plan name:", plan.name);
console.log("Description:", plan.description);
// Paid plans include a prices array; free plans have an empty array
plan.prices?.forEach((price) => {
console.log(`Price ${price.id}: ${price.amount} ${price.currency}`);
});
return plan;
} catch (error) {
// Throws "plan-not-found" if the planId doesn't exist
console.error("Couldn't get plan:", error.message);
return null;
}
}Adding a Free Plan
Here's how to create a free plan signup button and handle enrollment:
// Add this HTML
<button onclick="startFreePlan()">Get Free Plan</button>
// Add this JavaScript
async function startFreePlan() {
try {
// Get the current member
const member = await memberstack.getCurrentMember();
if (!member) {
// Not logged in - show signup with free plan
await memberstack.openModal("SIGNUP", {
signup: { plans: ["YOUR_FREE_PLAN_ID"] }
});
} else {
// Logged in - add free plan
await memberstack.addPlan({
planId: "YOUR_FREE_PLAN_ID"
});
// Go to dashboard after success
window.location.href = "/dashboard";
}
} catch (error) {
alert("Couldn't add free plan. Please try again.");
}
}Free Plan Tips
- Make sure to clearly list what's included in the free plan
- Consider adding a trial of paid features to free plans
- Show comparison tables to encourage upgrades
- Test the signup flow both logged in and logged out
Paid Plans
Paid plans use Stripe for secure payment processing. Before implementing paid plans, make sure you've connected Stripe in your Memberstack dashboard and created your plans.
You can read more about the Stripe Customer Portal configuration here.
Adding a Paid Plan
Here's how to create a paid plan button and handle Stripe checkout:
// Add this HTML
<button onclick="startPaidPlan()">Get Pro Plan</button>
// Add this JavaScript
async function startPaidPlan() {
try {
const member = await memberstack.getCurrentMember();
if (!member) {
// Not logged in - show signup
await memberstack.openModal("SIGNUP", {
priceId: "prc_YOUR_PRICE_ID"
});
} else {
// Start checkout. autoRedirect defaults to true (the SDK navigates to
// Stripe for you); pass autoRedirect: false to get the URL back instead.
const checkout = await memberstack.purchasePlansWithCheckout({
priceId: "prc_YOUR_PRICE_ID",
successUrl: window.location.origin + "/dashboard",
cancelUrl: window.location.origin + "/plans",
autoRedirect: false
});
// Go to checkout — the URL is at checkout.data.url
window.location.href = checkout.data.url;
}
} catch (error) {
alert("Couldn't start checkout. Please try again.");
}
}Required Setup
- Connected Stripe account
- Plans created in dashboard
- Test mode for development
- Plan IDs copied and ready
Plan Settings
- Set prices and billing cycles
- Define included features
- Configure trial periods
- Set member limits if needed
Plan Purchase Flow
Here's how to handle common plan management tasks like checking access, upgrades, and letting members manage their subscriptions:
// Check if member has a specific plan
async function hasPlan(planId) {
const member = await memberstack.getCurrentMember();
if (!member) return false;
return member.planConnections?.some(plan =>
plan.planId === planId &&
plan.status === "ACTIVE"
);
}
// Open billing portal for subscription management
async function openBilling() {
try {
const { data } = await memberstack.launchStripeCustomerPortal({
returnUrl: window.location.origin + "/account"
});
window.location.href = data.url;
} catch (error) {
alert("Couldn't open billing. Please try again.");
}
}Removing a Plan
Use removePlan() to remove a plan from the logged-in member. For a paid plan
this cancels the subscription. The call resolves to { data: { member } } with the member's updated planConnections, and Memberstack refreshes the persisted session for you
(your onAuthChange listeners fire) — so you don't need to re-fetch the member.
// Remove a plan from the current member.
// For a paid plan this cancels the subscription.
async function dropPlan(planId) {
try {
const { data } = await memberstack.removePlan({ planId });
// The SDK returns the UPDATED member and refreshes the persisted
// session for you (onAuthChange fires) — no need to re-fetch.
console.log("Remaining plans:", data.member.planConnections);
return data.member;
} catch (error) {
// Throws if the member isn't logged in or doesn't have the plan
alert("Couldn't remove plan. Please try again.");
}
}Note: the member must be logged in, and the call throws if they don't
have the plan. To let members cancel or switch paid plans through Stripe's hosted UI
instead, use launchStripeCustomerPortal() (shown above).
Common Questions
What's the difference between Plan IDs and Price IDs?
Free plans use Plan IDs (starts with "pln_") while paid plans use Price IDs (starts with "prc_"). You can find both in your Memberstack dashboard under the respective plan settings.
Where do I find my plan/price IDs?
In your Memberstack dashboard: Plans → click on a plan → find the Plan ID for free plans or Price ID for paid plans in the settings
Where do I find my plan IDs?
In your Memberstack dashboard: Plans → click on a plan → copy the ID from the URL or settings
How do members change plans?
Use memberstack.launchStripeCustomerPortal() to let them manage their subscription
Can I offer a trial period?
Yes! Configure trial periods in your Memberstack dashboard when creating plans
Next Steps
Now that you've set up plan management, you might want to explore: