Inputs and Variables
Parameterize your report with document inputs and use variables in text and headers
Overview
Document inputs are the parameters readers supply before exporting a report — a date range, a customer, a region, a metric to break out by. They appear in the input bar above the page canvas, and they drive what the report's tables, charts, and text actually show.
Inputs are document-scoped. They're isolated from the dashboard's filter toolbar and controls, so a paginated report always runs against the values you configure for it. Changing a filter on another sheet has no effect on the report; changing an input here has no effect on the rest of the dashboard.
Two kinds of inputs
Filter-backed inputs narrow the data rows your sections return — dates, regions, accounts. Control-backed inputs change structural choices — which metric to show, what grain to roll up to, which option to bind to a SQL parameter. Use whichever matches the parameter you need.
Adding an input
Open the report and select the Inputs tab in the document inspector. Pick a field from your dataset (for a filter-backed input) or a control already defined on the dashboard (for a control-backed input). Semaphor creates a document-scoped input with an auto-generated alias you can rename.
The alias is what you reference in variables. Renaming an alias changes only the display label in the input bar — any {{alias}} references you've already written in text or headers continue to resolve to the same input.
Inputs don't inherit from the dashboard
Adding a filter to the dashboard's top filter bar doesn't add it as a document input. Each report defines its own inputs explicitly so it's reproducible — the same document, configured the same way, every time.
Filter-backed inputs
Filter-backed inputs constrain the rows your tables, pivots, and charts return. They're backed by filter definitions on the dashboard, so you get the same field metadata, timezone handling, and relative-date behavior you'd expect from a regular dashboard filter.
Supported types:
- Single-select — one value from a list
- Multi-select — one or more values from a list
- Date — a single date or relative date (e.g. Today, Yesterday)
- Date range — start and end dates, with relative presets like Last 30 days or Year to date
Each input can be required or optional. Required inputs block PDF export until the reader supplies a value — useful when the report is meaningless without, say, an account selection. Optional inputs let the reader export with whatever default you've configured.
Multi-select and date-range inputs keep their selected values visible even before the option list finishes loading. That matters for generated documents — a report rendered on a schedule shows the right selection in the header immediately, without waiting for option lookups.
Control-backed inputs
Control-backed inputs change the structure of the report rather than the data it filters down to. They're backed by control definitions on the dashboard.
Use a control-backed input when you want the reader to pick:
- A metric to break the report out by (e.g. Revenue vs. Bookings)
- A grain to roll up to (e.g. Day, Week, Month)
- An option that binds to a SQL parameter inside a section's query
Control-backed inputs render as dropdown selectors in the input bar. Their option list can be static or loaded from SQL, just like a dashboard control.
Variables
Variables interpolate input values into text — body copy, headings, headers, footers. The syntax is {{alias}} for the default rendering, or {{alias.property}} to pull a specific piece of the input's value.
Exported properties
Each input type exposes a different set of properties. Use the property that matches what you want to show.
| Input type | Properties | Example |
|---|---|---|
| Single-select filter | label, value | {{facility.label}} → Eastside Clinic |
| Multi-select filter | label, value | {{regions.label}} → North, South, East |
| Date filter | label, start, end | {{asOf.start}} → Mar 31, 2025 |
| Date-range filter | label, start, end, range | {{period.range}} → Jan 1 – Mar 31, 2025 |
| Control | label, value | {{metric.label}} → Revenue |
A bare {{alias}} resolves to the input's display label, which is usually what you want in narrative text:
Quarterly summary for {{facility}}, covering {{period.range}}.Renders as:
Quarterly summary for Eastside Clinic, covering Jan 1 – Mar 31, 2025.When you need the underlying value — for example, to compose a filename or a precise date — use value, start, or end:
Report run as of {{period.end}}Renders as:
Report run as of Mar 31, 2025Document metadata variables
A few variables aren't tied to inputs at all — they describe the document itself. They're available everywhere variables are supported, and they resolve at render time.
| Variable | What it shows |
|---|---|
{{document.generatedAt}} | Timestamp the PDF was generated |
{{document.pageNumber}} | Current page number |
{{document.pageCount}} | Total number of pages in the document |
A typical footer combines them:
Generated {{document.generatedAt}} · Page {{document.pageNumber}} of {{document.pageCount}}Where you can use variables
Variables work in any rich-text or label field on the report:
- Text sections — body copy, headings, callouts
- Page header — title, metadata line, note
- Page footer — note, page-info line
They don't go inside SQL queries — for that, use the control-backed input bound to the SQL parameter, and let the input's value flow through the binding.
Putting it together
A monthly statement might define three inputs:
customer— single-select filter oncustomer_id, requiredperiod— date-range filter, required, default Last monthmetric— control-backed input, optional, default Revenue
The header could read:
{{metric}} statement for {{customer}}
{{period.range}}And the footer:
Generated {{document.generatedAt}} · Page {{document.pageNumber}} of {{document.pageCount}}The same template now produces a different, fully personalized PDF for every customer and period — no duplication, no manual editing.