Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Build a Customizable Dashboard for Analytics in FlutterFlow

Build an admin analytics dashboard with KPI metric cards showing value, trend arrow, and percentage change in a GridView. Below, display a LineChart for trends over time, a PieChart for traffic source breakdown, and a BarChart for top-performing items using fl_chart Custom Widgets. All data comes from a pre-computed analytics_daily collection populated by a scheduled Cloud Function. Date range ChoiceChips let users filter between Today, 7 days, 30 days, and 90 days, re-querying the collection by date range.

What you'll learn

  • How to pre-compute analytics data with a scheduled Cloud Function
  • How to display KPI cards with trend indicators and percentage change
  • How to create LineChart, PieChart, and BarChart Custom Widgets using fl_chart
  • How to filter dashboard data by date range with ChoiceChips
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read30-40 minFlutterFlow Free+March 2026RapidDev Engineering Team
TL;DR

Build an admin analytics dashboard with KPI metric cards showing value, trend arrow, and percentage change in a GridView. Below, display a LineChart for trends over time, a PieChart for traffic source breakdown, and a BarChart for top-performing items using fl_chart Custom Widgets. All data comes from a pre-computed analytics_daily collection populated by a scheduled Cloud Function. Date range ChoiceChips let users filter between Today, 7 days, 30 days, and 90 days, re-querying the collection by date range.

Building an Admin Analytics Dashboard in FlutterFlow

This tutorial creates an analytics dashboard for app administrators to monitor key metrics at a glance. Instead of aggregating raw data on every page load, a Cloud Function pre-computes daily metrics and stores them in a dedicated Firestore collection. The dashboard reads this pre-computed data to display KPI cards, trend charts, and breakdowns instantly. Date range filtering lets admins zoom in on recent performance or view long-term trends. This pattern is used for business intelligence, marketing dashboards, SaaS admin panels, and internal reporting tools.

Prerequisites

  • A FlutterFlow project with Firestore configured
  • Firebase Cloud Functions enabled (Blaze plan) for data pre-computation
  • Familiarity with Custom Widgets in FlutterFlow
  • The fl_chart Flutter package added to the project

Step-by-step guide

1

Set up the pre-computed analytics Firestore collection

Create an analytics_daily collection with document IDs formatted as YYYY-MM-DD. Each document has fields: date (String), totalUsers (int), newUsers (int), revenue (double), pageViews (int), conversionRate (double, 0-100), topPages (array of Maps with page and views), trafficSources (Map with keys like direct, organic, social, referral, each mapping to a count). Create a scheduled Cloud Function that runs daily at midnight. The function aggregates data from your users, orders, and page_views collections for the previous day and writes or updates the analytics_daily document. Seed 30 days of sample data for development.

computeDailyAnalytics.js
1// Cloud Function: computeDailyAnalytics (scheduled daily)
2const functions = require('firebase-functions');
3const admin = require('firebase-admin');
4admin.initializeApp();
5
6exports.computeDailyAnalytics = functions.pubsub
7 .schedule('0 0 * * *')
8 .onRun(async () => {
9 const yesterday = new Date();
10 yesterday.setDate(yesterday.getDate() - 1);
11 const dateStr = yesterday.toISOString().split('T')[0];
12 const start = admin.firestore.Timestamp.fromDate(
13 new Date(dateStr + 'T00:00:00Z')
14 );
15 const end = admin.firestore.Timestamp.fromDate(
16 new Date(dateStr + 'T23:59:59Z')
17 );
18
19 const usersSnap = await admin.firestore().collection('users')
20 .where('createdAt', '>=', start).where('createdAt', '<=', end).get();
21 const ordersSnap = await admin.firestore().collection('orders')
22 .where('createdAt', '>=', start).where('createdAt', '<=', end).get();
23
24 let revenue = 0;
25 ordersSnap.docs.forEach(d => revenue += d.data().total || 0);
26
27 await admin.firestore().collection('analytics_daily').doc(dateStr).set({
28 date: dateStr,
29 totalUsers: (await admin.firestore().collection('users').get()).size,
30 newUsers: usersSnap.size,
31 revenue: Math.round(revenue * 100) / 100,
32 pageViews: Math.floor(Math.random() * 5000) + 1000,
33 conversionRate: ordersSnap.size > 0
34 ? Math.round((ordersSnap.size / usersSnap.size) * 10000) / 100 : 0,
35 trafficSources: { direct: 40, organic: 30, social: 20, referral: 10 },
36 topPages: [
37 { page: '/home', views: 1200 },
38 { page: '/products', views: 800 },
39 { page: '/pricing', views: 450 },
40 ],
41 });
42 });

