Matrix/TableFree

Creating a Dynamic Customer Pareto Dashboard (First Version)

This documentation provides a step-by-step approach to building the first version of the one-for-all customer Pareto analysis dashboard.

Written byIwa Sanjaya
Updated on26 October 2025Read time17 min

Creating a Dynamic Customer Pareto Dashboard (First Version)

Foreword

This documentation provides a step-by-step approach to building the first version of the one-for-all customer Pareto analysis dashboard. This interactive tool allows you to seamlessly switch between various metrics, significantly saving time, effort, and dashboard space. It's designed to help you analyze the "vital few" versus the "trivial many" for specific variables, such as customers, across different key performance indicators. Currently, it effectively analyzes total transactions, total order value, total items and total profit.

The first version loads faster because it doesn't require a new table for dynamic customer grouping ("A+" or "Others") based on thresholds and cumulative percentages, simplifying calculations.

Understanding Pareto Principle

What is the Pareto Principle (The 80/20 Rule)?

Imagine you have a big pile of something – let's say, 100 colorful building blocks. The Pareto Principle suggests that if you were to count how many of those blocks are truly important for building your best tower, you'd find something interesting:

  • About 20% of the blocks (the "important few") would be used to build 80% of the height or strength of your tower.

  • The other 80% of the blocks (the "many less important ones") would only contribute to about 20% of the tower's overall impact.

So, it's not a strict math rule, but a general observation that a small number of things (causes) often create a big impact (results).

It's called the 80/20 Rule because that's the most common ratio, but it could be 70/30, 90/10, or something similar. The point is, it's uneven.


Applying the 80/20 Rule to Your Customers

Now, how does this help with understanding customers? It's super powerful for businesses because it helps you figure out where to put your energy.

Think of your customers like those building blocks. If you have 100 customers:

  1. Finding Your "Star" Customers:

    • The Idea: Roughly 20% of your customers are likely bringing in about 80% of your total sales (or profits).
    • How to do it:
      • Look at your sales records.
      • Sort your customers from the ones who spend the most down to the ones who spend the least.
      • Then, just visually or by calculation, find the group of customers (likely around 20% of them) that collectively make up about 80% of your total money.
    • What this tells you: These are your VIPs. They are the most crucial for your business's survival. You should treat them extra well, offer them special perks, listen to their feedback, and make sure they stay happy. Losing one of these "star" customers hurts much more than losing one of the others.
  2. Popular Products:

    • The Idea: About 20% of your products or services probably make up 80% of your sales.
    • How to do it: Look at which products sell the most.
    • What this tells you: These are your cash cows. Make sure you always have them in stock, promote them heavily, and consider improving them further.
  3. Solving Customer Problems:

    • The Idea: If customers are complaining, roughly 20% of the types of complaints are causing 80% of all the actual complaints you receive.
    • How to do it: Track what customers are complaining about. Group similar complaints together.
    • What this tells you: Instead of trying to fix every tiny complaint, focus on fixing those top 20% of types of complaints. If you solve those few big issues, you'll dramatically reduce customer unhappiness overall.
  4. Effective Marketing:

    • The Idea: About 20% of your advertising efforts or marketing channels are bringing in 80% of your new customers.
    • How to do it: See which ads or marketing methods are actually getting you the most new business.
    • What this tells you: Don't spread your marketing budget too thin. Pour more money and effort into the few channels that are really working, and scale back on the less effective ones.

The Big Takeaway: Focus Your Energy Smartly!

The Pareto Principle for customers (and business in general) is all about smart focus.

Instead of treating everyone or everything equally, it helps you identify the "vital few" (the 20% that matter most) versus the "trivial many" (the 80% that matter less).

By identifying these key areas, you can:

  • Save Time & Money: Don't waste resources on things that don't give much back.

  • Boost Profits: By nurturing your best customers and products, your income will grow.

  • Make Customers Happier: Solve the biggest problems for the most people.

It's a simple idea, but incredibly powerful for making better business decisions.

DAX Measures

Base Measures

Total Transactions

DAX
_01 Total Transactions = DISTINCTCOUNT(Superstore[Order ID])

Total Revenue (Total Order Value)

DAX
_01 Total Revenue = SUM(Superstore[Sales])

Total Quantity

DAX
_01 Total Quantity = SUM(Superstore[Quantity])

