Skip to content

Query Widget YAML

This page is the Query Widget YAML field reference. For when to use a Query Widget, creating steps, refresh behavior, and troubleshooting, see Query Widgets. Put joins and reusable SQL in a Query Dataset.

Keep query as the last top-level key.

schemaVersion: 1
source:
type: dataset
source: 46b0bbe8-619a-4b23-bc44-f11842775640
display:
type: metric
value: ticket_count
timezone: America/Chicago
parameters:
- name: board_values
filterVariable: 32b69796-14b3-48d1-a9a7-d196b91752c1
drilldownQuery: |-
select ticket_number, ticket_subject
from source
where board_name in $board_values
query: |-
select count(*) as ticket_count
from source
where board_name in $board_values

The editor Copy AI Instructions button copies authoring guidance you can paste into a chat along with the current YAML, columns, and any preview error.

Field Required Notes
schemaVersion yes Must be 1
source yes One Dataset or Query Dataset. SQL always sees it as source
source.type yes dataset or queryDataset
source.source yes UUID from Browse Sources
display yes Maps result columns to a chart, table, metric, gauge, or funnel
timezone no IANA timezone. Source datetimes are localized before the Widget Query
parameters no Filter Variable bindings
drilldownQuery no Optional detail SQL. Same source and parameter rules as query
query yes Read-only Widget Query. Keep this last

Unknown top-level keys are rejected. Do not wrap the definition in a widget object.

Exactly one source object:

source:
type: queryDataset
source: 5a242d39-195c-41da-a99b-93b402a4325b
source.type Use when
dataset The widget reads one synced Dataset
queryDataset The widget reads a saved Query Dataset result

modifiedDataset and joinedDataset are not valid Query Widget sources. If you need filtered, joined, or multi-source shaping, create a Query Dataset first.

Do not use a sources list or source aliases in a Query Widget. The Widget Query always selects from source.

Each parameter has a SQL name and a Filter Variable UUID. Use $name in SQL.

parameters:
- name: board_values
filterVariable: 32b69796-14b3-48d1-a9a7-d196b91752c1
Field Required Notes
name yes Starts with a letter or underscore; letters, numbers, underscores
filterVariable yes Filter Variable UUID for the same company
where board_name in $board_values
  • Use in for multi-select Filter Variables.
  • Use = for single-select Filter Variables.
  • Every $name in SQL must be declared.
  • Empty multi-select values become an empty list; empty single-select values become null.
  • Parameters are typed values, not spliced SQL text.

{{ column_name }} placeholders do not bind filters. Those slots are for metric text and columnLinks templates. columnLinks can also use {{ conn.variable_name }} for non-secret values from the source integration config. In drilldownQuery, {{ x }} is the clicked chart category.

timezone is an IANA name such as America/Chicago or UTC. If you omit it, the definition defaults to UTC (new editor drafts usually fill in your timezone).

Datetime columns from the source are converted into this timezone before the Widget Query runs. Date helpers such as dashboard_date_filter() use the same timezone.

query must be one read-only SELECT from exactly one relation named source.

Allowed: filters, grouping, aggregates, case, ordering, limits, declared $parameters, and dashboard date helpers.

Not allowed: joins, CTEs, subqueries, unions, selecting from anything other than source, or changing data.

Table displays cap the main Widget Query at 1,000 rows. Drilldown is not capped at 1,000 rows. Prefer filters, aggregates, or LIMIT so the truncated page is the set you intend.

Helper Behavior
dashboard_date_filter(column) Uses the active dashboard date range. Allows all rows when no dashboard date filter is set
dashboard_date_filter_or_default(column, start, end) Uses the dashboard date filter when present; otherwise applies the fallback start and end
dashboard_start_date(default) Active dashboard start, or the default
dashboard_end_date(default) Active dashboard end, or the default
runtime_start_date('this month') Concrete relative start phrase such as today, this week, or this month
runtime_end_date('this month') Matching relative end phrase

Do not pass 'dashboard' to runtime_start_date or runtime_end_date. Opt into the dashboard filter with the helpers above.

Activity and flow widgets should use the selected range. Point-in-time widgets should use the selected end date and may include history before the start date.

drilldownQuery is optional. When set, it must follow the same Widget Query rules: one SELECT from source, no joins or CTEs, same Query Parameters.

drilldownQuery: |-
select ticket_number, ticket_subject, board_name
from source
where board_name = {{ x }}
and dashboard_date_filter(created_at)
  • Mirror the main query’s filters and date window.
  • {{ x }} is replaced with the clicked display.x value on charts.
  • Table widgets open drilldown from the footer expand control, not row clicks on the dashboard.
  • Chart and metric widgets open drilldown from a click on the widget body.
  • Drilldown cells stay raw until display.columnFormats adds design cues. That includes format: date, datetime, and time with dateStyle / timeStyle for timestamp columns.

