Documentation menu

Standings table block

A ranked season table for a sports team or club: team name, played/won/drawn/lost, points for/against, and points, sorted by points descending with the top three rows marked. Unlike every block on the analytics & chart blocks page, this one never renders as an image — a real HTML <table> is the entire block, in every email client including Outlook.

How it works

Every one of the thirteen chart blocks in the analytics family renders a server-generated raster image with a text fallback alongside it. That's because a bar chart or a line graph genuinely has no equivalent HTML markup that displays consistently across clients. A ranked table doesn't have that problem: sorted rows and columns are exactly what <table> markup already renders natively and consistently everywhere, Outlook's Word-based engine included. There's no image-plus-fallback split here — one render path, used unconditionally.

Rows are typed in directly in the inspector's row editor, one team per row. There's no live data-source binding yet, so you update the block by hand after each match — the same manual-update model a KPI scorecard's authored value uses before it's bound to a data source. Sorting happens at render time: rows are sorted by the Points column descending, and ties keep their originally authored order rather than being reshuffled, since Array.prototype.sort is a stable sort. The top three rows after sorting get a rank badge (🥇🥈🥉) instead of a plain number; every row below third gets a plain rank number.

Points is always a number you fill in yourself. It is never computed from wins/draws/losses, because leagues award points differently (a straight 3-point win, bonus points for a high-scoring loss, and so on), and hard-coding one formula would be wrong for most sports.

Turn off Show draws column for a sport that has none, like basketball or most tennis leagues. Doing so removes the "D" column from both the header and every row, rather than just hiding it visually. Highlight team matches a row's Team value case-insensitively and, when it matches, bolds the row's text and tints its background. That's useful for a parent digest, so a family can spot their kid's team at a glance without scanning the whole table.

If no rows have a non-empty team name, the block still renders its title and card chrome, with a plain "Add at least one team to render the standings table" notice instead of an empty table. That's the same "don't throw mid-keystroke while building" convention every other analytics block's empty-data branch follows.

Standings table is pure content: there's nothing to answer, so — like Venue — it never appears in the responses dashboard, CSV export, or click heatmap. Nothing on it is a link.

Configurable fields:

  • Title — shown above the table; omit it and only the table renders.
  • Teams — the row list: Team, Played, Won, Drawn, Lost, Points for, Points against, Points.
  • Show draws column — toggles the "D" column on/off.
  • Highlight team (exact name match) — case-insensitive match against the Team column.
  • Background color, padding, border and border radius on the card.
  • Title color/size, and table text color/size.

Examples

Subject

Season standings after Week 10

The "Sports team" project purpose starts a new project with a Standings table already in place alongside Venue, Add to calendar, and RSVP. Send a weekly digest that updates the same block with the latest results — see Sports teams & clubs for the full pattern, including how to keep one shared contact list across multiple squads or age-groups. A league newsletter recaps a full division's results in one email, with Highlight team left blank since there's no single "home" team to call out. A youth club sends the same standings email to every parent, with Highlight team set per-squad through a visibleWhen audience filter rather than sending a separate email per team.

What the static fallback looks like

<div style="margin:12px 0;background-color:#ffffff;padding:16px;border-radius:8px">
  <p style="margin:0 0 8px;font-weight:600;font-size:15px;color:#111827">Standings</p>
  <table style="width:100%;border-collapse:collapse;margin-top:4px">
    <tr>
      <th style="text-align:left;padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:600">#</th>
      <th style="text-align:left;padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:600">Team</th>
      <th style="text-align:right;padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:600">Pts</th>
    </tr>
    <tr style="background-color:#eef2ff">
      <td style="padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:700">🥇 1</td>
      <td style="padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:700">Eagles</td>
      <td style="text-align:right;padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:700">23</td>
    </tr>
  </table>
</div>

This is the block's real, only render — there's no separate fallback tier, since a table's the same markup in every client. (Played/Won/Drawn/Lost/PF/PA columns are omitted here for brevity; the row with the medal shows the highlighted-team tint applied to the same row.)