Total Profit

DAX
_01 Total Profit = SUM(Superstore[Profit])

Total Customers

AC Total Customers

DAX
_01 Total Customers = DISTINCTCOUNT(Superstore[Customer ID])

PY Total Customers

DAX
_02 PY Total Customers = 
IF(
  HASONEVALUE(DimDate[Year]),
  CALCULATE(
      [_01 Total Customers],
      SAMEPERIODLASTYEAR(DimDate[Date])
  ),
  BLANK()
)

△PY Total Customers

DAX
_03 △PY Total Customers = 
IF(
  HASONEVALUE(DimDate[Year]) 
  && NOT(ISBLANK([_02 PY Total Customers])) 
  && NOT(ISBLANK([_01 Total Customers])) 
  && [_01 Total Customers] <> 0,
  [_01 Total Customers] - [_02 PY Total Customers],
  BLANK()
)

△PY% Total Customers

DAX
_04 △PY% Total Customers = 
IF(
  ISBLANK([_01 Total Customers]) || [_01 Total Customers] = 0,
  "--",
  DIVIDE([_01 Total Customers] - [_02 PY Total Customers], [_02 PY Total Customers], 0)
)

CF_△PY Total Customers

DAX
CF_△PY Total Customers = 
SWITCH(
  TRUE(),
  [_03 △PY Total Customers] > 0, "#6A994E",
  [_03 △PY Total Customers] = 0, "#808080",
  "#BC4749"
)

CF_△PY% Total Customers

DAX
CF_△PY% Dynamic Selected Metric = 
SWITCH(
  TRUE(),
  [_04 △PY% Dynamic Selected Metric] > 0, "#6A994E",
  [_04 △PY% Dynamic Selected Metric] = 0, "#808080",
  "#BC4749"
)

Disconnected Table - Selected Metric

DAX
Selected Metric = 
DATATABLE (
  "Measure", STRING,
  "Order", INTEGER,
  {
      {"Total Transactions", 1},
      {"Total Order Value", 2},
      {"Total Items", 3},
      {"Total Profit", 4}
  }
)

Dynamic Selected Metric

DAX
_01 Dynamic Selected Metric = 
VAR SelectedMeasure = SELECTEDVALUE('Selected Metric'[Measure])
RETURN
  SWITCH(
      SelectedMeasure,
      "Total Transactions", [_01 Total Transactions],
      "Total Order Value", [_01 Total Revenue],
      "Total Items", [_01 Total Quantity],
      "Total Profit", [_01 Total Profit],
      BLANK()
  )

Dynamic Rank (based on selected metric)

DAX
_01 Dynamic Rank (based on selected metric) = 
IF(
  ISINSCOPE('Table_RFM Analysis'[Customer Name]) && 
  NOT ISBLANK([_01 Dynamic Selected Metric]),
  
  RANKX(
      ALL('Table_RFM Analysis'[Customer ID], 'Table_RFM Analysis'[Customer Name]),
      [_01 Dynamic Selected Metric] * 10000000 + CALCULATE(SUM('Table_RFM Analysis'[Customer ID_Number])),
      ,
      DESC,
      DENSE
  ),
  BLANK()
)

Total Dynamic Selected Metric

DAX
_01 Total Dynamic Selected Metric = 
CALCULATE(
  [_01 Dynamic Selected Metric],
  ALLSELECTED('Table_RFM Analysis')
)

% of Grand Total of Dynamic Selected Metric

DAX
_01 GT%_Dynamic Selected Metric = 
DIVIDE(
  [_01 Dynamic Selected Metric],
  [_01 Total Dynamic Selected Metric],
  0
)

Cumulative Value by Dynamic Rank

DAX
_01 Cumulative Value by Dynamic Rank = 
VAR CurrentRank = [_01 Dynamic Rank (based on selected metric)]
VAR IsTotal = ISINSCOPE('Table_RFM Analysis'[Customer Name]) = FALSE()

RETURN
IF(
  IsTotal,
  BLANK(),  -- Hide the total row
  IF(
      NOT ISBLANK(CurrentRank),
      SUMX(
          FILTER(
              ALL('Table_RFM Analysis'[Customer Name], 'Table_RFM Analysis'[Customer ID]),
              CALCULATE([_01 Dynamic Rank (based on selected metric)]) <= CurrentRank
          ),
          CALCULATE([_01 Dynamic Selected Metric])
      )
  )
)