display maps Widget Query result columns onto the rendered widget. It does not reshape data. Put shaping in SQL.

display.type must be one of:

  • bar
  • line
  • pie
  • metric
  • table
  • gauge
  • funnel

Column mappings use the aliases your Widget Query returns.

Required: x and at least one y.

display:
type: bar
x: facility
y:
- open_shift_pct
seriesBy: shift_type
yLabel: Uncovered shift rate
Field Required Notes
x yes Category or time column
y yes One or more numeric result column names. A single string is allowed. Do not use series objects; put series labels in columnLabels
seriesBy no Category column that splits long-form rows into series. Bar and line only. Requires exactly one y. Must differ from x
seriesMode no grouped or stacked
showStackTotals no Stack total labels when stacked
horizontalBars no Bar charts only
areaFill no Line charts only
barGap no Bar gap string such as "30%"
xLabel / yLabel no Axis titles
yAxisMin / yAxisMax no Numeric axis bounds. Max must be greater than min
yAxisLogScale no Logarithmic y-axis
xLabelRotation no Integer from -90 to 90
overlay no Number Overlay object for bar and line only. Omit for no overlay. Partial overlay fails validation

Paints one reduced number on a bar or line chart from the same Widget Query rows. This is not a Metric Display: no comparison, icon, tone, layout, or templates. Overlay graphic is applied after display.option so it wins.

display:
type: line
x: month
y:
- revenue
overlay:
value: revenue
reducer: last
placement: topRight
size: large
label: Current
Field Required Notes
value yes Numeric result column to reduce
reducer yes last, sum, avg, min, max, or first. first/last follow Widget Query row order; include ORDER BY when a specific row is intended. Prefer sum, avg, min, or max when order does not matter. Skips non-numeric cells
placement no center, top, right, bottom, left, topLeft, topRight (default), bottomLeft, bottomRight. Always paints; never auto-hides or auto-moves
size no small, medium (default), or large. Compact cards step down one size
label no Optional static label shown with the number
accessibleText no auto (default) or value. Independent of the visible label

If no numeric value remains, the overlay shows a muted em dash. Truncated results still reduce the returned rows and keep the header pill.

The Widget Query must return at most one row for each (x, seriesBy) pair. Aggregate in SQL, or use multiple y columns for wide data:

display:
type: bar
x: board_name
y:
- open_count
- closed_count
yLabel: Tickets

Required: label and value. Do not use x or y.

display:
type: pie
label: status_name
value: ticket_count
donut: true
pieLabelFormat: labelAndPercentage
display:
type: funnel
label: status_name
value: ticket_count
Field Required Notes
label yes Slice or stage name column
value yes Numeric column
donut no Pie only. Omit or true for a donut; false for a solid pie
pieRadius no One radius string or [inner, outer] such as ["40%", "70%"]
pieLabelFormat no label, value, percentage, labelAndValue, or labelAndPercentage

Required: value (result column from the first result row). The column may be numeric, text, date, time, or datetime.

display:
type: metric
value: ticket_count
label: Tickets opened
subtitle: '{{ period_label }}'
icon: zap
tone: info
comparison:
value: prev_period_count
label: vs previous period
rounding: 0
abbreviatedNumbers: true

Clock-time metrics should put a real time on display.value. Prefer a TIMESTAMP/TIME column with valueFormat:

display:
type: metric
value: estimated_finish_at
valueFormat:
format: time
timeStyle: short
hour12: true

A SQL-formatted text column such as 5:14 PM can also be display.value with no valueFormat. format: time does not convert a decimal hour such as 17.25.

Field Required Notes
value yes One result column name. Not a template, and not a literal %. May be numeric, text, date, time, or datetime
valueFormat no Metric only. Formatting for the primary value. Same fields as columnFormats (format, rounding, timeStyle, hour12, …). Does not apply to subtitle slots
label no Short Metric Label above the value. Omit it when it would repeat the widget title
subtitle no Supporting text. May include {{ column_name }} slots
icon / iconColumn no Lucide icon name, or a first-row column that chooses the icon
tone / toneColumn no positive, negative, neutral, info, or warning
layout no stacked, split, or centered. Metric only
comparison no Metric only. Needs comparison.value or comparison.text

label, subtitle, and comparison.text can use Metric Templates: {{ column_name }} slots filled from the first row. Shape the text in SQL; templates do not evaluate expressions.

The widget title is the full headline. Use display.label only as a short eyebrow when it adds meaning the title does not already carry. Put comparison and timeframe wording in comparison.label and subtitle.

