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

How to generate custom reports in Bubble.io: Step-by-Step Guide

Bubble lets you build custom reports by aggregating data with Search constraints and the :group by operator, displaying results in charts or repeating groups, and exporting to PDF or CSV. You can create dashboards that update in real time as your database changes, giving stakeholders the insights they need without any code.

What you'll learn

  • How to aggregate database records using Search constraints and the :group by operator
  • How to display report data in charts and repeating groups
  • How to add date range filters for dynamic reporting
  • How to export report data to CSV or PDF
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner9 min read20-25 minAll Bubble plansMarch 2026RapidDev Engineering Team
TL;DR

Bubble lets you build custom reports by aggregating data with Search constraints and the :group by operator, displaying results in charts or repeating groups, and exporting to PDF or CSV. You can create dashboards that update in real time as your database changes, giving stakeholders the insights they need without any code.

Build Dynamic Reports in Bubble Without Code

This tutorial shows you how to create custom reports that pull data from your Bubble database, aggregate it with filters and groupings, and display it visually using charts and tables. Whether you need sales summaries, user activity reports, or financial dashboards, you will learn how to build reports that non-technical team members can use. This guide is for Bubble builders who already have data in their app and want to create meaningful reports from it.

Prerequisites

  • A Bubble account with an existing app that has data in the database
  • Basic understanding of Bubble's Data Types and the Data tab
  • Familiarity with the Design tab and adding elements to a page
  • At least one Data Type with enough records to report on (e.g., Orders, Users, Transactions)

Step-by-step guide

1

Create a Reports Page and Add Date Range Filters

Go to your Bubble editor and create a new page called 'reports'. In the Design tab, add a Group container at the top of the page set to Row layout. Inside it, place two Date/Time Picker elements — name them 'DatePicker Start' and 'DatePicker End'. Set both to date-only mode (uncheck 'Include time'). Add a Button element labeled 'Generate Report' next to the date pickers. This filter bar will let users select a date range before generating their report.

Pro tip: Set default values on your date pickers — for example, 'Current date/time :rounded down to day +(days): -30' for the start and 'Current date/time' for the end — so users see the last 30 days by default.

Expected result: A reports page with a date range filter bar containing two date pickers and a Generate Report button.

2

Build a Summary Statistics Section with Aggregated Data

Below the filter bar, add a Group container set to Row layout. Inside it, add four smaller Groups — each will display a summary metric. In each group, add a Text element. For the first text, set its content to a dynamic expression: 'Do a Search for [YourDataType]:filtered:count'. Add constraints to the search matching your date range — for example, 'Created Date >= DatePicker Start's value' and 'Created Date <= DatePicker End's value'. For revenue, use ':each item's Amount:sum'. Repeat for other metrics like average order value (':each item's Amount:average') and unique customers (':unique elements:count').

Pro tip: Use Search constraints rather than :filtered whenever possible — constraints run server-side and are far more efficient. Only use :filtered for conditions that constraints cannot handle.

Expected result: Four summary cards showing total count, total revenue, average value, and unique customer count for the selected date range.

3

Add a Chart Element to Visualize Report Data

Install a chart plugin from the Bubble plugin marketplace — the 'Chart Element' plugin by Bubble or 'ApexCharts' are popular choices. Go to Plugins tab → '+ Add plugins' → search for your chosen chart plugin → Install. Return to the Design tab and drag a Chart element onto the page below the summary cards. Configure the chart's data source to 'Do a Search for [YourDataType]' with the same date constraints. Set the grouping to a date field (e.g., 'Created Date :formatted as MM/DD') for the X-axis and a numeric field (e.g., 'Amount') for the Y-axis values. Choose a chart type like Bar or Line.

Expected result: A visual chart showing your data aggregated over time within the selected date range.

4

Create a Detailed Data Table with a Repeating Group

Below the chart, add a Repeating Group element. Set its Type of content to your Data Type (e.g., Order). Set the Data source to 'Do a Search for [YourDataType]' with the same date range constraints. Choose a layout of 'Ext. vertical scrolling' with rows of fixed height. Inside the first cell, add Text elements for each column you want — map each to 'Current cell's [DataType]'s [field]'. For example: 'Current cell's Order's Customer's Name', 'Current cell's Order's Amount:formatted as currency', and 'Current cell's Order's Created Date:formatted as MM/DD/YYYY'.

Pro tip: Add a header row above the Repeating Group using a separate Group with text labels. This keeps column headers visible while the user scrolls through data.

Expected result: A scrollable table displaying individual records with all relevant fields for the selected date range.

5

Add CSV Export Functionality

To let users export report data, you have two approaches. The simpler method: go to the Data tab → App Data → select your Data Type → use the built-in CSV export. For an in-app solution, install a CSV export plugin (search 'CSV Creator' in the plugin marketplace). Add a Button labeled 'Export CSV' to your reports page. Create a workflow: When 'Export CSV' is clicked → use the plugin's action to generate a CSV from 'Do a Search for [YourDataType]' with the same constraints. Map the fields you want in each column. The plugin will trigger a file download in the user's browser.

Expected result: Clicking the Export CSV button downloads a CSV file containing all the filtered report data.

6

Add PDF Export for Printable Reports

For PDF export, install a PDF generation plugin such as 'PDF Conjurer' from the plugin marketplace. Configure it by adding the PDF Conjurer element to your page (it is invisible at runtime). Create a workflow on a 'Download PDF' button: use the plugin's actions to define the PDF layout — add text blocks for the title and date range, a table for the data rows, and optionally embed chart screenshots. Set the output filename dynamically (e.g., 'Report - ' merged with 'DatePicker Start's value:formatted as YYYY-MM-DD'). Trigger the PDF generation and download actions in sequence.

