Skip to main content

DRAFT Merge field syntaxes for HTML invoice templates

Zuora

DRAFT Merge field syntaxes for HTML invoice templates

A merge field is a field you can put into templates to automatically incorporate values from data when a document is generated from the template. In templates, you can define merge fields that are automatically filled with the value when a document is generated.

A merge field used in HTML templates is surrounded by double curly brackets. You can refer to the Mustache Specification for more information about the merge field syntax that Zuora supports in HTML templates. 

Overview 

A merge field is a dotted data path consisting of objects and fields enclosed by double curly brackets. For example:

  • {{Invoice.InvoiceNumber}}: used to incorporate the invoice number of an invoice. 
  • {{Invoice.Account.BillTo.FirstName}}: used to incorporate the first name of the bill-to contact associated with an invoice.

When defining merge fields in HTML templates, you cannot omit the root object.

  • Invoice is the root object for invoice templates.
  • CreditMemo is the root object for credit memo templates.
  • DebitMemo is the root object for debit memo templates.

When defining merge fields, you can only place objects on the left of the dot (.), while scalar type fields or lists are not allowed. For example, the following merge fields are valid:

  • {{Invoice.Account.Name}}
  • {{Invoice.Account.BillTo.FirstName}}
  • {{Invoice.Account.Invoices}}

Merge fields are mainly classified into three types: variables, sections, and inverted sections. You can decorate each type of merge fields with different functions to achieve the goal of data transformation.

Variables

Variables are the most basic merge fields. A variable type merge field like {{Invoice.InvoiceNumber}} is replaced with a corresponding value according to the data path indicated by the merge field at template rendering time. 

For example, assume that an invoice has the invoice number of INV-0000001, and its balance is 100.00.

If you define the following merge fields in an HTML invoice template, you can see they are replaced with the following values on the rendered invoice:

  • {{Invoice.InvoiceNumber}} is replaced by INV-0000001.
  • {{Invoice.Balance}} is replaced by 100.00.

HTML templates support two types of variables:

  • Builtin variables
    Builtin variables are variables whose names are Zuora business objects and field names. For example, {{Account.AccountNumber}}, {{InvoiceDate}}, and so on.

  • Custom variables
    Custom variables are user defined variables by using the Cmd_Assign command. Each custom variable has its own scope. If it is a local variable, it can only be used in the section of its immediate parent object. For example:

{{#Invoice}}

{{Cmd_Assign(MainId,Id,False)

……  {{MainId}} is valid here.

{{/Invoice}}

{{#default__customobjects}}

…… {{! MainId is invalid here}}

{{/default__customobjects}}

In the preceding example, MainId is a local variable that is available within the "Invoice" section, but it is not accessible in the section of default__customobjects.

However, if a variable is defined as a global variable, it can be used anywhere in the template. You can use global variables as merge fields, in expressions, and as part of conditional logic in functions. For more information about how to define global variables, see Defining global variables.

To use custom variables, you must define them first. 

Sections

You can use sections to render blocks of text one or more times, depending on the value of the key in the current context. 

A section begins with a pound and ends with a slash. That is, {{#Invoice}} begins an "Invoice" section while {{/Invoice}} ends it.

Inside sections, you can use variable-type merge fields, and can omit the object name of a field.

Sections can be classified into three types: object sections, list sections, and boolean sections.

Object sections

If a merge field represents an object, you can use the merge field as an object section. 

For example, Invoice is a single object for invoice templates, you can define it as an object section.

{{#Invoice}}
  {{InvoiceNumber}}   # In the context of Invoice, you can directly use InvoiceNumber.
  {{Amount}}
  {{Account.Name}}
{{/Invoice}}

You can use object sections to shorten merge fields defined in HTML templates. For example, to simplify the {{Invoice.InvoiceNumber}}  {{Invoice.Balance}} merge fields, you can use the following section instead:

{{#Invoice.InvoiceItems}}       # InvoiceItems is a list type attribute of the Invoice object.
ChargeName:  {{ChargeName}}
{{/Invoice.InvoiceItems}}

List sections

If a merge field represents a list of records, you can use the merge field as a list section. The content inside the section will be rendered and displayed for each record in the list. 

List sections are typically used to build a data table. If a list is empty, no content is displayed on the rendered billing document.

For example, to display the line items of an invoice, you can define the following list section in HTML templates:

{{#Invoice.InvoiceItems}}       # InvoiceItems is a list type attribute of the Invoice object.
ChargeName:  {{ChargeName}}
{{/Invoice.InvoiceItems}}

Assume that an invoice contains three charge line items as follows:

{
 ....,
   "InvoiceItems": [
       {
           "ChargeName": "C-000001"
       },
       {
           "ChargeName": "C-000002"
       },
       {
           "ChargeName": "C-000003"
       }
   ],
 ...
}

If you define the preceding list section in an HTML invoice template, you can see the following information displayed on the rendered invoice:

ChargeName: C-000001

ChargeName: C-000002

ChargeName: C-000003

Boolean sections

In addition to object and list sections, you can also use boolean values as sections.

For example, if an account has the AutoPay option enabled, the following merge fields only display the value of CreditCardMaskNumber for the account.

{{#Invoice.Account.AutoPay}}
Payment Method: {{Invoice.Account.DefaultPaymentMethod.CreditCardMaskNumber}}
{{/Invoice.Account.AutoPay}}

Inverted sections

You can use inverted sections to render text once based on the inverse value of the merge field. That is, they will be rendered if the object merge field key does not exist, the boolean value is false, or the list is empty. 

For example, if the input InvoiceItems list is empty, you cannot see any invoice items but the No line items. message displayed in the rendering result. If an invoice account does not have the AutoPay option enabled, you can see the Not Auto Pay message displayed in the rendering result. 

{{^Invoice.InvoiceItems}}   # If the InvoiceItems list is empty. 
No line items.                  
{{/Invoice.InvoiceItems}}

{{^Invoice.Account.AutoPay}}
Not Auto Pay
{{/Invoice.Account.AutoPay}}

Decorated merge fields

To transform data, you can apply functions to the data represented by a merge field.

A decorated merge field is a regular merge field, like {{Invoice.InvoiceItems}}, decorated with functions. For example:

{{Invoice.InvoiceItems|FilterByValue(ChargeAmount,GT,0)|Sum(ChargeAmount)}}

A Pipe character ("|") is an operator that passes the previous data as input to its right side function. In the preceding example, it transforms data as follows:

  • Invoice.InvoiceItems|FilterByValue(ChargeAmount,GT,0) filters out all invoice items with zero and negative amounts.
  • FilterByValue is a function applied to the InvoiceItems list, and (ChargeAmount,GT,0) are the three arguments of the function. The output of the function is all the invoice items with positive amounts.
  • Sum is another function whose input is all the invoice items with positive amounts; it simply sums up all ChargeAmount of positive invoice items and outputs a total number.

As you can see from the preceding example, you can chain decorator functions as long as the input type matches the function's argument type.

The following image shows an example of decorated merge fields:

HTML_invoice_decorated_merge_fields.png

For a full list of supported decorator functions, see Functions used in merge fields for more information.

Supported objects and fields

All objects and fields that are available in Data Query are available in HTML templates.

The naming of merge fields is case insensitive.

In the HTML template editor, you can find all supported objects and their fields from the Merge Field component, or the Merge Fields drop-down list through the Text component.

You can also learn the object relationship from the Merge Fields drop-down list. 

For example, Account.SoldTo is a Contact type object, while Account.Subscriptions is a list type of the Subscription object. To see which fields are available for the Contact object, scroll down the Merge Fields list on the left panel and hover over the Contact object. You can see a list of available fields for the Contact object, for example, Contact.Country and Contact.CreatedDate.

Custom objects and custom fields

HTML templates also support custom objects and custom fields. You can find available custom objects and custom fields in the Merge Fields drop-down list of the Text component, similar to the standard objects and fields.

In the Merge Fields drop-down list, custom object names are prefixed with default__, and custom field names are suffixed with __c by Zuora naming conventions.

When new custom fields are added, or existing custom fields are updated or removed, it takes around 5 minutes to be visible in the merge fields list.

For common use cases, see Use custom objects in HTML templates.

Logic control and looping

For more information, see Logic control and looping.

Functions used in merge fields

For more information about the functions that you can use in HTML templates, see Functions used in merge fields.

Expressions

In addition to the merge fields and functions, you can also use expressions in HTML templates. An expression is simply a text input with merge fields and operators, which is evaluated at runtime, and generates text as output.

To use an expression in your template, enclose your expression with the Wp_Eval section. For example, the following expression generates 2.5 as output.

{{#Wp_Eval}}
1 + 2 - 0.5
{{/Wp_Eval}}

The "Wp" prefix stands for "wrapper" lambda in Mustache, see the lambda section in the Mustache Specification for more information.

You can use merge fields within expressions. For example, to sum up the invoice item charge amount and tax amount, you can use the following expression:

{{#Wp_Eval}}
{{ChargeAmount}} + {{TaxAmount}}
{{/Wp_Eval}}

The merge fields are replaced with data before the expression is evaluated. If the charge amount is 100 and the tax amount is 10, the expression generates 110 as output.

Decorator functions are also supported in expressions. Like how they work in merge fields, the decorator functions are led and delimited by pipe characters, no whitespace is allowed. For example, you can use the following expressions to round the sum of the charge amount and tax amount in two decimals and format the sum value based on the default locale.

{{#Wp_Eval}}
{{ChargeAmount}} + {{TaxAmount}}|Round(2)|Localise
{{/Wp_Eval}}

In the preceding example,{{ChargeAmount}} + {{TaxAmount}} is the input for |Round(2)|Localise. If the charge amount is 100, the tax amount is 10, and the default locale is en_US, the expression generates 110.00 as output.

Examples

You can use expressions to link different properties to meet business demands.

Comparing strings with whitespace characters

You can use expressions to compare strings with whitespace characters. 

You can use the following expression to indicate whether the charge model of a rate plan charge is Flat Fee Pricing. If yes, the Is Flat Fee message is displayed in the rendered result. If no, the Not Flat Fee message is displayed in the rendered result.

{{#Wp_Eval}}
"{{RatePlanCharge.ChargeModel}}" == "Flat Fee Pricing" ? "Is Flat Fee" : "Not Flat Fee"
{{/Wp_Eval}}

If you want to show bold text for product rate plan charges with the Per Unit Pricing charge model and the price in generated billing documents, use the following expression:

{{#Wp_Eval}}
"{{RatePlanCharge.ChargeModel}}" == "Per Unit Pricing" ? `
<b>Per Unit: {{Invoice.Account.Currency|Symbol}} {{UnitPrice|Round(2)|Localise}} Per {{UOM}}</b>
`: '
Flat Fee: {{Invoice.Account.Currency|Symbol}} {{UnitPrice|Round(2)|Localise}}
'{{/Wp_Eval}}<b>Per Unit: {{Invoice.Account.Currency|Symbol}} {{UnitPrice|Round(2)|Localise}} Per {{UOM}}</b>

If you want to display different texts for rate plan charges with different charge models in generated billing documents, use the following expression:

{{#Wp_Eval}}
"{{RatePlanCharge.ChargeModel}}" == "Flat Fee Pricing" ? "Is Flat Fee" : "{{RatePlanCharge.ChargeModel}}" == "Per Unit Pricing" ? "Per Unit Pricing" : "{{RatePlanCharge.ChargeModel}}" == "Tiered Pricing" ? "Tiered Pricing" : "Other Pricing"
{{/Wp_Eval}}

Mapping state strings to state acronyms

You can use expressions to map state strings to state acronyms. For example, if the state name in a bill-to contact address is New York, you can use the following expression to generate NY as the rendered result:

{{#Invoice.Account.BillTo}}
{{#Wp_Eval}}
"{{State}}" == "New York" ? "NY" : "{{State}}" == "California" ? "CA" : "{{State}}" == "Taxas" ? "TX" : ""
{{/Wp_Eval}}
{{/Invoice.Account.BillTo}}

Not displaying blank line when Address2 is empty

If Address2 in a bill-to contact is empty, you can use an expression to not display a blank line for the Address2 line on generated PDF files. To achieve this goal, you can place the following code into the HTML component.

{{Name}}<br/>
{{BillTo.Address1}}<br/>
{{#Wp_Eval}}
"{{BillTo.Address2}}" == "" ? "" : "{{BillTo.Address2}}<br/>"
{{/Wp_Eval}}
{{BillTo.City}}, {{BillTo.State}} {{BillTo.PostalCode}}
{{/Invoice.Account}}

Red text for negative charge amounts

To display negative charge amounts in red text on generated PDF files, place the following code into a table column through the Data Table component. ChargeAmount is a field of the InvoiceItem object.

{{#Wp_Eval}}
{{ChargeAmount}} < 10 ? "<span style='color:red;'>" : "<span>"
{{/Wp_Eval}}
{{Account.Currency|Symbol}}{{ChargeAmount|Round(2)|Localise}}
</span>

Red text for amount less than 110, calculating from custom fields

To display amounts that are less than 110 in red text on generated PDF files, place the following code into the HTML code editor through the HTML component:

<td style="text-align: right">
<!-- red font for negative amount -->
{{#Wp_Eval}}
{{ActualPrice__c}} * {{ActualQTY__c}} < 110 ? "<span style='color:red;'>" : "<span>"{{/Wp_Eval}}
{{Account.Currency|Symbol}}{{#Wp_Eval}}{{ActualPrice__c}} * {{ActualQTY__c}}|Round(2)|Localise
{{/Wp_Eval}}
</span>
</td>

Calculating unit price excluding tax

When you use tax-inclusive products, the standard field UnitPrice is tax inclusive. You can calculate unit price excluding tax.

To achieve this goal, place the following code into a table column through the Data Table component or HTML component.

{{Account.Currency|Symbol}}{{#Wp_Eval}}{{ChargeAmount}}/{{Quantity}}|Round(2)|Localise{{/Wp_Eval}}

Displaying red text when account is overdue

To display red text on generated PDF files in scenarios where an account is overdue, place the following code into the HTML code editor through the HTML component:

<Strong style="color:Red; text-align:right;">
{{#Invoice}}
{{#Wp_Eval}}
{{Balance}} < {{Account.Balance}} ? "Your account is now overdue." : ""
{{/Wp_Eval}}
{{/Invoice}}
</Strong>

If an customer account is overdue, the Your account is now overdue. message in red is displayed in the rendered result.

Excluding items based on conditions

You can use expressions to exclude some invoice items but only display the invoice items whose start dates fall into a specific period. For example, you can use the following expression to display the invoice items whose service start date is in January 2021 or December 2021 are selected, and then sort the selected invoice items in the following order:

  • ServiceStartDate: sorts invoice items by service start date in ascending order.
  • ServiceEndDate: sorts invoice items by service end date in ascending order.
  • ChargeAmount: sorts invoice items by charge amount in descending order.
{{#InvoiceItems|SortBy(ServiceStartDate,ASC,ServiceEndDate,ASC,ChargeAmount,DESC)}}
{{#Wp_Eval}}
("{{ServiceStartDate}}" < "2021-02-01" or "{{ServiceStartDate}}" >= "2021-12-01") ? "" :
`
<tr>
<td >{{ChargeName}}</td><td >{{ServiceStartDate}}</td><td >{{ServiceEndDate}}</td><td >{{ChargeAmount}}</td>
</tr>
`
{{/Wp_Eval}}
{{/InvoiceItems|SortBy(ServiceStartDate,ASC,ServiceEndDate,ASC,ChargeAmount,DESC)}}

In the preceding expression example, 

Restrictions and limitations

When using expressions in HTML templates, keep the following restrictions and limitations in mind: 

  • Be aware of the data type of each merge field used in expressions.
    If you are trying to use a decorator function for a text type input, ensure that the input data is text or has been converted to text. For example, if you want to use the Substr function to decorate the ChargeAmount  numeric field, you have to convert the field to text first. To achieve this goal, you have to enclose the merge field with double quotation marks.
    {{#Wp_Eval}}
    "{{ChargeAmount}}"|Substr(0,2)
    {{/Wp_Eval}}
  • You cannot enclose any HTML tags within the Wp_Eval section, because the system treats them as part of the expression and throws validation errors.

  • If your expression contains special characters like > or <, you have to use an HTML component instead of a Text component, since the characters will be escaped.
    For example, you want to display a message in red when your customer is overdue. You have to place the following expression into an HTML component, and the HTML style must be outside of the Wp_Eval section.

    <Strong style="color:Red; text-align:right;">
    {{#Invoice}}
    {{#Wp_Eval}}
      {{Balance}} < {{Account.Balance}} ? "Your account is now overdue." : ""
    {{/Wp_Eval}}
    {{/Invoice}}
    </Strong>

Operators

Merge fields used in HTML templates support a variety of operators.

The following table lists the operators that you can use in HTML templates.

Operator

Description

Boolean and

The usual && operator can be used as well as the word and. For example, cond1 and cond2 and cond1 && cond2 are equivalent.

Boolean or

The usual || operator can be used as well as the word or. For example, cond1 or cond2 and cond1 || cond2 are equivalent.

Boolean not

The usual ! operator can be used as well as the word not. For example, !cond1 and not cond1 are equivalent.

Ternary conditional ?:

The usual ternary conditional operator condition ? if_true : if_false  can be used as well as the abbreviation value ?: if_false, which returns the value if its evaluation is defined, non-null and non-false. For example, val1 ? val1 : val2 and val1 ?: val2 are equivalent.

Note: The condition evaluates to false when it refers to an undefined variable or null. 

Null coalescing operator ??

The null coalescing operator returns the result of its first operand if it is defined and is not null.

When x and y are null or undefined, x ?? 'unknown or null x' evaluates as 'unknown or null x', and y ?? "default" evaluates as "default".

When var x = 42 and var y = "forty-two",x??"other" evaluates as 42 and y??"other" evaluates as "forty-two".

Note: This operator does not behave like the ternary conditional since it does not coerce the first argument to a boolean to evaluate the condition. When var x = false and var y = 0,x??true evaluates as false and y??1 evaluates as 0.

Equality

The usual == operator can be used as well as the abbreviation eq. For example, val1 == val2 and val1 eq val2 are equivalent.

null is only ever equal to null, that is if you compare null to any non-null value, the result is false.

Inequality

The usual != operator can be used as well as the abbreviation ne. For example, val1 != val2 and val1 ne val2 are equivalent. 

Less Than

The usual < operator can be used as well as the abbreviation lt. For example, val1 < val2 and val1 lt val2 are equivalent. 

Less Than Or Equal To

The usual <= operator can be used as well as the abbreviation le. For example, val1 <= val2 and val1 le val2 are equivalent. 

Greater Than

The usual > operator can be used as well as the abbreviation gt. For example, val1 > val2 and val1 gt val2 are equivalent. 

Greater Than Or Equal To 

The usual >= operator can be used as well as the abbreviation ge. For example, val1 >= val2 and val1 ge val2 are equivalent. 

Addition

The usual + operator is used. For example, val1 + val2.

Subtraction

The usual - operator is used. For example, val1 - val2.

Multiplication

The usual * operator is used. For example, val1 * val2.

Division

The usual / operator is used, or you can use the div operator. For example, val1 / val2 or val1 div val2.

Modulus (or remainder)

The % operator is used. An alternative is the mod operator. For example, 5 mod 2 gives 1 and is equivalent to 5 % 2.

Negate

The unary - operator is used. It changes the sign of its numeric argument. For example, -12 or -(a * b).

Commands

A command is a merge field that is parsed and executed with side effects, for example, to change the value of other objects or create new objects. Commands have no return value, so if a Command merge field is used, the merge field itself shows nothing.

Cmd_Assign

The Cmd_Assign command takes three arguments. The first one is a variable name, which can only contain alphabet characters, aka, [0_9a-zA-Z_]. The second argument is a merge field whose value will be assigned to the variable and the merge field can be decorated. For example, {{Cmd_Assign(MaxInvoiceAmount,Account.Invoices|Max(Amount),False)}}.

The third argument is an optional boolean value indicating whether this variable is a global variable; its default value is False, which means the variable is a local variable.

What this command does is to evaluate the right argument if it is a merge field and assign the value to the variable, and then append that variable as a new field of its immediate container object. For example:

{{#Invoice}}
{{Cmd_Assign(Inv_id,Id)}}
{{/Invoice}}

In the preceding example, a new attribute of Inv_id will be appended to the invoice with the value of Invoice.Id.

You can also use Cmd_Assign in a list section, for example:

{{#InvoiceItems|FilterByValue(ProcessingType,EQ,0)}}                            (1)
{{Cmd_Assign(RegularItemId,Id)}}                                                (2)
{{ChargeName}} - {{ChargeAmount}} - {{#InvoiceItems|FilterByRef(AppliedToInvoiceItemId,EQ,RegularItemId)}}          (3)
* {{ChargeName}} - {{ChargeAmount}}
{{/InvoiceItems|FilterByRef(AppliedToInvoiceItemId,EQ,RegularItemId)}}
{{/InvoiceItems|FilterByValue(ProcessingType,EQ,0)}}

In the preceding example, line (1) lists all invoice items for non-discount charges. Line (2) appends a new attribute named RegularItemId with the value of InvoiceItem.Id. Line (3) is to get all the InvoiceItems, of which AppliedToInvoiceItemId equals to the variable RegularItemId. Because the RegularItemId attribute is created only for the non-discount charges, so for discount charges, no such an attribute exists. Therefore, the engine will check its outer object, which is the object of the list defined in line (1).

Note that the variable defined by Cmd_Assign is only available in scope of its immediate container object, so it cannot be used as a global variable.

Defining global variables

You can use the Cmd_Assign command to define global variables.

In the following example, the value of the third argument in the Cmd_Assign command is Ture, indicating that VarEntityNumber and VarEntityTotalAmount are defined as global variables. The value of the EntityNumber__c merge field is assigned to the VarEntityNumber global variable, and the value of the EntityTotalAmount__c merge field is assigned to the VarEntityTotalAmount global variable.

For example, the following boolean values of variables are True:

{{#Invoice.Account.default__legalentities|First(1)}}
{{Cmd_Assign(VarEntityNumber,EntityNumber__c,True)}}
{{Cmd_Assign(VarEntityTotalAmount,EntityTotalAmount__c,True)}}
{{/Invoice.Account.default__legalentities|First(1)}}

The rendering result of the preceding global variables can be VarEntityNumber and VarEntityTotalAmount.

You can use the global variables defined in the preceding command example as merge fields in HTML templates, for example:

Entity Number: {{VarEntityNumber}}
Entity Total Amount: {{VarEntityTotalAmount}}
Entity Total Amount: {{VarEntityTotalAmount|Localise}}

In addition, you can also use the global variables in functions as part of conditional logic. For example, to display the tax information for the UK entity and countries other than the UK entity, you can use the global variables in  theEqualToVal function as part of conditional logic in the following section:

{{#VarEntityNumber|EqualToVal(100001)}}
Display tax information for UK entity
{{/VarEntityNumber|EqualToVal(100001)}}

{{^VarEntityNumber|EqualToVal(100001)}}
Display tax information for countries other than UK entity
{{/VarEntityNumber|EqualToVal(100001)}}

You can also use the global variables in expressions. For example, you can use the global variables in the following expression to display the UK tax information:

{{#Wp_Eval}}
"{{VarEntityNumber}}" == "100001" ? "show UK tax info" : ""
{{/Wp_Eval}}