When comparison.value and display.value are both numeric, the widget shows a percent-change chip plus the baseline. By default, an increase is positive (green) and a decrease is negative (red). Set comparison.favorableDirection to down when a decrease is the good outcome, such as outstanding balance or error counts. Use comparison.tone or comparison.toneColumn for a fixed tone that overrides automatic polarity.

Required: value.

display:
type: gauge
value: completion_percent
min: 0
max: 100
percentSuffix: true
gaugeIntervalLabels:
- Low
- High
Field Required Notes
value yes Numeric column
min / max no Literal numbers or numeric column names. Literal max must be greater than literal min
gaugeIntervalLabels no Exactly two labels, shown at the min and max ends
percentSuffix no Append %

All table column mappings are optional. Omit columns to show every result column. If you set columns, the list must not be empty.

display:
type: table
columns:
- ticket_number
- ticket_subject
- last_email_age_minutes
columnFormats:
last_email_age_minutes:
rounding: 0
columnLinks:
ticket_number: "https://psa.example.com/tickets/{{ ticket_number }}"
Field Required Notes
columns no Ordered result columns to show
columnFormats no Per-column number, date, and text formats
columnLinks no Column to http(s) URL template. {{ column_name }} slots come from the row; {{ conn.variable_name }} slots come from the source integration config
columnAutoSort no alphabetical, reverseAlphabetical, calendarAscending, or calendarDescending. Off when omitted
columnLabels no Header text map for main-table and drilldown columns, including drilldown-only names. Prefer columnDefs.<column>.headerName when customizing columns
pinnedColumns no Prefer columnDefs.<column>.pinned. May name drilldown-only columns
fitToWidth no Columns stretch by default. Prefer gridOptions.autoSizeStrategy for advanced sizing

columnLabels, columnDefs, pinnedColumns, columnFormats, and columnLinks apply to matching columns in the main table and in drilldown, including columns that exist only in drilldownQuery. display.columns still lists the main Widget Query columns to show. When you omit columnLinks on a new widget, Resplendent copies link templates from the source Dataset—or from parent Datasets when the source is a Query Dataset—for columns in the Widget Query or drilldownQuery. Direct source columns and URL row slots are translated to their result aliases. A link is omitted if its linked column or another row slot it needs is not selected in that result; SELECT * keeps source names. Set columnLinks: {} to keep links off; that choice is not overwritten on later saves. Non-http(s) schemes are rejected as links at render time, so those cells remain plain text.

The main table query is capped at 1,000 rows. Use drilldownQuery for larger detail sets.

Table displays can also pass optional gridOptions and columnDefs for advanced grid behavior (pagination, pinned columns, cell classes). Prefer the typed fields above unless you need that extra control.

These options are fallbacks for every numeric result column used by the display. A matching columnFormats entry overrides the global setting wherever that column renders, including a metric primary value and numeric {{ column }} slots.

display:
type: table
columnFormats:
invoice_id:
format: text
invoice_total:
format: currency
currencyCode: USD
rounding: 2
win_rate_pct:
rounding: 1
percentSuffix: true
opened_at:
format: datetime
dateStyle: medium
timeStyle: short
Field Notes
rounding 0 to 6 decimal places
percentSuffix Append %
abbreviatedNumbers 1.2K / 3.4M / 5.6B
currencyPrefix Compatibility boolean that prepends $. Prefer format: currency plus currencyCode
format automatic, text, number, currency, percent, date, datetime, time, or scientific
currencyCode Three-letter code such as USD
prefix / suffix Literal affixes. Use prefix: '$' only when you want a literal dollar sign
useGrouping Set false to drop thousands separators on ID-like numbers
dateStyle / timeStyle short, medium, long, or full
hour12 12-hour clock when formatting times

For mixed units, format each exceptional column instead of one global format. If the primary metric is a percentage and the subtitle contains counts, omit global percentSuffix and set display.valueFormat.percentSuffix: true.

Field Notes
dataLabels Show formatted values on bars, points, slices, funnels, and gauges
legend Show or hide the legend
legendPosition top, right, bottom, or left
colors Ordered palette. Omit to keep the product theme
thresholds List of { value, color, label } entries. Label is optional
showTitle / title Optional in-display title. Metric displays hide this by default; prefer the widget title
noDataMessage Replaces the default empty-result text

display.option can hold extra chart styling as JSON. Do not put result data in option. Prefer typed display fields whenever one exists.

If a source column name contains a dot, quote it in SQL:

select count(*) as ticket_count
from source
where "board.name" = $board_values

Display fields use the output alias, without SQL quotes:

display:
type: metric
value: ticket_count

Alias dotted names in a Query Dataset when you can, so widgets can use simple names like board_name.