% of Cumulative Value by Dynamic Rank

DAX
_01 % Cumulative Value by Dynamic Rank = 
VAR CumulativeValue = [_01 Cumulative Value by Dynamic Rank]
VAR TotalValue = [_01 Total Dynamic Selected Metric]
VAR IsTotal = ISINSCOPE('Table_RFM Analysis'[Customer Name]) = FALSE()
RETURN
IF(
  IsTotal,
  BLANK(), // Hide the total row
  IF(
      NOT ISBLANK(CumulativeValue) && NOT ISBLANK(TotalValue) && TotalValue <> 0,
      CumulativeValue / TotalValue,
      BLANK()
  )
)

Cutoff Customer Pareto Segment

DAX
_01 Cutoff_Customer Pareto Segment = 
VAR ParetoThreshold = [Pareto Value]  -- e.g., 0.15 for 15%
VAR CumulativePct = [_01 % Cumulative Value by Dynamic Rank]  -- your cumulative % measure
VAR IsTotal = ISINSCOPE('Table_RFM Analysis'[Customer Name]) = FALSE()  -- Check if at total level
RETURN
IF(
  IsTotal,
  BLANK(),  -- Hide ONLY the total row
  IF(
      NOT ISBLANK(CumulativePct),
      IF(CumulativePct <= ParetoThreshold, "A+", "Others"),
      BLANK()
  )
)

SVG Pareto Bar Charts

SVG Pareto Bar Chart - Total Transactions

DAX
_01 SVG Pareto Bar Chart_Total Transactions = 
VAR IsTotal = ISINSCOPE('Table_RFM Analysis'[Customer Name]) = FALSE

VAR MaxTransaction = CALCULATE(
  MAXX(ALL(Superstore), [_01 Total Transactions])
)

VAR Bar_Value = [_01 Total Transactions]
VAR NormalizedValue = DIVIDE(Bar_Value, MaxTransaction)
VAR Bar_Fill = NormalizedValue * 25

-- Get the group from your cutoff measure
VAR CustomerGroup = [_01 Cutoff_Customer Pareto Segment]

-- Set color based on group
VAR Bar_Color = 
  IF(
      CustomerGroup = "A+",
      "#024AB2",  -- Blue for A+ group
      "#E6E6E6"   -- Light gray for others
  )

VAR SVG_Data_URL = "data:image/svg+xml;utf8,"
VAR SVG_Start = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 175 25'>"
VAR SVG_Data = "<rect fill='" & Bar_Color & "' x='0' y='0' width='" & Bar_Fill & "' height='25' />"
VAR SVG_End = "</svg>"

RETURN
IF(
  IsTotal,
  BLANK(),
  SVG_Data_URL & SVG_Start & SVG_Data & SVG_End
)

SVG Pareto Bar Chart - Total Order Value

DAX
_01 SVG Pareto Bar Chart_Total Order Value = 
VAR IsTotal = ISINSCOPE('Table_RFM Analysis'[Customer Name]) = FALSE

VAR MaxTransaction = CALCULATE(
  MAXX(ALL(Superstore), [_01 Total Revenue])
)

VAR Bar_Value = [_01 Total Revenue]
VAR NormalizedValue = DIVIDE(Bar_Value, MaxTransaction)
VAR Bar_Fill = NormalizedValue * 250

-- Get the group from your cutoff measure
VAR CustomerGroup = [_01 Cutoff_Customer Pareto Segment]

-- Set color based on group
VAR Bar_Color = 
  IF(
      CustomerGroup = "A+",
      "#024AB2",  -- Blue for A+ group
      "#E6E6E6"   -- Light gray for others
  )

VAR SVG_Data_URL = "data:image/svg+xml;utf8,"
VAR SVG_Start = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 175 25'>"
VAR SVG_Data = "<rect fill='" & Bar_Color & "' x='0' y='0' width='" & Bar_Fill & "' height='25' />"
VAR SVG_End = "</svg>"

RETURN
IF(
  IsTotal,
  BLANK(),
  SVG_Data_URL & SVG_Start & SVG_Data & SVG_End
)

SVG Pareto Bar Chart - Quantity

DAX
_01 SVG Pareto Bar Chart_Total Quantity = 
VAR IsTotal = ISINSCOPE('Table_RFM Analysis'[Customer Name]) = FALSE

