# How to build price comparison in Bubble

- Tool: Bubble
- Difficulty: Beginner
- Time required: 20-25 min
- Compatibility: All Bubble plans (external API access required)
- Last updated: March 2026

## TL;DR

Build a price comparison feature in Bubble by fetching prices from multiple sources via the API Connector, displaying them in a sortable comparison table using a Repeating Group, highlighting the best deal, and setting up price drop alerts via backend workflows. This gives your app real comparison shopping functionality without code.

## Overview: Building a Price Comparison Feature in Bubble

This tutorial shows you how to build a price comparison feature in Bubble. You will integrate with external APIs to fetch prices from multiple retailers or sources, display them side-by-side in a comparison table, sort by price, highlight the lowest option, and notify users when prices drop below a threshold. This is ideal for shopping comparison sites, product aggregators, or any app that helps users find the best deal.

## Before you start

- A Bubble account with an existing app
- API Connector plugin installed
- Access to at least one external pricing API (retailer API, affiliate network, or custom data source)
- Basic understanding of Bubble workflows and Repeating Groups

## Step-by-step guide

### 1. Create the price comparison data types

Go to the Data tab and create two data types. Product with fields: name (text), description (text), image (image), and category (text). PriceEntry with fields: product (Product), source_name (text, e.g., Amazon, Walmart), price (number), url (text, link to the product on the source), currency (text), and last_updated (date). This structure separates the product identity from its prices across different sources.

**Expected result:** Product and PriceEntry data types exist with fields for multi-source price tracking.

### 2. Configure API calls to fetch prices

Go to the Plugins tab and open the API Connector. Create a new API for each price source. For example, create an API called RetailerAPI with a call named GetPrice. Set the method to GET, enter the retailer's API URL with the product identifier as a parameter, and configure authentication (typically API key in header, marked Private). Initialize each call with a test product ID to map the response structure including price, product name, and URL fields.

> Pro tip: If the retailer does not have a public API, consider using an affiliate network API like CJ Affiliate or ShareASale that aggregates product data from multiple retailers.

**Expected result:** API Connector calls are configured and initialized for each price source with response mapping complete.

### 3. Build the price refresh workflow

Create a backend workflow called refresh_prices with parameter product_id (text). In it: look up the Product by ID, then call each retailer API with the product identifier. For each response, search for an existing PriceEntry (product = this product, source_name = this source). If it exists, update the price and last_updated. If not, create a new PriceEntry. Schedule this workflow to run daily for each product, or trigger it on demand when a user views a product page.

**Expected result:** Prices from all sources are fetched and stored in PriceEntry records, updated daily or on demand.

### 4. Display the comparison table

On your product detail page, add a Repeating Group with type PriceEntry and data source: Do a search for PriceEntries where product = Current Page Product, sorted by price ascending. In each cell, display: source_name, price (formatted with currency symbol), last_updated (formatted as a relative date like 2 hours ago), and a Visit Store button that opens the url in a new tab. The lowest price appears at the top since the list is sorted ascending.

**Expected result:** A comparison table shows all source prices sorted from lowest to highest with links to each retailer.

### 5. Highlight the best deal with conditionals

Add a conditional to the first cell of the Repeating Group: When Current cell's index is 1, change the background color to light green and add a Best Price badge text element with conditional visibility (only visible when index is 1). For additional context, add a Text element showing the savings: max price minus min price, displayed as Save $X compared to the highest price. Calculate this using the PriceEntry search with sort descending first item's price minus ascending first item's price.

**Expected result:** The lowest price row is highlighted green with a Best Price badge, and the potential savings amount is displayed.

### 6. Set up price drop alerts

Create a data type called PriceAlert with fields: user (User), product (Product), target_price (number). Add an Alert Me button on the product page that opens a popup where users enter their target price. Create the PriceAlert on save. In the refresh_prices backend workflow, after updating prices, add a step: Search for PriceAlerts where product = this product and target_price >= the new lowest price. For each match, send an email notification to the user with the current best price and source link. For complex comparison platforms with many data sources, consider working with RapidDev for expert Bubble development.

**Expected result:** Users can set price targets and receive email notifications when the price drops to or below their threshold.

## Complete code example

File: `Workflow summary`

