Skip to main content
RapidDev - Software Development Agency
bubble-tutorial

How to Build an E-Commerce Filter System in Bubble

An e-commerce filter system in Bubble uses custom states to track user selections and combines them into a single search constraint on a product Repeating Group. This tutorial covers building checkbox category filters with product counts, a price range filter with min and max inputs, visual color and size selectors, combining all active filters into one efficient database query using Ignore empty constraints, and displaying removable filter tags above the results grid.

What you'll learn

  • How to build checkbox-based category filters with product counts
  • How to implement price range filtering with min and max inputs
  • How to combine multiple filter types into one efficient search query
  • How to display active filter tags with individual clear and clear-all options
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner10 min read25-35 minAll Bubble plansMarch 2026RapidDev Engineering Team
TL;DR

An e-commerce filter system in Bubble uses custom states to track user selections and combines them into a single search constraint on a product Repeating Group. This tutorial covers building checkbox category filters with product counts, a price range filter with min and max inputs, visual color and size selectors, combining all active filters into one efficient database query using Ignore empty constraints, and displaying removable filter tags above the results grid.

Overview: Building an E-Commerce Filter System in Bubble

Product filtering is essential for any e-commerce app with more than a handful of items. This tutorial builds a professional multi-facet filter sidebar that lets shoppers narrow products by category, price range, color, and size -- all updating a single Repeating Group in real time. It is designed for non-technical founders building product catalogs, marketplaces, or directory apps in Bubble.

Prerequisites

  • A Bubble app with a Product Data Type containing fields for name, price, category, color, and size
  • At least 10-20 sample products in the database for testing filters
  • Basic understanding of custom states and how they store temporary values
  • Familiarity with Repeating Groups and search constraints

Step-by-step guide

1

Set up the page layout and custom states for filters

Create a new page called 'shop'. Add a Group element on the left side (250-300px wide) as the filter sidebar. Add a larger Group on the right for the product grid. On the page itself, create these custom states: selected_categories (type: list of texts), min_price (type: number), max_price (type: number), selected_colors (type: list of texts), selected_sizes (type: list of texts). These states will hold the user's current filter selections and drive the product search. At the top of the sidebar, add a 'Clear All Filters' button. Its workflow will reset every custom state to empty. Inside the sidebar, create four collapsible Group sections with headings: Categories, Price Range, Colors, and Sizes.

Expected result: A two-column page layout with a filter sidebar containing four sections and five custom states ready to track user selections.

2

Build the checkbox category filters with product counts

Create an Option Set called ProductCategory with options matching your catalog (e.g., Electronics, Clothing, Home, Sports). Inside the Categories section, add a Repeating Group with type ProductCategory and data source: All ProductCategories. In each cell, place a Checkbox element and a Text element showing the option's Display value. Next to it, add another Text element displaying the count: Do a search for Product where category = Current cell's ProductCategory :count. This shows users how many products each category contains. Add a workflow on the Checkbox element: When Checkbox value changes and is checked, set state selected_categories to selected_categories plus item Current cell's ProductCategory's Display. When unchecked, set state selected_categories to selected_categories minus item Current cell's ProductCategory's Display.

Pro tip: Use an Option Set for categories instead of a Data Type. Option Sets load instantly without a database query, making your filter sidebar snappy even with many categories.

Expected result: Checking or unchecking a category immediately updates the selected_categories custom state, and each category shows a product count.

3

Add the price range filter

Inside the Price Range section, add two Input elements side by side: one labeled 'Min' and one labeled 'Max'. Set both content formats to Integer. Below the inputs, add a Text element showing the current range: 'Showing products from $Min to $Max'. Add two workflows. Workflow 1: When Min input's value changes, set state min_price to Min input's value. Workflow 2: When Max input's value changes, set state max_price to Max input's value. If you want a more visual control, install a Range Slider plugin from the Bubble Plugin Marketplace and configure it with min = 0, max = your highest product price, and two handles. Map each handle to the corresponding custom state.

Expected result: Entering or adjusting min and max price values updates the custom states, which will feed into the product search query.

4

Create visual color and size selectors