Pro tip: If you need a quick solution without a plugin, use the browser's built-in print dialog. Add a button that runs the 'Run JavaScript' action with 'window.print()' — users can then save as PDF from the print dialog.

Expected result: Clicking the Download PDF button generates and downloads a formatted PDF report.

Complete working example

Workflow summary
1PAGE: reports
2
3ELEMENTS:
4- Group FilterBar (Row layout)
5 - DatePicker Start (date only, default: Current date -30 days)
6 - DatePicker End (date only, default: Current date)
7 - Button "Generate Report"
8- Group SummaryCards (Row layout)
9 - Group Card1: Text = Search for Orders (date constrained):count
10 - Group Card2: Text = Search for Orders:each item's Amount:sum
11 - Group Card3: Text = Search for Orders:each item's Amount:average
12 - Group Card4: Text = Search for Orders:filtered (unique Customer):count
13- Chart Element
14 - Type: Bar chart
15 - Data source: Search for Orders (date constrained)
16 - X-axis: Created Date grouped by day
17 - Y-axis: Amount (sum)
18- Group DataTableHeader (Row layout)
19 - Text "Customer" | Text "Amount" | Text "Date" | Text "Status"
20- RepeatingGroup Orders (ext. vertical scroll, 15 rows/page)
21 - Data source: Search for Orders (date constrained, sorted by Created Date descending)
22 - Cell contents:
23 - Text: Current cell's Order's Customer's Name
24 - Text: Current cell's Order's Amount :formatted as $#,##0.00
25 - Text: Current cell's Order's Created Date :formatted as MM/DD/YYYY
26 - Text: Current cell's Order's Status
27- Button "Export CSV"
28- Button "Download PDF"
29
30WORKFLOWS:
311. When Button Generate Report is clicked
32 No action needed (elements auto-refresh with date picker values)
33 Optional: Set state on page to trigger loading animation
34
352. When Button Export CSV is clicked
36 CSV Creator: Create CSV from Search for Orders (date constrained)
37 Map columns: Customer Name, Amount, Date, Status
38 Trigger download
39
403. When Button Download PDF is clicked
41 PDF Conjurer: Add title "Sales Report"
42 Add date range text
43 Add table from Search for Orders
44 Generate and download PDF

Common mistakes when generating custom reports in Bubble.io: Step-by-Step Guide

Why it's a problem: Using :filtered instead of Search constraints for date ranges

How to avoid: Always add date constraints directly in the 'Do a Search for' dialog rather than filtering after the search.

Why it's a problem: Not paginating the Repeating Group for large datasets

How to avoid: Set the Repeating Group to show 15-25 rows with pagination controls, or use 'Ext. vertical scrolling' with a fixed number of rows.

Why it's a problem: Running nested searches inside Repeating Group cells

How to avoid: Pre-compute aggregated values and store them as fields on your Data Type, or use the :group by operator outside the Repeating Group.

Best practices

  • Use Search constraints over :filtered for all server-supported comparisons to reduce workload unit consumption.
  • Store commonly needed aggregations (totals, counts) as fields on parent records to avoid recalculating on every page load.
  • Set sensible default date ranges so users see meaningful data immediately without having to pick dates.
  • Add a loading indicator while report data loads — use a custom state 'is_loading' toggled by the Generate Report workflow.
  • Limit Repeating Group rows to 15-25 items per page and add pagination for large datasets.
  • Use Option Sets for report categories and status filters — they load instantly with zero workload unit cost.
  • Test reports with realistic data volumes to catch performance issues before going live.
  • Add Privacy Rules that restrict report access to admin or manager roles.

Still stuck?

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

ChatGPT Prompt

I'm building a Bubble.io app and need to create a custom reports page. I have an Orders data type with fields: Customer (User), Amount (number), Status (text), and Created Date. I want summary cards showing totals, a bar chart showing revenue over time, a data table with all records, and CSV export. How should I structure the page and what search expressions should I use?

Bubble Prompt

Create a reports page with date range filters, summary cards showing total orders, total revenue, average order value, and unique customers. Add a bar chart showing daily revenue and a repeating group table with all order details. Include CSV and PDF export buttons.

Frequently asked questions

Can I schedule reports to be generated and emailed automatically in Bubble?

Yes. Create a backend workflow that runs the same search queries, formats the data into an email body or generates a CSV attachment, then use the Send Email action. Schedule it to run daily or weekly using the Schedule API Workflow action with a recursive pattern.

How do I handle large datasets without slowing down the reports page?

Use Search constraints instead of :filtered, paginate your Repeating Group to 15-25 rows, pre-compute aggregations as stored fields, and consider running heavy calculations in a backend workflow that saves results to a Report data type.

Which chart plugin should I use in Bubble for reports?

The built-in Chart Element plugin works for basic charts. For more customization, ApexCharts or Chart.js plugins offer more chart types, better styling, and interactive features. All are available in the Bubble plugin marketplace.

Can I create real-time reports that update automatically?

Yes. Bubble's database searches on page elements auto-update in real time via WebSocket connection. As new records are created or modified, your report data refreshes automatically without the user needing to click a button.

How do I restrict report access to admin users only?

Add a 'role' field to your User data type. On the reports page, add a 'Page is loaded' workflow with the condition 'Current User's role is not admin' that redirects to the home page. Also set Privacy Rules on your Data Types to restrict data access.

Is it worth hiring a professional Bubble developer for complex reporting?

For complex reporting needs involving multiple data sources, advanced calculations, or heavy data volumes, working with experienced developers like the RapidDev team can save significant time and ensure your reports are optimized for performance and accuracy.

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.