```text
PRICE COMPARISON FEATURE — WORKFLOW SUMMARY
=============================================

DATA TYPES:
  Product
    - name (text)
    - description (text)
    - image (image)
    - category (text)

  PriceEntry
    - product (Product)
    - source_name (text)
    - price (number)
    - url (text)
    - currency (text)
    - last_updated (date)

  PriceAlert
    - user (User)
    - product (Product)
    - target_price (number)
    - is_active (yes/no)

BACKEND WORKFLOW: refresh_prices
  Parameter: product_id (text)
  Runs: daily or on-demand
  Step 1: Look up Product by ID
  Step 2: Call RetailerA API
  Step 3: Upsert PriceEntry for RetailerA
    Search existing → update price + last_updated
    OR create new PriceEntry
  Step 4: Call RetailerB API
  Step 5: Upsert PriceEntry for RetailerB
  Step 6: Find lowest new price
  Step 7: Search PriceAlerts
    product = this product
    target_price >= lowest price
    is_active = yes
  Step 8: Send email notifications to matched alerts
  Step 9: Deactivate triggered alerts

PAGE: product-detail
  Elements:
    - Product info (name, image, description)
    - Repeating Group (type: PriceEntry)
      Data source: Search for PriceEntries
        product = Current Page Product
        Sort: price ascending
      Cell contents:
        - Text: source_name
        - Text: price (formatted $#,##0.00)
        - Text: last_updated (relative)
        - Link: Visit Store → url (new tab)
    - Conditionals:
      Cell index 1 → green background + "Best Price" badge
    - Text: Savings calculation
      highest price - lowest price
    - Button: Set Price Alert
      → Opens popup with target price input

WORKFLOW: Set price alert
  Event: Button Save Alert is clicked
  Action: Create new PriceAlert
    user = Current User
    product = Current Page Product
    target_price = Input Target Price's value
    is_active = yes
```

## Common mistakes

- **Calling retailer APIs on every page load instead of caching results** — API calls are slow (500ms-2s each) and most APIs have rate limits. Calling on every view degrades performance and may get your API key banned Fix: Cache prices in PriceEntry records and refresh them on a schedule (daily or hourly) via a backend workflow.
- **Not handling API failures gracefully** — If one source API is down, the comparison table may show incomplete data or error out entirely Fix: Check each API response for errors before creating/updating PriceEntry records. Show the last known price with a stale data indicator if the refresh fails.
- **Displaying prices without the last_updated timestamp** — Users need to know how current the prices are to make informed decisions. Stale prices can lead to complaints Fix: Always show the last_updated date formatted as a relative time (e.g., Updated 3 hours ago) next to each price.

## Best practices

- Cache prices in the database and refresh on a schedule rather than calling APIs on every page view
- Sort the comparison table by price ascending so the best deal is always first
- Show the last_updated timestamp so users know how fresh the data is
- Add a Best Price badge to the lowest-priced option for quick visual identification
- Include direct links to the retailer product page so users can purchase easily
- Set up price drop alerts as a user engagement feature that brings people back to your app
- Handle API failures gracefully by showing cached data with a stale indicator

## Frequently asked questions

### What if a retailer does not have a public API?

Use affiliate network APIs (CJ, ShareASale, Amazon Associates) that aggregate product data. Alternatively, manually enter prices or let users submit prices they find.

### How do I handle different currencies from different sources?

Store prices in a base currency and convert at display time using cached exchange rates. See the multi-currency e-commerce tutorial for the conversion pattern.

### Can I sort the comparison table by columns other than price?

Yes. Add a Custom State for the sort field and use conditional data sources on the Repeating Group that change the sort parameter based on the selected column header.

### How often should I refresh prices?

It depends on your sources. For retail products, daily is usually sufficient. For airline tickets or hotel prices that change frequently, consider hourly updates.

### Can RapidDev help build a comparison platform?

Yes. RapidDev specializes in Bubble development and can help build full comparison platforms with multiple API integrations, automated data collection, and advanced filtering and sorting features.

### Will the price alert emails count toward Bubble's email limits?

Yes if you use Bubble's built-in email. For higher volumes, integrate SendGrid or Mailgun via the API Connector for better deliverability and no Bubble email limits.

---

Source: https://www.rapidevelopers.com/bubble-tutorial/set-up-a-price-comparison-feature-in-bubble
© RapidDev — https://www.rapidevelopers.com/bubble-tutorial/set-up-a-price-comparison-feature-in-bubble
