Placeholders

Placeholders are markers in a template that the system replaces with field values when a document is generated. Every placeholder is wrapped in double braces: {{fieldName}}.

Where the names come from

A placeholder is not free text. The name inside the braces is the machine name of a field on the entity type the template is attached to — the same identifier the administrator typed when they created that field.

This is the single thing to understand before writing a template: the template’s vocabulary is the entity type’s field list. Nothing else resolves.

Machine name and display label

Every field has two names. The display label is what users see on the form and can be changed at any time, in any language. The machine name is the stable identifier, and it is what templates use.

Open the entity type in Settings → Entities, find the field, and read its machine name. A field labelled "Customer name" is very unlikely to be {{Customer name}}.

See entity types for how fields are defined and where the machine name is set.

Suppose an administrator has defined a document type Invoice with these fields:

Display label Machine name Type Placeholder

Invoice number

invoiceNumber

String

{{invoiceNumber}}

Issue date

issueDate

Date/time

{{issueDate}}

Customer

customer

Link → Counterparty

{{customer.name}}

Currency

currency

Set

{{currency}}

Line items

lineItems

Nested entity

{{#lineItems}}...{{/lineItems}}

Total

total

Expression

{{total}}

Those six machine names — plus the system fields below — are the entire set of placeholders that will resolve in a template attached to this document type. A seventh name, however plausible, produces a blank.

What is available besides your own fields

Every record also carries system fields, which are always present regardless of how the type is configured:

name

The record’s name.

description

The record’s description, if filled.

id

The record’s internal identifier.

Alongside these, the record’s author, assignee and timestamps are rendered and can be reached by dot path.

In batch reports, the template context also includes a filter object that holds the search criteria the user applied when generating the report. See filter values in the template for details.

System fields take precedence on a name collision. If a custom field is given the machine name name, the system field wins and the custom one becomes unreachable. Avoid name, id and description as machine names for your own fields.

How each field type arrives in the template

The field’s type decides the shape of the value, and therefore which placeholder form you need. The nine types themselves are described in data types; what follows is what each one looks like from inside a template.

String, integer, decimal, date/time, boolean, set, enum

A single value. Use it directly: {{invoiceNumber}}.

Link

The linked record is rendered in full, so you reach into it with a dot path: {{customer.name}}, {{customer.taxNumber}}. Chains work as far as the links go — {{site.division.company}}.

A bare {{customer}} is a record, not a value, and does not print usefully.

Nested entity and collection

A list. Use a repeating section — {{#lineItems}}...{{/lineItems}} — and inside it, reference the nested type’s own machine names, which are defined separately from the parent’s. See nested entities for how those rows are set up, and repeating sections for the template side.

Expression

A computed field. It arrives already calculated, so a plain placeholder is enough: {{total}}. See expressions for how the value is produced.

File and image

A reference rather than a value. For pictures, use an image placeholder rather than a text one.

Map

A list of key/value pairs, iterated like a collection.

A template is bound to one entity type

The available names change with what the template is attached to. A template on the Invoice document type sees invoice fields; a template on a counterparty type sees counterparty fields.

This is also why an XLSX _data sheet exists: it is the way to bring records of a different entity type into the same workbook, under a name you choose.

Simple value placeholders

A simple placeholder inserts one field value:

Invoice {{invoiceNumber}}
Issued: {{issueDate}}
Bill to: {{customer.name}}

Generated from an invoice record where invoiceNumber is INV-2026-0042, issueDate is 15 March 2026 and the linked customer is Apex Media, the output reads:

Invoice INV-2026-0042
Issued: 15.03.2026
Bill to: Apex Media

Nested paths

Dot notation reaches into linked records. If the entity type has a link field customer that points to a customer record, and that customer record has a field name, then:

{{customer.name}}

resolves to the linked customer’s name.

Nesting goes as deep as the data allows:

{{customer.billingAddress.city}}

Root-context access

Inside a repeating section, placeholders resolve against the current item. To reach a field from the top-level record instead, prefix the field name with $.:

{{$.dealNumber}}

This is useful when a table row needs to display both a line-item field and a deal-level field side by side. For example, a proposal line-item table might include the deal number in every row:

Column Placeholder

Deal number

{{$.dealNumber}}

Display name

{{displayName}}

Period

{{period}}

Price

{{price}}

Without the $. prefix, {{dealNumber}} would look for a dealNumber field on the line item itself — and if one does not exist, the placeholder resolves to blank.

Parent-context access

When sections are nested more than one level deep, {{../fieldName}} accesses a field from the parent context — one level up, not necessarily the root.

{{#campaigns}}
  Campaign: {{campaignName}}
  {{#placements}}
    Campaign (from parent): {{../campaignName}}
    Display: {{displayName}}
  {{/placements}}
{{/campaigns}}

For reaching all the way to the root regardless of nesting depth, use the $. prefix described above.

Inverted sections

An inverted section renders its content only when the field is empty, absent, or false. It uses a caret (^) instead of a hash:

{{^discount}}No discount applied.{{/discount}}

If the discount field has a value, the text "No discount applied." is omitted. If discount is empty or missing, the text appears in the output.

This is useful for fallback text — for example, showing "N/A" when an optional field has no value:

Contact: {{contactEmail}}{{^contactEmail}}N/A{{/contactEmail}}

Comments

Text wrapped in {{! ... }} is a comment. It is stripped when the document is generated and never reaches the reader.

{{! Clause 4.2 is for outdoor deals only. Legal asked for it -- keep. }}

A comment can span several lines, and it can sit inside a line of ordinary text:

Total: {{total}} {{! net of agency commission }}

That line comes out as Total: 45 000 — everything around the comment is untouched.

Use comments to record why a template is built the way it is: which clause is conditional, which column feeds which formula, which ticket asked for a field. The next person to open the file is usually not the person who wrote it.

What a comment leaves behind

The comment text always disappears. What happens to the space it occupied depends on the format.

XLSX

A cell holding nothing but a comment is left genuinely blank — not an empty string. Nothing else on the row is touched.

On the _data sheet this is doubly useful: a blank column A means the row is not read as a data source, so a comment in column A turns the row into a label row.

DOCX

The text goes, but the paragraph stays — an empty paragraph, which Word shows as a blank line.

To avoid the blank line, put the comment at the end of a paragraph that has content of its own rather than on a line by itself:

AGREEMENT No. {{contractNumber}} {{! number comes from the deal }}

A comment that is the only thing in a table cell simply leaves that cell empty, which costs nothing.

PPTX

The text goes, but the shape stays as an empty text box. It has no visible text, but it is still an object on the slide and will show if the shape has a fill or an outline. Give comment shapes no fill and no outline, or park them outside the slide canvas where nothing renders.

Never write placeholder syntax inside a comment

A comment must not contain }}.

A comment ends at the first }} it meets, not the last. Paste a placeholder into a comment and the comment is cut short there, and the remainder is printed into the document as ordinary text:

Total: {{total}} {{! see {{total}} above }}

comes out as Total: 45 000 above }} — the tail of your own note, delivered to the customer.

Describe placeholders in words, or split the braces so that no }} appears:

