How to Implement Daisy Chain Filtering in Bubble.io?

Anish GandhiAnish Gandhi
10 min read

TL;DR

Daisy Chain Filtering in Bubble.io is a client-side filtering technique where each filter input (like dropdowns or checkboxes) updates a shared custom state. As users select options, each filter refines the results based on the previous ones - forming a seamless, chained filtering logic.

This method avoids heavy searches or backend workflows and enables fast, dynamic filtering - ideal for datasets under ~1,000 records. You’ll use conditional visibility, custom states, and custom events to build the logic.

What is Daisy Chain Filtering?

Daisy chain filtering is a technique where multiple filters are applied in a specific sequence, one after another, to progressively narrow down a list of results. Each filter takes the output of the previous step and applies an additional condition, creating a “chain” of filters.

In Bubble.io, this is typically done using repeated :filtered operations on a list, instead of filtering everything at once or using database constraints.

How to implement Daisy Chain Filtering in bubble.io?

I will guide you through a step-by-step process to implement Daisy Chain Filtering in bubble.io with an example given below.

Step 1: Create UI for filters

As you can see in the image above, I am using the following elements in bubble.io for filtering the data of the Repeating Group of products.

Step 2: Set custom states for each filter

For each filter, I am setting a custom state on the Page.

Step 3: Load all data in the Popup Hidden variable as base data

As you can see in the image, I am loading all the product data on the page

Step 4: Set the source of the repeating group on the page

Set the VAR RG ALL Products as the data source of the Repeating Group, where filtered results will be displayed.

Step 5: Set up 6 custom events for 5 filters

As you can see, I have numbered it 00 to 05.

  • 00 is for setting up base data

  • 01 to 05 for each custom event for each filter

Step 6: Set up a 00 custom event to load basic data in the Repeating Group

As you can see in the image, first, I am displaying base data in the Repeating group and triggering the 01 custom event

Step 7: Set up a 01 to 05 custom event to filter the Repeating Group data based on active filters

As you can see in the 00 Filter workflow, the 01 workflow is triggered in the end. Repeat this process for workflows 01 to 04.
So,

  • Custom ‘00 Filter’ workflow will trigger ‘01 Filter’ workflow

  • Custom ‘01 Filter’ workflow will trigger ‘02 Filter’ workflow

  • Custom ‘02 Filter’ workflow will trigger ‘03 Filter’ workflow

  • Custom ‘03 Filter’ workflow will trigger ‘04 Filter’ workflow

  • Custom ‘04 Filter’ workflow will trigger ‘05 Filter’ workflow

Now, as you can see in the image attached in step 5, I have assigned each custom event from 01 to 05 for each filter.

  • Custom ‘00 Filter’ workflow is base data loading custom event

  • Custom ‘01 Filter’ workflow is an Input filter custom event

  • Custom ‘02 Filter’ workflow is a price range filter custom event

  • Custom ‘03 Filter’ workflow is a brand filter custom event

  • Custom ‘04 Filter’ workflow is a category filter custom event

  • Custom ‘05 Filter’ workflow is a location filter custom event

On 01 to 05 custom events, before triggering the next event, use the action ‘Display data in Repeating Group’ with the condition that if the filter value is not empty, then run this action. Just as shown in the image below:

Step 8: Trigger 00 Custom event after every action of setting the custom state for filters

As you can see in the image below, I am adding a category in custom state when the user selects a category from the category dropdown. In the next action, I am triggering the 00 Custom event

Similarly, Trigger 00 custom event after all actions, whenever the value of the custom state for any filter changes.

And here your daisy chain filter is ready. Now, let’s understand how this will work

How this Daisy chain filter will be executed?

Let’s understand this in a step-by-step flow chart manner:

  1. User selects a filter (e.g., Brand = Nike)

  2. Custom state is updated (brand = "Nike")

  3. Trigger "00 Filter" → loads all products

  4. Triggers "01 Filter" (Input) → skips if empty

  5. Triggers "02 Filter" (Price) → skips if not set

  6. Triggers "03 Filter" (Brand) → filters by brand = "Nike"

  7. Triggers "04 Filter" (Category) → skips if not selected

  8. Triggers "05 Filter" (Location) → skips if not selected

  9. Final result shown in the Repeating Group Products

❓ Frequently Asked Questions

Q1: Your "Daisy Chain" method feels very fast once the data is loaded. But what happens when my database grows from 200 products to over 10,000? Is this client-side method still the best choice?

This is a crucial question for any growing application. The Daisy Chain method is exceptionally fast for user interactions after the initial data is loaded. However, its scalability is limited.

  • For Small Datasets (< 500 items): This method is excellent. The initial load time in Step 3 is negligible, and the instant filtering provides a fantastic user experience.

  • For Large Datasets (> 1,000 items): The initial step of loading all items into a custom state becomes a major performance bottleneck. A user might have to wait a long time for 10,000+ items to download to their browser, and on lower-powered devices, this could even crash the browser page.

