- name
- power-bi-sales-analytics-dashboard
- description
- Build interactive Power BI sales dashboards with regional analysis, profit tracking, and predictive insights using the SalesPulse 360 framework
- triggers
- ["create a Power BI sales dashboard","build retail analytics visualization","setup SalesPulse 360 dashboard","analyze regional sales performance","create profit margin dashboard","build interactive business intelligence report","implement Power BI forecasting model","setup sales KPI dashboard"]
# Power BI Sales Analytics Dashboard Skill
> Skill by [ara.so](https://ara.so) — Data Skills collection.
## Overview
SalesPulse 360 is a comprehensive Power BI dashboard framework for retail and sales analytics. It transforms raw sales data into interactive visualizations with regional analysis, profit tracking, multi-dimensional slicing, predictive forecasting, and automated alerts. Built for the Global Superstore dataset, it provides a blueprint for creating production-ready business intelligence dashboards.
**Key Capabilities:**
- Multi-region profit and sales analysis with geographic heatmaps
- Predictive forecasting with confidence corridors
- Automated exception alerts for margin and performance thresholds
- Multilingual support with cultural localization
- Row-level security for regional data access
- Responsive design for desktop and tablet viewing
- Dynamic natural language insights generation
## Installation & Setup
### Prerequisites
- Power BI Desktop 2.120 or higher
- Global Superstore dataset (or similar retail transaction data)
- Power BI Service account (for publishing and scheduled refresh)
### Quick Start
1. **Clone the Repository**
```bash
git clone https://github.com/MahbubNibir/power-bi-retail-analytics-viz.git
cd power-bi-retail-analytics-viz
```
2. **Extract Dataset**
```bash
# Extract the Global Superstore CSV from the archive
unzip data/global_superstore.zip -d data/
```
3. **Open Power BI Desktop File**
```bash
# Open the main dashboard file
start salespulse360.pbix # Windows
open salespulse360.pbix # macOS
```
4. **Initial Data Load**
- Power BI will automatically trigger the data transformation pipeline
- Expect 2-3 minute processing time on first load
- The query editor will clean, normalize, and augment raw records
## Data Source Configuration
### CSV File Connection
In Power BI Desktop, configure the data source path:
1. Navigate to **Transform Data** > **Data Source Settings**
2. Update the file path to your extracted CSV location:
```m
// Power Query M - Data source configuration
let
Source = Csv.Document(
File.Contents("C:\data\global_superstore.csv"),
[Delimiter=",", Columns=21, Encoding=65001, QuoteStyle=QuoteStyle.None]
),
PromotedHeaders = Table.PromoteHeaders(Source, [PromoteAllScalars=true])
in
PromotedHeaders
```
### Database Connection (Alternative)
For live database connections:
```m
// Power Query M - SQL Server connection
let
Source = Sql.Database(
"YOUR_SERVER_NAME",
"SalesDB",
[Query="SELECT * FROM dbo.Sales WHERE OrderDate >= '2011-01-01'"]
)
in
Source
```
Use environment variables for credentials:
- Server: `${Env:SQL_SERVER}`
- Database: `${Env:SQL_DATABASE}`
- Authentication: Windows or SQL (configure in connection settings)
## Key Data Transformations
### Date Dimension Table
```m
// Power Query M - Create date dimension
let
StartDate = #date(2011, 1, 1),
EndDate = #date(2025, 12, 31),
NumberOfDays = Duration.Days(EndDate - StartDate) + 1,
DateList = List.Dates(StartDate, NumberOfDays, #duration(1,0,0,0)),
TableFromList = Table.FromList(DateList, Splitter.SplitByNothing()),
ChangedType = Table.TransformColumnTypes(TableFromList, {{"Column1", type date}}),
RenamedColumns = Table.RenameColumns(ChangedType, {{"Column1", "Date"}}),
// Add calculated columns
AddYear = Table.AddColumn(RenamedColumns, "Year", each Date.Year([Date]), Int64.Type),
AddQuarter = Table.AddColumn(AddYear, "Quarter", each "Q" & Text.From(Date.QuarterOfYear([Date]))),
AddMonth = Table.AddColumn(AddQuarter, "Month", each Date.MonthName([Date])),
AddWeek = Table.AddColumn(AddMonth, "WeekOfYear", each Date.WeekOfYear([Date]), Int64.Type),
AddDayOfWeek = Table.AddColumn(AddWeek, "DayOfWeek", each Date.DayOfWeekName([Date]))
in
AddDayOfWeek
```
### Profit Margin Calculation
```m
// Power Query M - Add profit margin percentage
let
Source = Sales,
AddProfitMargin = Table.AddColumn(
Source,
"ProfitMargin",
each if [Sales] <> 0 then [Profit] / [Sales] else 0,
type number
),
FormatPercentage = Table.TransformColumns(
AddProfitMargin,
{{"ProfitMargin", each Number.Round(_, 4), type number}}
)
in
FormatPercentage
```
## DAX Measures
### Core KPIs
```dax
// Total Sales measure
Total Sales = SUM(Sales[Sales])
// Total Profit measure
Total Profit = SUM(Sales[Profit])
// Average Order Value
Avg Order Value = DIVIDE([Total Sales], DISTINCTCOUNT(Sales[Order ID]), 0)
// Profit Margin %
Profit Margin % = DIVIDE([Total Profit], [Total Sales], 0)
// Sales Growth YoY
Sales Growth YoY =
VAR CurrentYearSales = [Total Sales]
VAR PreviousYearSales = CALCULATE(
[Total Sales],
DATEADD(DateDim[Date], -1, YEAR)
)
RETURN
DIVIDE(
CurrentYearSales - PreviousYearSales,
PreviousYearSales,
0
)
```
### Moving Annual Total (MAT)
```dax
// 12-month rolling sales
MAT Sales =
CALCULATE(
[Total Sales],
DATESINPERIOD(
DateDim[Date],
LASTDATE(DateDim[Date]),
-12,
MONTH
)
)
```
### Regional Performance Index
```dax
// Regional performance vs global average
Regional Performance Index =
VAR RegionalMargin = [Profit Margin %]
VAR GlobalMargin = CALCULATE(
[Profit Margin %],
ALL(Sales[Region])
)
RETURN
DIVIDE(RegionalMargin, GlobalMargin, 0)
```
### Exception Alert Flag
```dax
// Alert when margin drops below threshold
Margin Alert =
VAR CurrentMargin = [Profit Margin %]
VAR Threshold = 0.15 // 15% threshold - make this a parameter table value
RETURN
IF(
CurrentMargin < Threshold,
"⚠️ Low Margin",
"✓ On Track"
)
```
### Predictive Forecast Measure
```dax
// Sales forecast using historical trend
Forecasted Sales =
VAR HistoricalAvg = CALCULATE(
[Total Sales],
DATESINPERIOD(DateDim[Date], MAX(DateDim[Date]), -6, MONTH)
)
VAR GrowthRate = [Sales Growth YoY]
RETURN
HistoricalAvg * (1 + GrowthRate)
```
## Dashboard Configuration
### Alert Threshold Parameters
Create a **Config** table with thresholds:
```dax
// DAX table for configuration
Config = DATATABLE(
"Parameter", STRING,
"Value", NUMBER,
{
{"ProfitMarginThreshold", 0.15},
{"ReturnRateWarning", 0.08},
{"RollingAverageDays", 90}
}
)
// Reference in measures
Profit Threshold =
LOOKUPVALUE(Config[Value], Config[Parameter], "ProfitMarginThreshold")
```
### Row-Level Security (RLS)
Define roles for regional data access:
```dax
// RLS filter for Regional Managers
[Region] = USERNAME()
// RLS filter for specific email mapping
VAR UserEmail = USERPRINCIPALNAME()
VAR UserRegion = LOOKUPVALUE(
UserMapping[Region],
UserMapping[Email],
UserEmail
)
RETURN [Region] = UserRegion
```
Apply RLS in **Modeling** > **Manage Roles** > **Create Role** > Add DAX filter.
### Localization Setup
Create a **Language** table:
```dax
Language = DATATABLE(
"LanguageCode", STRING,
"LanguageName", STRING,
"DateFormat", STRING,
"CurrencySymbol", STRING,
{
{"en-US", "English", "MM/DD/YYYY", "$"},
{"es-ES", "Spanish", "DD/MM/YYYY", "€"},
{"zh-CN", "Chinese", "YYYY-MM-DD", "¥"},
{"ja-JP", "Japanese", "YYYY/MM/DD", "¥"}
}
)
```
Use field parameters to switch labels dynamically.
## Visualization Patterns
### Geographic Heatmap with Profit
1. Insert **Map** visual
2. Location: `Sales[City]` or `Sales[State]`
3. Size: `[Total Sales]`
4. Color saturation: `[Profit Margin %]`
5. Tooltip: Add `[Regional Performance Index]`
### Treemap for Category Performance
1. Insert **Treemap** visual
2. Group: `Sales[Category]` > `Sales[Sub-Category]`
3. Values: `[Total Profit]`
4. Color: `[Profit Margin %]` with conditional formatting
### Time Series with Forecast
1. Insert **Line Chart**
2. X-axis: `DateDim[Date]` (Month hierarchy)
3. Y-axis: `[Total Sales]`
4. Analytics pane > Forecast > 12 months, 95% confidence interval
### KPI Cards with Conditional Formatting
1. Insert **Card** visual for each KPI
2. Display value: `[Total Profit]`
3. Conditional formatting > Background color > Rules:
- If `[Profit Margin %] < 0.15` → Red
- If `[Profit Margin %] >= 0.15 AND < 0.25` → Yellow
- If `[Profit Margin %] >= 0.25` → Green
### Dynamic Text Panel (Smart Storytelling)
```dax
// Natural language insight generator
Sales Insight =
VAR CurrentSales = [Total Sales]
VAR PrevSales = CALCULATE([Total Sales], PREVIOUSMONTH(DateDim[Date]))
VAR Change = DIVIDE(CurrentSales - PrevSales, PrevSales, 0)
VAR ChangeText = IF(Change >= 0, "increased", "declined")
VAR ChangePercent = FORMAT(ABS(Change), "0.0%")
VAR TopRegion = TOPN(1, VALUES(Sales[Region]), [Total Sales], DESC)
RETURN
"Sales have " & ChangeText & " by " & ChangePercent &
" this period. The " & TopRegion & " region is the top performer."
```
Insert a **Text Box** or **Card** visual with this measure.
## Publishing & Scheduling
### Publish to Power BI Service
1. In Power BI Desktop: **File** > **Publish** > **Publish to Power BI**
2. Select workspace (e.g., "Sales Analytics")
3. Confirm publish
### Configure Scheduled Refresh
1. Navigate to workspace in Power BI Service
2. Find the dataset > **Settings** > **Scheduled refresh**
3. Enable: **Keep your data up to date**
4. Frequency: Daily at 02:00 UTC (or custom)
5. Gateway: Configure if using on-premises data
### Embed in Web Application
```html
<!-- HTML embedding example -->
<!DOCTYPE html>
<html>
<head>
<title>Sales Dashboard</title>
<script src="https://cdn.jsdelivr.net/npm/powerbi-client@2.20.0/dist/powerbi.min.js"></script>
</head>
<body>
<div id="embedContainer" style="height:600px;"></div>
<script>
const embedConfig = {
type: 'report',
id: 'YOUR_REPORT_ID',
embedUrl: 'https://app.powerbi.com/reportEmbed',
accessToken: process.env.POWERBI_ACCESS_TOKEN,
settings: {
filterPaneEnabled: false,
navContentPaneEnabled: true
}
};
const reportContainer = document.getElementById('embedContainer');
const report = powerbi.embed(reportContainer, embedConfig);
</script>
</body>
</html>
```
## Common Patterns
### Drill-Through Page for Product Details
1. Create a new page "Product Detail"
2. Add **Drill through** field: `Sales[Product Name]`
3. Add visuals: Sales trend, profit margin, customer segments
4. Right-click any product in main dashboard > Drill through > Product Detail
### Bookmark Navigation
1. **View** > **Bookmarks**
2. Configure dashboard state (filters, page, selections)
3. Save bookmark (e.g., "Regional View")
4. Add **Buttons** with bookmark actions for navigation
5. Button text: "Sales Overview", "Profit Analysis", "Regional Deep Dive"
### Parameter-Based "What-If" Analysis
```dax
// Create What-If parameter
What-If Discount % =
GENERATESERIES(0, 0.5, 0.05) // 0% to 50% in 5% increments
// Adjusted profit with discount
Adjusted Profit =
[Total Profit] - ([Total Sales] * 'What-If Discount %'[Value])
```
Add a **slicer** for the What-If parameter to simulate scenarios.
### Cross-Report Filtering
```dax
// In source report, create measure for selection
Selected Region =
IF(
HASONEVALUE(Sales[Region]),
VALUES(Sales[Region]),
BLANK()
)
```
Pass as URL parameter to second report:
```
https://app.powerbi.com/groups/WORKSPACE_ID/reports/REPORT_ID?filter=Sales/Region eq 'West'
```
## Troubleshooting
### Data Refresh Failures
**Issue:** Scheduled refresh fails with "Unable to connect to data source"
**Solutions:**
- Verify gateway is online (for on-premises data)
- Update credentials in Power BI Service dataset settings
- Check firewall rules allow outbound connections
- Test connection in Power BI Desktop first
### Performance Optimization
**Issue:** Dashboard loads slowly with large datasets
**Solutions:**
- Use **Import** mode instead of DirectQuery when possible
- Enable query folding in Power Query
- Remove unused columns early in transformation
Voir sur GitHub