Streamlit Sales Dashboard: A Practical Tutorial
Here is a breakdown of how to build a production-ready sales analytics dashboard with filtering and KPI tracking.
Prerequisites
You'll need Python 3.9+. Install the core stack via pip:
pip install streamlit pandas numpy1. Data Setup and Performance Caching
The key to a responsive Streamlit app is @st.cache_data. Without it, the app reruns the entire script (including heavy data loading) every time a user clicks a filter.
import streamlit as st
import pandas as pd
import numpy as np
# Set layout configuration
st.set_page_config(page_title="Sales Dashboard", layout="wide")
# Cache data loading for performance optimization
@st.cache_data
def load_data():
dates = pd.date_range("2025-01-01", periods=180)
regions = ["North", "South", "East", "West"]
df = pd.DataFrame({
"date": np.random.choice(dates, 500),
"region": np.random.choice(regions, 500),
"product": np.random.choice(["A", "B", "C"], 500),
"sales": np.random.randint(100, 5000, 500),
"units": np.random.randint(1, 50, 500),
})
return df.sort_values("date")
df = load_data()2. Implementing Dynamic Filters
I prefer placing filters in the sidebar to maximize the screen real estate for charts. Using a boolean mask is the most efficient way to handle multi-select filtering in Pandas.
# --- Sidebar filters ---
st.sidebar.header("Filters")
region_filter = st.sidebar.multiselect("Region", df["region"].unique(), default=df["region"].unique())
product_filter = st.sidebar.multiselect("Product", df["product"].unique(), default=df["product"].unique())
date_range = st.sidebar.date_input("Date range", [df["date"].min(), df["date"].max()])
# Filter dataframe based on selections
mask = (
df["region"].isin(region_filter)
& df["product"].isin(product_filter)
& (df["date"] >= pd.to_datetime(date_range[0]))
& (df["date"] <= pd.to_datetime(date_range[1]))
)
filtered = df[mask]3. Building the KPI Layer and Visuals
To create a professional "Executive" view, use st.columns for KPIs and st.expander for the raw data table so it doesn't clutter the UI.
# --- Title & Subtitle ---
st.title("📈 Sales Dashboard")
st.caption(f"Showing {len(filtered):,} records")
# --- KPI row ---
c1, c2, c3, c4 = st.columns(4)
c1.metric("Total Sales", f"${filtered['sales'].sum():,.0f}")
c2.metric("Total Units", f"{filtered['units'].sum():,}")
c3.metric("Avg Order", f"${filtered['sales'].mean():,.0f}" if len(filtered) else "$0")
c4.metric("Orders", f"{len(filtered):,}")
st.divider()
# --- Visualizations ---
col1, col2 = st.columns(2)
with col1:
st.subheader("Sales Over Time")
daily = filtered.groupby("date")["sales"].sum()
st.line_chart(daily)
with col2:
st.subheader("Sales by Region")
by_region = filtered.groupby("region")["sales"].sum()
st.bar_chart(by_region)
# --- Product Performance ---
st.subheader("Sales by Product")
by_product = filtered.groupby("product")["sales"].sum()
st.bar_chart(by_product)
# --- Raw Data Section ---
with st.expander("View raw data"):
st.dataframe(filtered, use_container_width=True)To deploy this, just run streamlit run app.py in your terminal. It's a solid AI workflow for anyone needing to prototype a data tool quickly.