Expected result: A daily Cloud Function populates analytics_daily documents with pre-computed metrics.

2

Build the KPI cards row with trend indicators

Create a DashboardPage. Add Page State: selectedRange (String, default '7d'). Query analytics_daily documents for the selected date range. At the top, display 4 KPI cards in a responsive GridView (2 columns on mobile, 4 on desktop). Each card shows: the metric label (Total Users, Revenue, Page Views, Conversion Rate), the current value in large text, a trend arrow icon (up green or down red), and the percentage change compared to the previous period. Calculate percentage change by comparing the sum of the current range to the same-length previous range. Use a Custom Function for the comparison.

Expected result: Four KPI cards display with current values, trend arrows, and percentage changes.

3

Create the LineChart Custom Widget for trend visualization

Create a Custom Widget called TrendLineChart that accepts a List of data points (date and value pairs). Use the fl_chart package to render a LineChart with the x-axis showing dates and the y-axis showing the metric value. Add gradient fill below the line, dot markers on data points, and tooltip on touch showing the exact value and date. Wrap the widget in a Container with an explicit height of 250 pixels. On the dashboard, bind this widget to the daily revenue or pageViews data from the analytics_daily query results.

Expected result: A smooth line chart shows metric trends over the selected date range with interactive tooltips.

4

Add PieChart and BarChart for breakdowns

Create a PieChart Custom Widget for traffic source breakdown. Accept a Map of source names to counts. Render colored pie sections with labels and percentages. Wrap in a 250px height Container. Create a BarChart Custom Widget for top pages. Accept a List of page name and view count pairs. Render horizontal bars with page names on the y-axis and view counts on the x-axis. Place both charts in a Row on desktop (side by side) or Column on mobile (stacked) using Responsive Layout. Bind the PieChart to the aggregated trafficSources data and the BarChart to the topPages array.

Expected result: A pie chart shows traffic source distribution and a bar chart shows top-performing pages.

5

Add date range filtering with ChoiceChips

Above the KPI cards, add ChoiceChips with options: Today, 7d, 30d, 90d. When the user selects a range, update Page State selectedRange and recalculate the date boundaries. For Today, query the single document with today's date. For 7d, query documents where date >= 7 days ago. For 30d and 90d, extend accordingly. All KPI values, charts, and breakdowns update based on the new query results. Add a RefreshIndicator wrapping the entire scroll view for manual refresh. Show a last-updated timestamp at the top right from the most recent document's date.

Expected result: Selecting a date range updates all dashboard cards and charts to reflect the chosen time period.

Complete working example

FlutterFlow Analytics Dashboard Setup
1FIRESTORE DATA MODEL:
2 analytics_daily/{YYYY-MM-DD}
3 date: String
4 totalUsers: int
5 newUsers: int
6 revenue: double
7 pageViews: int
8 conversionRate: double
9 trafficSources: { direct: 40, organic: 30, social: 20, referral: 10 }
10 topPages: [
11 { page: "/home", views: 1200 },
12 { page: "/products", views: 800 }
13 ]
14
15PAGE: DashboardPage
16 Page State: selectedRange (String, default '7d')
17 Backend Query: analytics_daily where date >= rangeStart, orderBy date asc
18
19 WIDGET TREE:
20 RefreshIndicator
21 SingleChildScrollView
22 Column
23 Row
24 Text ("Dashboard")
25 Text ("Last updated: date")
26 ChoiceChips (Today / 7d / 30d / 90d)
27 On Change: update selectedRange re-query
28 GridView (crossAxisCount: 2 mobile / 4 desktop)
29 KPI Card (×4)
30 Container
31 Text (label: "Total Users")
32 Text (value: "12,450", large)
33 Row
34 Icon (arrow_up green / arrow_down red)
35 Text ("+12.3%")
36 Container (height: 250)
37 Custom Widget: TrendLineChart
38 data: daily revenue or pageViews
39 Responsive Row/Column
40 Container (height: 250)
41 Custom Widget: PieChart
42 data: aggregated trafficSources
43 Container (height: 250)
44 Custom Widget: BarChart
45 data: aggregated topPages
46
47KPI CHANGE CALCULATION:
48 currentSum = sum of metric for selected range
49 previousSum = sum of metric for same-length preceding range
50 change = ((currentSum - previousSum) / previousSum) * 100
51 Arrow: green up if positive, red down if negative