Create an Option Set called ProductColor with options like Red, Blue, Black, White. Add an attribute called hex_code (text) to store the color value (e.g., #FF0000 for Red). Inside the Colors section, add a Repeating Group of ProductColor options laid out as a grid (3-4 columns, fixed cell size of 40x40px). Style each cell as a circle with the background color set to Current cell's ProductColor's hex_code. Add a conditional: when Current cell's ProductColor's Display is in selected_colors, show a white checkmark icon overlay. Workflow on cell click: if the color is in selected_colors, remove it; if not, add it. For Sizes, create a ProductSize Option Set (XS, S, M, L, XL). Display as a row of rectangular buttons. Use the same toggle pattern: click adds or removes the size from selected_sizes, and a conditional changes the button style when selected.

Expected result: Colored circles and size buttons toggle on and off visually, updating their respective custom states with each click.

5

Combine all filters into one product search

Select the product grid Repeating Group on the right side of the page. Set its Type of content to Product. Set the data source to: Do a search for Product with these constraints: category is in This page's selected_categories, price >= This page's min_price, price <= This page's max_price, color is in This page's selected_colors, size is in This page's selected_sizes. Critically, check the 'Ignore empty constraints' checkbox. This means when a filter state is empty (no categories selected, no min price entered, etc.), that constraint is ignored and all products pass through. The result is that only active filters restrict the results. Above the Repeating Group, add a Text element showing the result count: 'Showing X products' where X is the Repeating Group's List of Products :count.

Pro tip: The Ignore empty constraints option is the key to making multi-facet filtering work in Bubble. Without it, an empty list constraint would return zero results instead of all results.

Expected result: The product grid updates in real time as users check categories, adjust price, or select colors and sizes. Only active filters restrict the results.

6

Display active filter tags with remove and clear-all functionality

Above the product grid and below the result count, add a horizontal Repeating Group to show active filter tags. Create a custom state called active_filter_tags (list of texts) on the page. Whenever a filter state changes, rebuild this list by combining all non-empty filter values into readable tags (e.g., 'Category: Electronics', 'Min price: $50', 'Color: Red', 'Size: M'). In each tag cell, display the tag text and an X icon button. The X button workflow: parse the tag type and remove the corresponding value from its custom state (e.g., remove 'Electronics' from selected_categories). Wire up the 'Clear All Filters' button at the top of the sidebar to reset all five custom states to empty and clear the active_filter_tags list. For a polished experience, add RapidDev-style smooth transitions: set the product Repeating Group to animate when its data source changes.

Expected result: Active filters appear as removable tag chips above the product grid. Clicking X on a tag removes that specific filter. Clear All resets everything.

Complete working example

Workflow summary
1E-COMMERCE FILTER SYSTEM FULL ARCHITECTURE
2===============================================
3
4OPTION SETS:
5 ProductCategory: Electronics, Clothing, Home, Sports, ...
6 ProductColor: Red (#FF0000), Blue (#0000FF), Black (#000),
7 White (#FFF), Green (#00FF00), ...
8 ProductSize: XS, S, M, L, XL
9
10CUSTOM STATES (on page 'shop'):
11 selected_categories list of texts
12 min_price number
13 max_price number
14 selected_colors list of texts
15 selected_sizes list of texts
16 active_filter_tags list of texts
17
18FILTER SIDEBAR (left column, 250-300px):
19 Clear All Filters button
20 Reset all 5 filter states to empty
21
22 Section: Categories
23 RG of ProductCategory Option Set
24 Each cell: Checkbox + category name + product count
25 Checked add to selected_categories
26 Unchecked remove from selected_categories
27
28 Section: Price Range
29 Min Input + Max Input (integer format)
30 Value changes update min_price / max_price states
31 Display: "$min — $max"
32
33 Section: Colors
34 RG grid of ProductColor Option Set (40x40 circles)
35 Background: hex_code attribute
36 Click toggle in/out of selected_colors
37 Selected state: white checkmark overlay
38
39 Section: Sizes
40 Row of ProductSize buttons
41 Click toggle in/out of selected_sizes
42 Selected state: filled background
43
44PRODUCT GRID (right column):
45 Data source: Do a search for Product
46 category is in selected_categories
47 price >= min_price
48 price <= max_price
49 color is in selected_colors
50 size is in selected_sizes
51 Ignore empty constraints = YES
52 Sorted by: price ascending (or user choice)
53 Items per page: 12-20
54
55ACTIVE FILTER TAGS (above grid):
56 Horizontal RG of active_filter_tags
57 Each cell: tag text + X remove button
58 X button remove value from matching state
59
60RESULT COUNT:
61 Text: "Showing X products"
62 X = Product RG's list :count

Common mistakes when building an E-Commerce Filter System in Bubble

Why it's a problem: Using :filtered on the client instead of database search constraints

How to avoid: Always place filter logic inside the Do a search for Product constraints so filtering happens on the server before data is sent to the browser

Why it's a problem: Forgetting to enable Ignore empty constraints on the product search

How to avoid: Check the Ignore empty constraints checkbox on the search so unselected filter groups do not restrict the results

Why it's a problem: Recalculating product counts on every single filter change

How to avoid: Show static counts based on the full catalog, or only update counts for one filter group when a related filter changes

Why it's a problem: Not handling products that have multiple colors or sizes

How to avoid: Use list fields (colors: list of texts, sizes: list of texts) on Product and use the 'contains' constraint in the search to match any value in the list

Best practices

  • Use Do a search for with server-side constraints and Ignore empty constraints instead of client-side :filtered for fast performance
  • Show product counts next to each filter option so users can see how many results each choice produces before clicking
  • Display active filters as removable tag chips above the results so users always know which filters are applied
  • Provide a Clear All button at the top of the sidebar for a one-click reset of every filter
  • Use Option Sets for categories, colors, and sizes so filter values load instantly without a database lookup
  • Paginate the product grid to 12-20 items per page to keep the page responsive even with large catalogs
  • Store filter state in URL parameters so users can bookmark or share a filtered view with others
  • Add a sort dropdown (price low to high, newest, popularity) alongside the filters for a complete shopping experience

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I want to build a product filter system in my Bubble.io e-commerce app with checkbox category filters showing product counts, a price range with min and max inputs, visual color circle selectors, and size buttons. All filters should combine into one efficient search and display removable filter tags. Design the data model and outline every workflow.

Bubble Prompt

Build a product filter system for my e-commerce page. Create an Option Set for categories, colors (with hex_code attribute), and sizes. Add a filter sidebar with checkboxes for categories, min/max price inputs, color circles, and size buttons. Combine all filters into a single Do a search for Product with Ignore empty constraints. Show active filter tags above the product grid with remove buttons.

Frequently asked questions

How many filter categories can I add before performance suffers?

There is no hard limit in Bubble. However, more than six or seven filter groups tend to overwhelm users. Focus on the attributes that matter most for your product type and consider collapsing less-used filters behind a Show More toggle.

Can I save filter selections so users can return to them later?

Yes. Store the custom state values in URL parameters using Bubble's Go to page action with query strings. Users can bookmark the URL or share it. For logged-in users, you can also create a SavedFilter Data Type.

Does changing a filter cause a full page reload?

No. Custom states update instantly on the client, and the Repeating Group's data source re-evaluates automatically. The product grid refreshes without a page reload, typically in 100-500ms.

Can I add a star rating filter?

Yes. Add a rating field (number) to your Product Data Type and a Minimum Rating dropdown or star selector to the sidebar. Include rating >= selected_rating as an additional search constraint on the product query.

How do I handle products that come in multiple colors?

Use a list of texts field for colors on the Product Data Type. In the search constraint, use the contains operator to check if the product's color list contains any of the selected colors.

Can RapidDev help build an advanced filtering system?

Yes. RapidDev builds production-grade filter systems in Bubble including faceted search with dynamic counts, URL-based filter persistence, sort controls, and responsive mobile filter drawers.

Should I show zero-result categories or hide them?

Best practice is to show them but gray them out with the count displayed as zero. This tells users the category exists but has no matching products given the other active filters, which is more informative than hiding the option entirely.

Can I add a text search alongside the facet filters?

Yes. Add a Search Input above the product grid and include a name contains Search Input's value constraint on the product search. It combines naturally with the other filter constraints.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.