Documentation menu

Pie / donut chart block

One value per category, shown as share of a whole — a pie, or in donut mode a ring with room for a headline number in the middle.

How it works

The chart renders as a single server-generated PNG (no client-side chart library, no JavaScript) with an always-visible legend and an HTML data table beneath it — the same non-negotiable pairing every chart in this family commits to. Unlike the bar/line chart's legend, a pie's legend always renders regardless of slice count: a pie's own title can't name an individual slice the way a lone bar/line series can borrow the block's title, so even a single-slice pie needs its legend to say what that slice is. Each legend entry shows the slice's label alongside its percentage of the total, and the data table adds a third column — exact value, alongside category and percent — so both the rounded at-a-glance share and the precise number are always available as text.

The authoring shape differs from bar/line's fixed series slots: one row per category, each with a single Value and an optional per-slice Color override — there's no second or third series, since a pie has exactly one measure per category by definition. Rows with a blank category or a zero/negative value are skipped entirely rather than drawn as an empty wedge.

Past 8 slices, the smallest ones fold together into a single synthetic "Other" wedge instead of the chart getting unreadably thin — a pie past roughly 8 slices stops being able to show each one at a distinguishable angle, so the fold keeps every drawn wedge legible. The fold keeps the largest 7 slices by value and combines everything else into "Other"; the legend and data table both reflect the same fold, so what you read next to the chart always matches what's actually drawn in it — nothing is quietly hidden from the legend while still counted in the image, or vice versa.

Donut mode turns the pie into a ring; only then do the Center value and Center label fields do anything, giving you a KPI-style number in the middle of the ring (an author-typed pair, not derived from the slice values — the same "authored, not inferred" precedent as the KPI scorecard's own Δ direction). A solid pie has no hole to put text into, so these fields are simply inert until Donut is switched on.

Configurable fields:

  • Chart title — shown above the image.
  • Donut (hollow center) toggle.
  • Data — the row-list (Category + Value + optional Color).
  • Center value / Center label — donut-only.
  • Background color, padding, border, border radius on the card.
  • Independent color/font-size pairs for the title and the legend/table text.

A pie chart can also bind its slices to a connected data source instead of authoring rows — a Group by field (each distinct value becomes a slice) plus one Value field and aggregate (Sum, Average, Count, or Latest row). An optional filter can reference recipient merge tags for a per-recipient slice of the same source. See Binding charts to real data for the full mechanics, including the campaign-response-results mode — plotting a past poll's or rating's own vote distribution directly, for example.

Examples

Subject

Where your traffic is coming from

A post-campaign report can pie-chart a poll's vote distribution by binding directly to that campaign's response results — no data source needed, just picking the poll from the picker — so the report always reflects the poll's current tally. A subscription recap might use a donut chart for "plan mix" (Free/Starter/Pro/Business as slices) with the center showing total active accounts as a KPI-style number inside the ring itself. A support digest with a dozen ticket categories relies on the automatic "Other" fold to keep the chart readable, trusting the data table underneath to still list every individual category by exact count.

What the static fallback looks like

<div style="margin:12px 0;padding:16px;background-color:#ffffff;border-radius:8px">
  <p style="margin:0 0 8px;font-weight:600;font-size:15px;color:#111827">Plan mix</p>
  <img src="https://mailinapp.com/api/analytics/chart?d=eyJ0eXBlIjoi...&s=3f9a2b1c..." width="320" height="320"
       alt="Donut chart: Free 420 (52%), Starter 210 (26%), Pro 175 (22%)"
       style="display:block;max-width:100%;height:auto;margin:8px 0" />
  <div style="display:flex;flex-wrap:wrap;gap:12px;margin:0 0 6px">
    <span style="font-size:12px;color:#6b7280">
      <span aria-hidden="true" style="display:inline-block;width:10px;height:10px;background-color:#4f46e5"></span>
      Free (52%)
    </span>
  </div>
  <table style="width:100%;border-collapse:collapse;margin-top:4px">
    <tr>
      <th style="text-align:left;padding:4px 8px;font-weight:600;font-size:12px;color:#6b7280">Category</th>
      <th style="text-align:left;padding:4px 8px;font-weight:600;font-size:12px;color:#6b7280">Value</th>
      <th style="text-align:left;padding:4px 8px;font-weight:600;font-size:12px;color:#6b7280">Percent</th>
    </tr>
    <tr>
      <td style="text-align:left;padding:4px 8px;font-size:12px;color:#6b7280">Free</td>
      <td style="text-align:left;padding:4px 8px;font-size:12px;color:#6b7280">420</td>
      <td style="text-align:left;padding:4px 8px;font-size:12px;color:#6b7280">52%</td>
    </tr>
  </table>
</div>

The legend and table both carry the exact same label/value/percent for every slice — deliberately duplicated, since the legend is quick-scan and the table is the precise source.