# How to Customize NetSuite Advanced PDF/HTML Templates

> Source: https://netray.co/erp-help/netsuite-how-to-advanced-pdf-html-templates
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: ERP Help

## Short answer

NetSuite Advanced PDF/HTML templates use FreeMarker markup inside an XML-for-PDF or HTML wrapper, edited under Customization > Forms > Advanced PDF/HTML Templates. You reference transaction body fields with ${record.fieldid}, loop line items with a list directive over record.item, and control layout with standard XSL-FO style tags in the barcode/pdf namespace.

## Kind

how-to

## System

netsuite

## Erp

Oracle NetSuite

## Module

Advanced PDF/HTML Templates

## Query

how to customize NetSuite advanced PDF HTML template

## Alternate Queries

- NetSuite advanced PDF template FreeMarker tutorial
- how to add a table column to NetSuite invoice PDF
- NetSuite advanced HTML template not showing custom field
- customize NetSuite PO template layout

## Applies To

NetSuite Advanced PDF/HTML Templates (SuiteBuilder), all editions that have Advanced PDF/HTML Templates enabled, transaction forms (invoice, sales order, purchase order, statement)

## Steps

### How to edit an Advanced PDF/HTML template

**Items:**

- Go to Customization > Forms > Advanced PDF/HTML Templates, click a standard template (e.g. Standard Invoice) and choose Customize to create an editable copy.
- In the template editor, locate the field you want using the Insert Field Type dropdown on the right, which generates the correct ${record.fieldid} or ${record.item.fieldid} syntax to paste in.
- For body fields use ${record.entity}, ${record.trandate}, ${record.total}; for custom body fields use ${record.custbody_yourfield}.
- For line items, work inside the existing <#list record.item as item> ... </#list> block and add a new <td>${item.custcol_yourfield}</td> cell matching the existing column structure.
- Add conditional sections with <#if record.custbody_flag>...</#if> so blocks only render when a field is set or non-empty.
- Preview with a real transaction using the Preview button in the template editor before saving, since some fields only render correctly against live data.
- Assign the customized template to the transaction form under Customization > Forms > Transaction Forms > your form > Printing/Email tab.
- If a field shows blank, confirm it is checked Store Value and Available Without Login is not required, and that the field is on the form's field list (sourced fields sometimes need the source field added too).

## Sections

### FreeMarker basics for NetSuite templates

**Body:**

Advanced PDF/HTML templates are rendered by FreeMarker, a Java templating language, wrapped in either an XSL-FO-like <pdf> tag set for PDF output or plain HTML for HTML/email templates. The record object exposes the transaction's body fields directly, and record.item (or record.expense, record.time depending on transaction type) exposes the sublist as an iterable list.

Custom fields follow NetSuite's standard prefix convention: custbody_ for transaction body fields, custcol_ for line item column fields, custentity_ for entity-level fields you may need to pull via record.entity.custentity_yourfield. Getting the prefix and internal ID exactly right is the most common source of blank output.

### Looping and formatting sublists

**Body:**

The existing <#list record.item as item> block already handles item, quantity, rate, amount. Add new columns inside the same <tr> structure rather than creating a second loop, otherwise the PDF renders two separate item tables or misaligned rows.

Number and date formatting uses FreeMarker built-ins: ${item.rate?string("#,##0.00")} for currency, ${record.trandate?string("MM/dd/yyyy")} for dates. Skipping the format string is the usual cause of PDFs showing raw unformatted numbers or ISO date strings to customers.

**Code:**

<#list record.item as item>
<tr>
<td>${item.item}</td>
<td>${item.custcol_lot_number!""}</td>
<td align="right">${item.quantity}</td>
<td align="right">${item.rate?string("#,##0.00")}</td>
</tr>
</#list>

### Conditional logic and subtotals

**Body:**

Use <#if> / <#else> / </#if> to show or hide blocks, such as a discount line that only appears when record.discounttotal is non-zero, or a different footer for international customers based on record.shipcountry.

For running totals across a filtered subset of lines (for example only taxable lines), FreeMarker does not aggregate automatically inside the template; either add a saved search-driven summary field on the transaction beforehand, or use a <#assign total = 0> accumulator variable incremented inside the list loop.

**Code:**

<#assign taxableTotal = 0>
<#list record.item as item>
  <#if item.taxcode != "NT">
    <#assign taxableTotal = taxableTotal + item.amount>
  </#if>
</#list>
Taxable subtotal: ${taxableTotal?string("#,##0.00")}

### Common rendering errors

**Body:**

FTL parsing errors on save usually point to an unclosed <#if> or <#list> tag, or a field reference with a typo in the internal ID; the error message gives a line number in the template source, not the rendered output, so count from the top of the FreeMarker markup.

A field that renders as 'null' rather than blank means the field exists but returned a null value that was not handled; wrap it with the FreeMarker default operator, e.g. ${record.custbody_note!""}, to fall back to an empty string.

## Pitfalls

- Editing the standard template directly instead of Customize-ing a copy, which blocks changes on the next NetSuite release upgrade.
- Forgetting the ! default operator on optional custom fields, causing 'null' to print on records where the field was never set.
- Adding a second <#list record.item as item> block instead of extending the existing one, which duplicates or misaligns the item table.
- Not adding the sourced field to the transaction form's field list when the PDF references a field sourced from another record.
- Testing only against one transaction that happens to have every field populated, then finding blank fields break layout on real customer records with sparse data.
- Confusing custbody_/custcol_/custentity_ prefixes, which is the single most common cause of a field simply not rendering.

## Ai Angle

ERPray, grounded on your NetSuite account's actual form and field configuration, can generate the exact FreeMarker snippet for a requested change, including the correct custbody_/custcol_ internal IDs pulled from your account rather than guessed, and flag when a referenced field is not yet on the transaction form's field list before you hit a blank-render surprise in production.

## Faq

### Can I use JavaScript inside an Advanced PDF/HTML template?

**Answer:** No. Advanced PDF/HTML templates render server-side with FreeMarker only; there is no client-side JavaScript execution in the PDF generation pipeline. Any dynamic logic must be expressed in FreeMarker directives or precomputed on the record before printing.

### Why does my custom field show on the form but not the PDF?

**Answer:** The PDF template references fields by internal ID independently of the form layout. Confirm the field's internal ID and prefix (custbody_/custcol_/custentity_) match exactly what you typed in ${record.fieldid}, and that Store Value is checked on the field definition.

### How do I test template changes without emailing real customers?

**Answer:** Use the Preview button in the template editor against an existing transaction, or print to PDF from a sandbox account transaction record before assigning the template to a live transaction form in production.

### Can Advanced PDF templates pull data from a different record type?

**Answer:** Yes, via dot-notation through a relationship the record already exposes, such as record.entity.custentity_field for a customer-level custom field, but you cannot arbitrarily query unrelated records the way a SuiteScript search can.

## Search terms

NetSuite advanced PDF template, NetSuite FreeMarker syntax, customize NetSuite invoice PDF, NetSuite advanced HTML template, NetSuite custbody custcol prefix, NetSuite PDF template list record.item, NetSuite template null field fix, NetSuite print template customization

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
