Funnel chart

Stages from top to bottom, each as wide as its value, with the share that made it from the stage before.

A report preset. Reference: Report presets. More workflows: n8n guide.

Funnel chart of four stages from visitors to paying customers, with the value and the percentage of the previous stage on each
The funnel preset with the config below.

Who this is for

People who build n8n workflows, and agents that send a conversion report to Slack or email: visitors to signups to customers, leads to deals, applications to hires. You have one number per stage.

What the funnel preset draws

Send a bar config with one dataset: data is the value of each stage and labels their names. Up to 12 stages, none of them negative. A stage that is not a number has no bar and shows a dash. A stage after an empty one has no share.

The config

{
  "type": "bar",
  "data": {
    "labels": ["Visitors", "Signups", "Trials", "Paying"],
    "datasets": [{ "data": [12400, 3100, 930, 214] }]
  },
  "options": {
    "plugins": {
      "title": { "display": true, "text": "Signup funnel, October" },
      "chartpng": { "preset": "funnel" }
    }
  }
}

The preset and its options live under options.plugins.chartpng:

OptionWhat it does
preset"funnel".
prefixA string put before each value, such as "$".
suffixA string put after each value, such as " users".
valuesfalse hides the values and the shares and leaves the bars.

Anything your config sets wins over the preset, the same as with the theme. The bar colour is the first colour of the theme, or the backgroundColor of the dataset.

A config that does not fit is a 400 whose message says why, such as preset funnel needs type bar or preset funnel needs stage values of zero or more; stage 2 is negative.

The GET URL

The whole config goes in c, URL-encoded. Paste the URL in an <img>, an email or a Slack image block. Past a few thousand characters, use a POST.

https://chartpng.dev/chart?c=%7B%22type%22%3A%22bar%22%2C%22data%22%3A%7B%22labels%22%3A%5B%22Visitors%22%2C%22Signups%22%2C%22Trials%22%2C%22Paying%22%5D%2C%22datasets%22%3A%5B%7B%22data%22%3A%5B12400%2C3100%2C930%2C214%5D%7D%5D%7D%2C%22options%22%3A%7B%22plugins%22%3A%7B%22title%22%3A%7B%22display%22%3Atrue%2C%22text%22%3A%22Signup%20funnel%2C%20October%22%7D%2C%22chartpng%22%3A%7B%22preset%22%3A%22funnel%22%7D%7D%7D%7D&w=800&h=450&dpr=2

The same chart with a POST

A POST takes the same fields in a JSON body. Use it from a server, or whenever the URL gets too long. The response is the PNG.

curl https://chartpng.dev/chart \
  -H "Content-Type: application/json" \
  -d '{"c": {"type":"bar","data":{"labels":["Visitors","Signups","Trials","Paying"],"datasets":[{"data":[12400,3100,930,214]}]},"options":{"plugins":{"title":{"display":true,"text":"Signup funnel, October"},"chartpng":{"preset":"funnel"}}}}, "w": 800, "h": 450, "dpr": 2}' \
  -o funnel-chart.png

In n8n

Build the config in a Code node and call https://chartpng.dev/chart with the HTTP Request node, as then8n guide shows. The templateweekly KPI report to Slack builds a KPI and a comparison and posts both images in one Slack message.

If a model wrote the config

Models often send near-JSON: a code fence around it, single quotes, a trailing comma. ChartPNG repairs the usual cases and lists what it changed in the X-ChartPNG-Fixes response header. Functions written as text are removed, never run. See lenient parsing.

Other report templates