VAR MaxTransaction = CALCULATE(
  MAXX(ALL(Superstore), [_01 Total Quantity])
)

VAR Bar_Value = [_01 Total Quantity]
VAR NormalizedValue = DIVIDE(Bar_Value, MaxTransaction)
VAR Bar_Fill = NormalizedValue * 25

-- Get the group from your cutoff measure
VAR CustomerGroup = [_01 Cutoff_Customer Pareto Segment]

-- Set color based on group
VAR Bar_Color = 
  IF(
      CustomerGroup = "A+",
      "#024AB2",  -- Blue for A+ group
      "#E6E6E6"   -- Light gray for others
  )

VAR SVG_Data_URL = "data:image/svg+xml;utf8,"
VAR SVG_Start = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 175 25'>"
VAR SVG_Data = "<rect fill='" & Bar_Color & "' x='0' y='0' width='" & Bar_Fill & "' height='25' />"
VAR SVG_End = "</svg>"

RETURN
IF(
  IsTotal,
  BLANK(),
  SVG_Data_URL & SVG_Start & SVG_Data & SVG_End
)

SVG Pareto Bar Chart - Total Profit

DAX
_01 SVG Pareto Bar Chart_Total Profit = 
VAR IsTotal = ISINSCOPE('Table_RFM Analysis'[Customer Name]) = FALSE

-- SVG dimensions
VAR TotalWidth = 200
VAR HalfWidth = TotalWidth / 2
VAR Height = 25

-- Max absolute profit to scale both directions
VAR MaxAbsProfit = CALCULATE(
  MAXX(ALL(Superstore), ABS([_01 Total Profit]))
)

-- Actual profit value
VAR Bar_Value = [_01 Total Profit]

-- Normalized bar width
VAR NormalizedWidth = DIVIDE(ABS(Bar_Value), MaxAbsProfit) * HalfWidth

-- Bar position
VAR Bar_X = IF(Bar_Value >= 0, HalfWidth, HalfWidth - NormalizedWidth)

-- Get the group from cutoff measure
VAR CustomerGroup = [_01 Cutoff_Customer Pareto Segment]