My Recommendation:

  • For large datasets, you must switch to server-side filtering. This means your Repeating Group's data source should be Do a search for Products, with the constraints dynamically referencing your filter inputs (e.g., Brand = Dropdown Brand's value). Use the "Ignore empty constraints" feature to build a single, powerful search query that only downloads the exact data needed from the server.

  • When your filtering logic is too complex for standard server-side constraints, you should use the hybrid approach. Here is an example:

    • Filtering Based on a Calculation: This is the most common use case. You want to filter based on a value that is calculated from two or more fields on the same data entry.

      • Example: You have a Product with regular_price and a sale_price. You want to show only products that are "more than 20% off." The required filter logic is sale_price < regular_price * 0.8. You cannot perform this calculation within a Do a search for... constraint.

      • Hybrid Solution: First, do a server-side search for all products in the relevant category (e.g., Category = "Shoes"). Then, apply a client-side :filtered with a Advanced: condition: This Product's sale_price < This Product's regular_price * 0.8.

  • Here is the golden rule for filtering in Bubble for Large Datasets:

    Filter as much as possible, as early as possible, on the server.

    Use the standard constraints in your Do a search for... to do all the heavy lifting. Get the dataset as small as you possibly can before it ever leaves the database.

    Only use the hybrid approach as a final step to perform a specific calculation or logical check that is impossible to do on the server. It is a powerful tool for complex situations, but relying on it for simple filters is an anti-pattern that will lead to performance issues as your app scales.

Q2: This article mentions saving Workload Units (WU) by avoiding multiple "Do a search for" calls. How does the WU cost of this method compare to a single, optimized server-side search?

You're right that this method cleverly avoids the high WU cost of running multiple separate searches and merging them. However, it's a trade-off. Let's compare:

  1. Daisy Chain Method: The main WU cost is in Step 3: Load all data. Loading a table with X number of items, even with minimal fields, can consume a significant amount of WU in a single burst. After that, all the :filtered Operations are free as they happen on the client.

  2. Server-Side Method: A Do a search for... with several constraints is extremely efficient. The WU cost is proportional to the final number of results returned, not the total size of the database table.

My recommendation:

  • For small to medium Datasets, this method is likely more WU-efficient.

  • For large tables, a single, well-constrained server-side search is almost always more WU-efficient and infinitely more performant because the cost is based on the small, filtered result set, not the entire database table.

Q3: Are there any security implications of loading all product data into a custom state on page load, as shown in Step 3?

Yes, and this is the most critical consideration. Any data loaded onto the page - even if held in a hidden variable or custom state - is fully accessible to a savvy user via their browser's developer tools.

Imagine your Product data type also has fields like cost_price or internal_notes. Even if you don't display these fields in the repeating group, by loading the "full list of Products" to the client, you are sending that sensitive data to every user.

Rule of Thumb: Never use client-side filtering for data that isn't 100% public. The only way to truly secure data is to use Bubble's Privacy Rules to define what data a user is allowed to see and server-side search constraints to ensure only that permitted data is ever sent from the database.

Q4: When Does Daisy Chain Filtering Make Sense in Bubble.io?

I want to get ahead of a common (and valid) reaction:

“Why not just use a single Do a search for with ignore empty constraints?”
So here’s a breakdown of when I think Daisy Chain Filtering (DCF) is a useful tool and when it’s not.

❌ When Not to Use Daisy Chain Filtering

Daisy chaining is a client-side pattern, which means:

  • All data is loaded into the browser first (:filtered is evaluated client-side)

  • Filters apply after page load, meaning initial data transfer can be large

  • It exposes all fields (not protected by privacy rules) of all loaded records, which could risk data leaks

  • It doesn’t scale well for large datasets (>1,000 records, depending on complexity)

  • It increases initial memory usage and may freeze or crash low-resource devices

So if you're working with:

  • Dynamic but searchable constraints (e.g. text contains, category is, status is not)

  • Data that can safely be retrieved directly from the server

  • A need for server-side filtering or pagination

👉 Then, yes - a standard Do a search for with "Ignore empty constraints" is the best and most scalable choice. No argument there.

✅ When Daisy Chain Filtering Can Be the Better Option

That said, DCF isn’t a mistake - it’s a targeted tradeoff. It works best when:

  • You have a bounded dataset (~<1,000 records) that is safe to load into the browser

  • You want ultra-fast interactions, especially when filters are toggled in rapid succession

  • You need complex filter logic that Bubble can’t express server-side
    e.g.,

    • Filters that involve computed fields (like discounts or margin %)

    • Nested field matching, where native Bubble search is limited

    • Dynamic comparison logic (e.g., user-defined operators like “merged with”, “contains”)

  • You're building a “multi-step” filter UX with visible stages, where each filter step refines the next (hence the chain)

These are areas where chaining filters through custom states and conditional events gives you granular control and better perceived performance, as long as you’re aware of the memory and security costs.

Final Thought

I’m not claiming DCF is better than server-side filtering - I’m saying it’s different.
Used intentionally, it's a specialized tool, not a default pattern.

And the article I wrote here breaks down where the tipping point lies - when DCF becomes faster, and when it becomes dangerous.

0
Subscribe to my newsletter

Read articles from Anish Gandhi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Anish Gandhi
Anish Gandhi

✔️ Certified Bubble.io Developer with 2+ Years of experience in creating scalable responsive web applications. ✔️ Top Rated Plus Upwork Freelancer ✔️ Canvas framework expert