Turning Confluence Pages into a Queryable Register with Page Properties
Confluence's Page Properties and Page Properties Report macros turn scattered wiki pages into a live, queryable register. Here's a decision-log setup that works, plus where the pattern quietly breaks.
13 Nov 2025, 13:49 UTC

Your team keeps its design decisions in Confluence, which is fine until someone asks "show me every decision that's still pending review" and the honest answer is "scroll through forty pages and read the headings." The information exists; it's just trapped in prose.
Confluence already ships with a lightweight fix for this: the Page Properties macro paired with the Page Properties Report macro. Together they turn a set of free-form pages into a live, sortable table — no plugins, no external database, no sync jobs. This post walks through how the pattern works, a concrete decision-log setup, and where it breaks.
The two macros, in plain terms
The Page Properties macro is a container you drop onto a page. Inside it you put a simple two-column table: the first column holds field names (Status, Owner, Date), the second holds values. Anything inside the macro becomes structured, queryable data; the rest of the page stays ordinary prose. You can place several Page Properties macros on one page as long as each gets a distinct macro ID.
The Page Properties Report macro lives on a separate page — think of it as the index. You point it at a label (a tag attached to Confluence pages), and it renders a table with one row per labeled page and one column per field name. It reads the data at render time, so when someone edits a source page, the index reflects the change on next load. No one maintains the index by hand.
A worked example: the decision log
Here's the setup that pays for itself fastest, because decision records are exactly the kind of thing teams write once and never find again.
- Create a template. In your space, add a template (space admins: Space settings → Templates; on Cloud, look under Space settings → Content tools). The template body contains a Page Properties macro with a table like this:
| Field | Example value |
|---|---|
| Status | Proposed |
| Owner | @priya |
| Date | 2026-10-12 |
| Decision | Move session store to Redis |
- Attach a label in the template. Add the label
decision-logto the template itself, so every page created from it inherits the label automatically. - Build the index page. Create a page called "Decision Register," insert the Page Properties Report macro, set its label filter to
decision-log, and pick the columns you want shown (Status, Owner, Date, Decision). - Test it. Create two pages from the template, fill in different values, then load the index. Both rows should appear. Edit the Status on one source page, reload the index, and confirm the value changes without touching the index page.
Below the macro, each decision page holds the actual discussion — context, alternatives considered, meeting notes. The macro row is the metadata; the prose is the record. Readers get the narrative; the register gets the structure.
If you want separate rollups — say, one table of security decisions and one of architecture decisions — give each template's macro a distinct ID and filter the report by label plus macro ID rather than inventing more labels.
Why the template matters more than the macro
The single biggest failure mode of this pattern is silent: a page that's missing the label or the macro simply never appears in the report. No error, no warning, no empty row. The author thinks their decision is logged; the register disagrees.
Templates fix this by construction. If the only sanctioned way to write a decision is "Create from template → Decision," every page arrives with the macro pre-seeded and the label attached. Authors only fill in values. Also pick one canonical label spelling and stick to it — label matching has been case-sensitive in some Confluence versions and contexts, so Decision-Log and decision-log can quietly become two different registers.
A periodic sanity check helps too: search for pages titled like decisions that lack the label (CQL — Confluence Query Language — can express this, e.g. pages in the space with "decision" in the title but without the label), and fix stragglers.
Where the pattern runs out of road
Be clear-eyed about what you have: a reporting convenience, not a database.
- Filtering is coarse. The report selects pages by label and macro ID. "Show me decisions owned by Priya that are still Proposed" is a two-criteria query the macro can't do — you'd sort the rendered table by eye, or drop to CQL in search, or pull the data via the REST API.
- Render-time cost. The index page computes its table when someone loads it. Over a few dozen pages this is fine; over many hundreds, the index can get sluggish. Split by label or archive old decisions if that happens.
- No validation. Nothing stops someone typing "proposed" in one row and "PROPOSED" in another. If you need enforced vocabularies and workflows, that's Jira's job, not this macro's.
One escape hatch worth knowing: everything in the macro is part of the page's storage format, which the Confluence REST API exposes. So when the report macro stops being enough, you can script against the same data — syncing statuses to Jira, generating release notes, feeding a dashboard — without migrating anything. Exact API paths differ between Cloud and Data Center, so check the Atlassian docs for your deployment before writing that script; macro names and editor behavior vary slightly too.
Try it this week
Pick the register your team re-derives by hand most often — decisions, design reviews, incident follow-ups, project statuses. Build the template, add the label, create two real pages, and stand up the index. The whole thing takes under an hour, and the verification is built in: if both rows show up and an edit propagates on reload, you have a working system. If a page goes missing later, the first thing to check is the label — it almost always is.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.