-- Set color based on profit sign and group
VAR FillColor = 
  SWITCH(
      TRUE(),
      CustomerGroup = "A+" && Bar_Value >= 0, "#6A994E",    -- strong green
      CustomerGroup = "A+" && Bar_Value < 0,  "#BC4749",    -- strong red
      CustomerGroup <> "A+" && Bar_Value >= 0, "#B5CCA7",   -- light green
      CustomerGroup <> "A+" && Bar_Value < 0,  "#DEA3A4",   -- light red
      "#CCCCCC"  -- fallback (shouldn't happen)
  )

-- SVG structure
VAR SVG_Data_URL = "data:image/svg+xml;utf8,"
VAR SVG_Start = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 " & TotalWidth & " " & Height & "'>"

-- Zero axis line (vertical center)
VAR Zero_Axis = "<line x1='" & HalfWidth & "' y1='0' x2='" & HalfWidth & "' y2='" & Height & "' stroke='#888888' stroke-width='1' />"

-- Bar rectangle
VAR SVG_Bar = "<rect fill='" & FillColor & "' x='" & Bar_X & "' y='0' width='" & NormalizedWidth & "' height='" & Height & "' />"

VAR SVG_End = "</svg>"

RETURN
IF(
  IsTotal,
  BLANK(),
  SVG_Data_URL & SVG_Start & Zero_Axis & SVG_Bar & SVG_End
)

Dynamic Selected SVG Bars

DAX
_01 Dynamic Selected SVG Bars = 
VAR SelectedMeasure = SELECTEDVALUE('Sort By'[Measure])
VAR SVGResult = 
  SWITCH(
      SelectedMeasure,
      "Total Transactions", [_01 SVG Pareto Bar Chart_Total Transactions],
      "Avg. Order Value", [_01 SVG Pareto Bar Chart_AOV],
      "Total Order Value", [_01 SVG Pareto Bar Chart_Total Order Value],
      "Total Items", [_01 SVG Pareto Bar Chart_Total Quantity],
      "Total Profit", [_01 SVG Pareto Bar Chart_Total Profit],
      "Avg. Items per Order", [_01 SVG Pareto Bar Chart_AIPO],
      BLANK()
  )
RETURN
  IF(ISBLANK(SVGResult), BLANK(), SVGResult & "")

Pareto Highlight Bars

DAX
Pareto highlight bars = BLANK()

Customer Segment (Hide the Total)

DAX
Customer Segment (No Total) = 
IF (
  ISINSCOPE('Table_RFM Analysis'[Customer Name]),
  VALUES('Table_RFM Analysis'[Customer Segment]),
  BLANK()
)

Dynamic Text/Subtitle Displaying Filter Selections

DAX
_01 Dynamic Text/Subtitle (Multi-Select) = 
-- Configuration constants
VAR LineBreak = UNICHAR(10)
VAR ExcludeThreshold = 3  -- Show "excluding" format when 3 or fewer items are unselected
VAR MaxDisplayItems = 4   -- Maximum items to show before truncating with "and X more"

-- Location filtering logic with enhanced length management
VAR IsRegionFiltered = ISFILTERED('Superstore'[Region])
VAR IsStateFiltered = ISFILTERED('Superstore'[State])

VAR SelectedLocation = 
  IF(IsRegionFiltered,
      -- Region is filtered, check state logic
      IF(IsStateFiltered,
          -- Both Region and State are filtered
          VAR AllStatesInRegion = CALCULATETABLE(
              VALUES('Superstore'[State]),
              ALLEXCEPT('Superstore', 'Superstore'[Region])
          )
          VAR SelectedStates = VALUES('Superstore'[State])
          VAR UnselectedStates = EXCEPT(AllStatesInRegion, SelectedStates)
          VAR UnselectedStateCount = COUNTROWS(UnselectedStates)
          VAR TotalStatesInRegion = COUNTROWS(AllStatesInRegion)
          VAR SelectedStateCount = COUNTROWS(SelectedStates)
          VAR SelectedRegion = CONCATENATEX(VALUES('Superstore'[Region]), 'Superstore'[Region], ", ")
          
          VAR LocationResult = 
              IF(UnselectedStateCount = 0,
                  -- All states selected, show only region
                  SelectedRegion,
                  IF(UnselectedStateCount <= ExcludeThreshold && UnselectedStateCount < TotalStatesInRegion,
                      -- Few states unselected, show "excluding" format
                      SelectedRegion & " (excluding " & CONCATENATEX(UnselectedStates, 'Superstore'[State], ", ") & ")",
                      -- Many states unselected, check if we should truncate selected states
                      IF(SelectedStateCount <= MaxDisplayItems,
                          -- Show all selected states
                          SelectedRegion & " - " & CONCATENATEX(SelectedStates, 'Superstore'[State], ", "),
                          -- Truncate with "and X more" format
                          VAR FirstStates = CONCATENATEX(
                              TOPN(MaxDisplayItems, SelectedStates, 'Superstore'[State], ASC),
                              'Superstore'[State], ", "
                          )
                          VAR RemainingCount = SelectedStateCount - MaxDisplayItems
                          RETURN SelectedRegion & " - " & FirstStates & " and " & RemainingCount & " more"
                      )
                  )
              )
          RETURN LocationResult,
          
          -- Only Region filtered
          VAR SelectedRegionCount = COUNTROWS(VALUES('Superstore'[Region]))
          VAR RegionText = CONCATENATEX(VALUES('Superstore'[Region]), 'Superstore'[Region], ", ")
          RETURN 
              IF(SelectedRegionCount <= MaxDisplayItems,
                  RegionText,
                  VAR FirstRegions = CONCATENATEX(
                      TOPN(MaxDisplayItems, VALUES('Superstore'[Region]), 'Superstore'[Region], ASC),
                      'Superstore'[Region], ", "
                  )
                  VAR RemainingRegions = SelectedRegionCount - MaxDisplayItems
                  RETURN FirstRegions & " and " & RemainingRegions & " more"
              )
      ),
      IF(IsStateFiltered,
          -- Only State filtered
          VAR SelectedStateCount = COUNTROWS(VALUES('Superstore'[State]))
          VAR StateText = CONCATENATEX(VALUES('Superstore'[State]), 'Superstore'[State], ", ")
          RETURN 
              IF(SelectedStateCount <= MaxDisplayItems,
                  StateText,
                  VAR FirstStates = CONCATENATEX(
                      TOPN(MaxDisplayItems, VALUES('Superstore'[State]), 'Superstore'[State], ASC),
                      'Superstore'[State], ", "
                  )
                  VAR RemainingStates = SelectedStateCount - MaxDisplayItems
                  RETURN FirstStates & " and " & RemainingStates & " more"
              ),
          
          -- No location filter
          "All Locations"
      )
  )

-- Segment filtering logic (simple, no sub-segments)
VAR IsSegmentFiltered = ISFILTERED('Superstore'[Segment])
VAR SelectedSegment = 
  IF(IsSegmentFiltered,
      VAR SelectedSegmentCount = COUNTROWS(VALUES('Superstore'[Segment]))
      VAR SegmentText = CONCATENATEX(VALUES('Superstore'[Segment]), 'Superstore'[Segment], ", ")
      RETURN 
          IF(SelectedSegmentCount <= MaxDisplayItems,
              SegmentText,
              VAR FirstSegments = CONCATENATEX(
                  TOPN(MaxDisplayItems, VALUES('Superstore'[Segment]), 'Superstore'[Segment], ASC),
                  'Superstore'[Segment], ", "
              )
              VAR RemainingSegments = SelectedSegmentCount - MaxDisplayItems
              RETURN FirstSegments & " and " & RemainingSegments & " more"
          ),
      "All Segments"
  )

-- Category filtering logic with enhanced length management
VAR IsCategoryFiltered = ISFILTERED('Superstore'[Category])
VAR IsSubCategoryFiltered = ISFILTERED('Superstore'[Sub-Category])

VAR SelectedCategory = 
  IF(IsCategoryFiltered,
      -- Category is filtered, check sub-category logic
      IF(IsSubCategoryFiltered,
          -- Both Category and Sub-Category are filtered
          VAR AllSubCategoriesInCategory = CALCULATETABLE(
              VALUES('Superstore'[Sub-Category]),
              ALLEXCEPT('Superstore', 'Superstore'[Category])
          )
          VAR SelectedSubCategories = VALUES('Superstore'[Sub-Category])
          VAR UnselectedSubCategories = EXCEPT(AllSubCategoriesInCategory, SelectedSubCategories)
          VAR UnselectedSubCount = COUNTROWS(UnselectedSubCategories)
          VAR TotalSubCategoriesInCategory = COUNTROWS(AllSubCategoriesInCategory)
          VAR SelectedSubCount = COUNTROWS(SelectedSubCategories)
          VAR SelectedCategoryText = CONCATENATEX(VALUES('Superstore'[Category]), 'Superstore'[Category], ", ")
          
          VAR CategoryResult = 
              IF(UnselectedSubCount = 0,
                  -- All sub-categories selected, show only category
                  SelectedCategoryText,
                  IF(UnselectedSubCount <= ExcludeThreshold && UnselectedSubCount < TotalSubCategoriesInCategory,
                      -- Few sub-categories unselected, show "excluding" format
                      SelectedCategoryText & " (excluding " & CONCATENATEX(UnselectedSubCategories, 'Superstore'[Sub-Category], ", ") & ")",
                      -- Many sub-categories unselected, check if we should truncate
                      IF(SelectedSubCount <= MaxDisplayItems,
                          -- Show all selected sub-categories
                          SelectedCategoryText & " - " & CONCATENATEX(SelectedSubCategories, 'Superstore'[Sub-Category], ", "),
                          -- Truncate with "and X more" format
                          VAR FirstSubCategories = CONCATENATEX(
                              TOPN(MaxDisplayItems, SelectedSubCategories, 'Superstore'[Sub-Category], ASC),
                              'Superstore'[Sub-Category], ", "
                          )
                          VAR RemainingSubCount = SelectedSubCount - MaxDisplayItems
                          RETURN SelectedCategoryText & " - " & FirstSubCategories & " and " & RemainingSubCount & " more"
                      )
                  )
              )
          RETURN CategoryResult,
          
          -- Only Category filtered
          VAR SelectedCategoryCount = COUNTROWS(VALUES('Superstore'[Category]))
          VAR CategoryText = CONCATENATEX(VALUES('Superstore'[Category]), 'Superstore'[Category], ", ")
          RETURN CategoryText
      ),
      IF(IsSubCategoryFiltered,
          -- Only Sub-Category filtered
          VAR SelectedSubCount = COUNTROWS(VALUES('Superstore'[Sub-Category]))
          VAR SubCategoryText = CONCATENATEX(VALUES('Superstore'[Sub-Category]), 'Superstore'[Sub-Category], ", ")
          RETURN 
              IF(SelectedSubCount <= MaxDisplayItems,
                  SubCategoryText,
                  VAR FirstSubCategories = CONCATENATEX(
                      TOPN(MaxDisplayItems, VALUES('Superstore'[Sub-Category]), 'Superstore'[Sub-Category], ASC),
                      'Superstore'[Sub-Category], ", "
                  )
                  VAR RemainingSubCount = SelectedSubCount - MaxDisplayItems
                  RETURN FirstSubCategories & " and " & RemainingSubCount & " more"
              ),
          
          -- No category filter
          "All Categories"
      )
  )

-- Year filtering logic
VAR SelectedYear = SELECTEDVALUE(DimDate[Year], "All Years")

-- Return multi-line format consistently
RETURN 
  "Year: " & SelectedYear & LineBreak & 
  "Location: " & SelectedLocation & LineBreak & 
  "Segment: " & SelectedSegment & LineBreak &
  "Category: " & SelectedCategory

Dynamic Matrix Title Displaying Number of Customers Within “A+” Group

DAX
_01 Pareto A+ Summary (Threshold) = 
VAR ParetoThreshold = [Pareto Value]  -- e.g., 0.15 for 15%
VAR SelectedMeasureName = SELECTEDVALUE('Selected Metric'[Measure])

-- Calculate A+ customers count
VAR APlusCustomers = 
  SUMX(
      FILTER(
          VALUES('Table_RFM Analysis'[Customer Name]),
          [_01 Cutoff_Customer Pareto Segment] = "A+"
      ),
      1
  )

-- Convert threshold to percentage for display
VAR ThresholdPercentage = ParetoThreshold * 100

-- Determine singular or plural form
VAR CustomerText = IF(APlusCustomers <= 1, "customer", "customers")

RETURN
IF(
  NOT ISBLANK(APlusCustomers) && APlusCustomers > 0,
  FORMAT(ThresholdPercentage, "0.0") & "% of " & SelectedMeasureName & " is generated by " & FORMAT(APlusCustomers, "#,0") & " " & CustomerText,
  BLANK()
)

Dynamic Matrix Subtitle Displaying Selected Metric from the Slicer

DAX
_01 Display Text_Selected Metric = 
VAR SelectedMetric = SELECTEDVALUE('Sort By'[Measure])
VAR MetricText = 
  SWITCH(
      SelectedMetric,
      "Total Transactions", "Total Transactions",
      "Avg. Order Value", "Average Order Value (expressed in USD)", 
      "Total Order Value", "Total Order Value (expressed in USD)",
      "Total Items", "Total Items",
      "Total Profit", "Total Profit (expressed in USD)",
      "Avg. Items per Order", "Average Items per Order",
      "No Selection"
  )
RETURN
  IF(
      MetricText <> "No Selection",
      "Selected Metric: " & MetricText,
      "No metric selected"
  )

Documentation

Understanding the Underlying Principle

This approach works great for your matrix or table visuals. The core idea is simple: we want to categorize customers into two groups: “A+” for the “vital few” and “Others” for the “trivial many.” This helps us understand exactly who these high-contributing customers are and how many of them drive our company’s success.

How to Achieve This?

First, we need to rank our customers. But what’s the basis for this ranking? It’s all about your chosen metric. For example, if you want to rank customers by their total order value, the customers with the highest values will be at the top. To avoid duplicate ranks, we’ll also use a secondary criterion like customer IDs to ensure each customer gets a unique rank (more on this later in the article).

Once each customer has a rank, we need another variable to assign them to either the “A+” or “Other” group. This is where the percentage of cumulative value comes in. Let’s say we set our Pareto threshold at 20% using “Total Order Value” as our metric. Your matrix will then dynamically identify and group the top customers who collectively contribute to 20% of the total order value.


In this documentation, you'll learn to construct a dynamic customer Pareto dashboard. This powerful tool will enable you to analyze your company's "vital few" and "trivial many" customers based on a selected metric and an adjustable threshold.

Watch the tutorial:

References

View all articles