{{! the total below is computed, not stored }}
{{! the block under this row loops -- see the items section }}

How missing fields behave

When a placeholder references a field name that does not exist in the data, the placeholder resolves to an empty string. No error is raised and no warning appears in the output.

This means that a misspelled field name — {{custmerName}} instead of {{customerName}} — silently produces a blank space in the generated document. The troubleshooting page covers how to diagnose this.

Auto-formatting

Dates and decimal numbers receive automatic formatting when inserted through a simple placeholder:

  • Dates are formatted as dd.MM.yyyy — for example, 15.03.2025.

  • Decimal numbers are formatted to two decimal places — for example, 1234.50.

To apply a different format, use an expression placeholder with a formatting helper instead. See expressions and formatting.

Summary of placeholder types

Syntax What it does

{{fieldName}}

Inserts a field value.

{{linked.field}}

Inserts a value from a linked record (dot notation).

{{$.fieldName}}

Inserts a value from the root context, even inside a nested section.

{{../fieldName}}

Inserts a value from the parent context (one level up).

{{#collection}} ... {{/collection}}

Repeats a block for each item in a collection. See repeating sections.

{{^field}} ... {{/field}}

Renders a block only when the field is empty or absent.

{{! ... }}

A comment. Removed from the output; never seen by the reader.

{{=expression}}

Evaluates a JavaScript expression inline. See expressions and formatting.

{{=}}formula

XLSX only — writes a live Excel formula into the cell. See Excel templates.