# How to build a membership site in Bubble

- Tool: Bubble
- Difficulty: Beginner
- Time required: 30-40 min
- Compatibility: All Bubble plans (Stripe required for payments)
- Last updated: March 2026

## TL;DR

Build a membership site in Bubble with free and paid tiers, Stripe-powered subscriptions, gated content pages, and member-only areas. This tutorial covers the data architecture for membership levels, Stripe Checkout integration for recurring payments, content access rules using conditionals and privacy rules, and a member dashboard.

## Overview: Membership Sites in Bubble

A membership site gates content behind subscription tiers — free users see limited content while paying members access premium material. This tutorial builds the complete membership infrastructure including tier management, Stripe billing, content access rules, and a member portal.

## Before you start

- A Bubble account with user authentication
- A Stripe account (test mode works for development)
- The Stripe plugin installed in Bubble
- Content ready to gate behind membership tiers

## Step-by-step guide

### 1. Design the membership data model

Create a 'MembershipTier' Option Set with options: Free, Basic ($9/mo), Premium ($29/mo). Add attributes: price (number), stripe_price_id (text — from Stripe dashboard), features (text — comma-separated feature list). On the User data type, add fields: membership_tier (MembershipTier, default: Free), stripe_customer_id (text), subscription_active (yes/no, default: no), subscription_end_date (date).

**Expected result:** Membership tiers and user subscription fields are set up.

### 2. Set up Stripe products and prices

In your Stripe dashboard, create Products for each paid tier (Basic, Premium). Add a recurring Price to each product matching your pricing. Copy each Price ID (starts with price_). Paste these into the stripe_price_id attribute on your MembershipTier Option Set. Install the Stripe plugin in Bubble and configure it with your Stripe publishable and secret keys.

**Expected result:** Stripe products and prices are created and linked to your Bubble membership tiers.

### 3. Build the pricing page with Stripe Checkout

Create a 'pricing' page displaying all tiers in a Row container. For each tier, show the name, price, features list, and a 'Subscribe' button. The Subscribe button workflow: Create a Stripe Checkout Session (via API Connector or Stripe plugin) with the tier's stripe_price_id, success_url = your success page, cancel_url = pricing page. Redirect the user to the Checkout Session URL.

**Expected result:** Users can select a tier and are redirected to Stripe Checkout to enter payment details.

### 4. Handle successful payment with webhooks

Create a backend workflow called 'stripe-webhook' that accepts Stripe webhook events. In the Stripe dashboard, add a webhook endpoint pointing to your Bubble API URL. Listen for checkout.session.completed events. When received: find the User by Stripe customer ID, update their membership_tier, set subscription_active = yes, and set subscription_end_date.

> Pro tip: Always use webhooks rather than redirect-page logic to confirm payments — redirects can fail but webhooks are reliable.

**Expected result:** Successful payments automatically upgrade the user's membership tier.

### 5. Gate content based on membership level

On content pages, add conditionals that check the user's tier. For a premium article page: When Current User's membership_tier is Free → hide the content Group, show a 'Subscribe to read' message. Add privacy rules on content Data Types: only return premium content in searches when the user's tier matches. This double-gating (frontend conditional + backend privacy rule) ensures content is truly protected.

**Expected result:** Free users see teaser content with upgrade prompts. Paid members see full content.

### 6. Build the member dashboard

Create a 'member-dashboard' page showing: current tier and subscription status, next billing date, a list of accessible content, and account settings. Add a 'Manage Subscription' button that opens the Stripe Customer Portal (create a portal session via API Connector and redirect). The portal lets members upgrade, downgrade, or cancel.

**Expected result:** Members can view their subscription details and manage billing through Stripe's portal.

## Complete code example

File: `Workflow summary`

```text
MEMBERSHIP SITE — ARCHITECTURE SUMMARY
========================================

OPTION SET: MembershipTier
  Free (price: 0, stripe_price_id: none)
  Basic (price: 900, stripe_price_id: price_xxx)
  Premium (price: 2900, stripe_price_id: price_yyy)

USER FIELDS:
  membership_tier (MembershipTier, default: Free)
  stripe_customer_id (text)
  subscription_active (yes/no)
  subscription_end_date (date)

PAGES:
  pricing          — Tier comparison + Subscribe buttons
  checkout-success — Confirmation page after payment
  member-dashboard — Account, subscription, content access
  [content pages]  — Gated based on membership tier

WORKFLOWS:
  Subscribe: Create Stripe Checkout Session → redirect to Stripe
  Webhook: checkout.session.completed → update User tier
  Manage: Create Stripe Portal Session → redirect to portal
  Cancel: Stripe webhook subscription.deleted → set tier to Free

CONTENT GATING:
  Frontend: Conditional visibility based on membership_tier
  Backend: Privacy rules restrict content searches by tier

STRIPE WEBHOOKS:
  checkout.session.completed → activate subscription
  customer.subscription.updated → change tier
  customer.subscription.deleted → downgrade to Free
```

## Common mistakes

- **Using redirect page logic instead of webhooks to confirm payments** — Users can close the browser before reaching the success page, leaving their subscription unactivated Fix: Always use Stripe webhooks to update membership status — they fire reliably regardless of user behavior
- **Only gating content with frontend conditionals** — Frontend-only gating can be bypassed by viewing page source or calling the API directly Fix: Combine frontend conditionals with backend privacy rules that restrict database searches by tier
- **Not handling subscription cancellations** — Cancelled users keep premium access indefinitely if you do not listen for the cancellation webhook Fix: Listen for customer.subscription.deleted webhook and downgrade the user's tier to Free

## Best practices

- Use Stripe webhooks for all subscription state changes, not redirect-page logic
- Gate content with both frontend conditionals and backend privacy rules
- Store Stripe customer ID on the User record for webhook matching
- Use the Stripe Customer Portal for subscription management instead of building custom UI
- Show a content teaser to free users with an upgrade CTA for better conversion
- Handle all webhook events: completed, updated, deleted, past_due

## Frequently asked questions

### Can I offer a free trial?

Yes. In Stripe, add a trial period to your Price. The user is not charged until the trial ends. Handle the trial_end webhook to update the user's status.

### How do I handle failed payments?

Listen for the invoice.payment_failed Stripe webhook. Send the user an email asking them to update their payment method. After a grace period, downgrade their tier.

### Can I have more than three membership tiers?

Yes. Add as many options as needed to the MembershipTier Option Set. Create corresponding Stripe Products and Prices for each.

### How do I let users switch between tiers?

Use the Stripe Customer Portal which handles upgrades and downgrades automatically, including prorated billing.

### Is Stripe required or can I use PayPal?

Stripe is the most common choice for Bubble subscriptions. PayPal can work via API Connector but has less plugin support.

### Can RapidDev build a membership platform?

Yes. RapidDev builds membership platforms with subscription management, content gating, member portals, and analytics dashboards.

---

Source: https://www.rapidevelopers.com/bubble-tutorial/create-a-membership-site-in-bubble
© RapidDev — https://www.rapidevelopers.com/bubble-tutorial/create-a-membership-site-in-bubble