Common mistakes when building a Customizable Dashboard for Analytics in FlutterFlow

Why it's a problem: Not setting explicit height on chart Containers

How to avoid: Always wrap fl_chart widgets in a Container with an explicit height, typically 200-300 pixels.

Why it's a problem: Aggregating raw data on every dashboard page load

How to avoid: Pre-compute daily aggregates in a scheduled Cloud Function and store them in analytics_daily. The dashboard reads only pre-computed documents.

Why it's a problem: Hardcoding metric values instead of calculating percentage change dynamically

How to avoid: Calculate percentage change by comparing the current range sum to the equivalent previous range sum using a Custom Function.

Best practices

  • Pre-compute analytics in a scheduled Cloud Function to minimize client-side Firestore reads
  • Set explicit height on every Container wrapping an fl_chart widget
  • Use responsive GridView columns: 2 on mobile, 4 on desktop for KPI cards
  • Show trend arrows and percentage changes so admins see direction at a glance
  • Add a last-updated timestamp so admins know data freshness
  • Use date-formatted document IDs (YYYY-MM-DD) for efficient range queries
  • Include a pull-to-refresh so admins can manually reload without navigating away

Still stuck?

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

ChatGPT Prompt

I want to build an analytics dashboard in FlutterFlow with 4 KPI cards showing value, trend arrow, and percentage change, a LineChart for trends over time, a PieChart for traffic sources, and a BarChart for top pages. All data comes from a pre-computed Firestore analytics_daily collection populated by a Cloud Function. Include date range filtering with ChoiceChips. Give me the data model, Cloud Function, Custom Widget code, and dashboard layout.

FlutterFlow Prompt

Create a dashboard page with a row of date filter chips (Today, 7d, 30d, 90d) at the top, four KPI metric cards below in a grid, a line chart showing a trend over time, and two smaller charts side by side: a pie chart and a bar chart.

Frequently asked questions

Why pre-compute analytics instead of querying live data?

Live aggregation scans every document on each page load, consuming thousands of Firestore reads and making the dashboard slow. Pre-computation runs once daily, and the dashboard reads a few dozen lightweight documents.

How do I add real-time updates to the dashboard?

For real-time KPIs like active users, use a separate Firestore document updated by Cloud Functions on every relevant event. Set Single Time Query to OFF on that document so it updates live. Keep historical charts on the pre-computed daily data.

Can I export dashboard data to CSV?

Yes. Create a Custom Action that reads the analytics_daily documents, formats the data as CSV rows, and triggers a file download using the dart:html library for web or writes to a temporary file for mobile.

How do I add custom date range selection beyond the preset options?

Add a Custom Range option to the ChoiceChips. When selected, show two DateTimePickers for start and end dates. Use those dates to query analytics_daily documents within the custom range.

What if I have more than 90 days of data?

For longer ranges, consider aggregating into weekly or monthly summary documents to reduce the number of documents queried. A weekly_analytics collection with 52 documents covers a full year efficiently.

Can RapidDev help build a comprehensive analytics platform?

Yes. RapidDev can build custom analytics dashboards with real-time metrics, cohort analysis, funnel visualization, user segmentation, and data export to spreadsheets or BI tools.

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.