Funnel Chart

A funnel chart shows how a number shrinks as people move through the steps of a process. Here, a month in an online store, from 10,000 visits to 2,300 payments.

  • Try it:
  • Click a legend item to hide a stage
  • Hover a legend item to find its stage
Get the code JavaScript React, Vue, Angular, Svelte JSON
About this chart

When a funnel chart works

A funnel fits a process where each step keeps only part of the one before: visitors who become buyers, applicants who get hired. The narrowing shows at once where most people drop out, here between viewing a product and adding it to the cart.

Good for

  • Sales and sign-up funnels
  • Hiring, from applications to offers
  • Finding the step where most people leave

Think twice when

  • Steps that aren’t a sequence: a bar chart compares them better
  • Two funnels to compare, like this month and last: try grouped bars
  • Counts that can grow from one step to the next: a funnel reads as always narrowing
For developers

Get the code.

Built with amCharts 5, a JavaScript library. The JavaScript includes your theme and renderer (canvas or SVG); the JSON also follows the changes you make with the controls.

// Create root element
// https://docs.amcharts.com/v5/getting-started/#root-element
var root = am5.Root.new("chartdiv");

// Set themes
// https://docs.amcharts.com/v5/concepts/themes/
root.setThemes([
  am5themes_Animated.new(root),
  am5themes_Responsive.new(root)
]);

// Create chart
// https://docs.amcharts.com/v5/charts/percent-charts/sliced-chart/
var chart = root.container.children.push(am5percent.SlicedChart.new(root, {
  layout: root.verticalLayout // the legend goes below the funnel
}));

// Create series
// https://docs.amcharts.com/v5/charts/percent-charts/sliced-chart/#series
var series = chart.series.push(am5percent.FunnelSeries.new(root, {
  // labels sit on the slices instead of in a column beside the funnel
  alignLabels: false,
  orientation: "vertical", // the funnel runs from top to bottom
  valueField: "value",
  categoryField: "category"
}));

// Each stage shows how many people got that far
series.labels.template.set("text", "{category}: {value}"); // as "Paid: 2,300"

// Set data: a month in an online store, from first visit to payment
// https://docs.amcharts.com/v5/charts/percent-charts/sliced-chart/#setting-data
series.data.setAll([
  { value: 10000, category: "Visited the store" },
  { value: 7600, category: "Viewed a product" },
  { value: 4200, category: "Added to cart" },
  { value: 2900, category: "Started checkout" },
  { value: 2300, category: "Paid" }
]);

// Play initial series animation
// https://docs.amcharts.com/v5/concepts/animations/#animation-of-series
series.appear();

// Create legend
// https://docs.amcharts.com/v5/charts/percent-charts/legend-percent-series/
var legend = chart.children.push(am5.Legend.new(root, {
  centerX: am5.p50, // the legend's middle...
  x: am5.p50,       // ...at the middle of the chart
  marginTop: 15,    // 15px of space above...
  marginBottom: 15  // ...and below the legend
}));

// The slices already show the numbers, so the legend lists the stages only
legend.valueLabels.template.set("forceHidden", true);

legend.data.setAll(series.dataItems);

// Make stuff animate on load
// https://docs.amcharts.com/v5/concepts/animations/
chart.appear(1000, 100);