NetSuite Advanced PDF source code controls the structure, data binding, styling, and page behavior of the PDF documents generated from NetSuite. It combines XML-based markup, FreeMarker template expressions, NetSuite record fields, and formatting instructions processed by NetSuite’s PDF rendering engine. By editing the source carefully, we can fix broken fields, conditional sections, tables, logos, page breaks, and transaction layouts without rebuilding a template from scratch.
A visual editor is useful for simple formatting, but source code is where the real control exists. A developer or administrator can inspect the template’s XML structure, identify the exact field or directive causing an error, and test a focused change. The most reliable approach is to treat an Advanced PDF/HTML Template as both a document layout and a small data-driven program.
What is NetSuite Advanced PDF source code?
NetSuite Advanced PDF source code is the underlying markup used by an Advanced PDF/HTML Template. The source generally contains XML-compatible HTML, FreeMarker expressions, CSS styling, and NetSuite-specific record references. When NetSuite generates a transaction PDF, it evaluates the FreeMarker expressions against the current record and sends the resulting document through its PDF rendering process.
A basic field expression looks like this:
${record.tranid}That expression tells NetSuite to print the transaction number from the `record` data object. Other common references include:
${record.trandate}
${record.entity}
${record.memo}
${record.total}The exact fields available depend on the record type, the template context, and the data exposed by NetSuite. A field that works on an invoice does not automatically work on a sales order, purchase order, credit memo, or custom transaction form.
The source also controls elements that are difficult to manage visually, including:
Repeating transaction lines
Conditional display with FreeMarker
Header and footer behavior
Custom fonts and colors
Subsidiary logos
Multi-page tables
Tax and shipping sections
Address formatting
Page numbers
XML escaping
Custom data sources supplied through SuiteScript
This is why source-level knowledge matters. A PDF that looks like a design problem often has a data-binding or markup problem underneath.
Where do you edit Advanced PDF source code in NetSuite?
You edit an Advanced PDF/HTML Template from the NetSuite customization menu, provided your role has the required permissions.
The standard navigation path is:
Customization > Forms > Advanced PDF/HTML Templates
From there, open an existing template or create a new one. NetSuite provides an editor with a visual design mode and a source code mode. The source mode exposes the XML and FreeMarker content that produces the final document.
The exact menu labels and available actions vary according to account configuration, role permissions, and NetSuite changes. In most accounts, the important controls include the ability to:
Open the template record.
Switch to the HTML or source view.
Edit the markup.
Preview the output.
Save the template.
Assign the template to the relevant transaction form or custom form.
Before making changes, we recommend duplicating the template or exporting and storing a copy of the original source. A missing closing tag or deleted directive can prevent the template from rendering, and a backup gives us a fast recovery path.
The template record also matters. A correct source edit has no effect if the wrong template is assigned to the transaction form, subsidiary, or printing preference. When a change appears to do nothing, we first verify that NetSuite is using the template we edited.
How do FreeMarker expressions work in NetSuite PDF templates?
FreeMarker expressions connect the template to NetSuite data. NetSuite uses FreeMarker syntax for field output, conditions, loops, variables, and certain formatting operations.
A simple conditional block looks like this:
<#if record.memo?has_content>
<p>Notes: ${record.memo}</p>
</#if>The `?has_content` test prevents an empty memo label from appearing when the field contains no value. This is more reliable than printing every optional field unconditionally.
A repeating transaction-line section commonly uses a loop:
<#list record.item as item>
<tr>
<td>${item.item}</td>
<td>${item.description}</td>
<td>${item.quantity}</td>
<td>${item.amount}</td>
</tr>
</#list>The object name is important. In a standard transaction template, line data is often available through a sublist such as `record.item`, but the correct sublist and field names depend on the transaction type. Expense lines, item lines, shipping information, tax details, and custom sublists use different data structures.
FreeMarker also supports default values and existence checks. For example:
${record.custbody_reference_number!"Not provided"}This provides fallback text if the custom body field is empty or unavailable. However, fallback syntax does not solve every missing-field problem. If the field reference itself is invalid for the template context, the template can still fail or produce unexpected output.
A useful debugging distinction is:
Empty value: The field exists, but the transaction has no value.
Invalid reference: The field does not exist in that template context or uses the wrong identifier.
Unavailable object: The parent object, such as a sublist or related record, is not exposed.
Formatting problem: The value exists, but the markup or formatting produces an incorrect visual result.
We test these conditions separately instead of changing several expressions at once.
Why does NetSuite Advanced PDF source code use XML and CSS?
Advanced PDF templates use XML-compatible markup because NetSuite must convert the template into a PDF document with predictable structure. The source may resemble HTML, but it is not equivalent to browser HTML. Browser-specific behavior, unsupported CSS, malformed nesting, and unescaped characters can cause PDF errors or inconsistent output.
For example, this text can create an XML parsing problem:
<p>Sales & Marketing</p>The ampersand should be escaped:
<p>Sales & Marketing</p>The same principle applies to values inserted from records. If a description contains special characters and the value is placed into an attribute or markup context incorrectly, the rendered output can break.
CSS support is also narrower than modern web-browser support. Advanced PDF templates respond best to straightforward rules such as:
<style type="text/css">
body {
font-family: sans-serif;
font-size: 9pt;
}
.total {
font-weight: bold;
text-align: right;
}
table {
width: 100%;
}
</style>Avoid assuming that flexbox, JavaScript, browser events, or advanced responsive behavior will work in the PDF engine. A PDF is fixed-layout output. Table-based layouts, explicit widths, simple display rules, and controlled font sizes provide more stable results.
One practical detail is that CSS placement affects behavior. Global styles belong in the document’s style section, while inline styles are useful for isolated exceptions. If a style appears correct in preview but fails in the downloaded PDF, we inspect unsupported CSS, nested table structure, and page-specific behavior before redesigning the entire template.
How do you debug NetSuite Advanced PDF source code?
The most effective debugging process is incremental. Change one structural or data-related issue, preview the template, and confirm the result before moving to the next issue.
1. Copy the template before editing
Create a backup or duplicate version before changing source code. Record the template name, internal ID, assigned transaction form, and current version. This prevents a failed edit from becoming a production outage.
If several administrators work in the account, include a short change note in the template description or maintain the source in an external version-control system. NetSuite itself is not a substitute for disciplined source history.
2. Confirm the template context
Check the transaction type, form, subsidiary, and printing configuration. A template may render correctly for one record type while failing for another because the available fields differ.
For SuiteScript-generated PDFs, confirm how the renderer is configured. NetSuite’s `N/render` module supports methods such as `setTemplateById`, `addRecord`, and `renderAsPdf`. If the script supplies a custom record or data source, the object name in the template must match the name assigned by the script.
A simplified SuiteScript 2.x pattern looks like this:
define(['N/render'], function(render) {
function createPdf(transaction) {
var renderer = render.create();
renderer.setTemplateById({
id: 123
});
renderer.addRecord({
templateName: 'record',
record: transaction
});
return renderer.renderAsPdf();
}
return {
createPdf: createPdf
};
});The numeric template ID is only an example. The important relationship is between `templateName: 'record'` and expressions such as `${record.tranid}` in the template.
3. Validate field and sublist references
Start with a known field, such as the transaction number, to verify that the primary record is available. Then add more specific fields one at a time.
For line data, confirm:
The correct sublist name
The correct line field ID
Whether the value belongs to the transaction or an associated record
Whether the field is available in the current rendering context
Whether the field is empty on the test transaction
Custom fields should use their script IDs, such as:
${record.custbody_customer_reference}A label shown in the NetSuite interface is not necessarily the identifier required in source code. We use the field’s script ID rather than guessing from its display name.
4. Isolate FreeMarker logic
When a template fails after adding a condition or loop, temporarily replace the block with static text. If the static text renders, the problem is inside the expression, object name, condition, or loop.
Check that every directive has a matching closing directive:
<#if condition>
...
</#if><#list record.item as item>
...
</#list>Nested directives require especially careful indentation. Although whitespace does not determine FreeMarker structure, readable indentation makes missing closures much easier to find.
5. Check XML structure and escaping
A source file can contain valid-looking HTML while still being invalid XML. Inspect unclosed tags, incorrectly nested elements, unescaped ampersands, quotation marks inside attributes, and special characters in dynamic values.
When a template produces a vague parser error, remove the most recent block first. Large-scale rewrites make the source harder to troubleshoot because they eliminate the ability to identify the triggering change.
6. Test with realistic records
A template that works on a simple transaction may fail when it encounters a long description, multiple pages, a blank optional field, a tax line, a foreign currency amount, or a subsidiary-specific logo.
Use test records that exercise the actual layout conditions:
No line items or a large number of line items
Blank and populated optional fields
Long addresses
Multiple tax or shipping values
Negative amounts and credits
Multiple currencies
Different subsidiaries
Long item descriptions
Multiple pages
This is where many page-break and table-width issues become visible.
For broader NetSuite development and customization support, we provide NetSuite development and customization services. The relevant principle is the same whether the change is a template, workflow, custom record, or SuiteScript integration: test the actual data conditions, not only the ideal record.
How do you fix common Advanced PDF layout problems?
Most layout problems fall into a small number of patterns.
Fields show blank. First verify the script ID and record context. Then check whether the field is empty, whether the parent object exists, and whether the template is assigned to the expected form. For custom fields, confirm that the field is available to the role and record type being rendered.
The PDF fails to render. Inspect the last source change for malformed XML, unsupported markup, an unclosed FreeMarker directive, or an invalid expression. Restore the last working copy if the error blocks preview, then reapply changes in smaller increments.
Transaction lines overlap or disappear. Review table structure, explicit column widths, font sizes, and long text behavior. A line description that expands without a controlled column layout can push totals off the page or create unexpected wrapping.
Headers repeat incorrectly. PDF table headers and page behavior depend on the markup structure and renderer support. Keep header rows inside a predictable table structure and test with enough lines to create multiple pages.
Totals move to a new page. Reduce unnecessary spacing, control line-height, and separate the totals table from the detail table. Avoid relying on browser-only CSS rules to keep related elements together.
Images or logos do not appear. Confirm the file reference, file cabinet permissions, and the way the image source is inserted. A logo that is visible to one role may not be available to the rendering process if permissions or file access are incorrect.
Amounts display with the wrong format. Prefer NetSuite’s available formatted values when appropriate, but do not assume every field exposes both raw and formatted versions. Currency, date, and number formatting should be tested across subsidiaries and currencies rather than validated with one transaction.
What should you secure in NetSuite PDF templates?
Advanced PDF templates are document-generation code, so security and access control deserve attention. A template can expose sensitive fields even when the transaction form does not visibly display them elsewhere.
Review who can edit templates, who can access source code, and which roles can print the resulting documents. Do not place passwords, API keys, internal credentials, or other secrets in template source. Avoid exposing internal notes, payment details, employee information, or unneeded custom fields.
External content also requires scrutiny. Referencing remote assets introduces availability and security concerns, while embedding uncontrolled user-entered content increases the risk of malformed markup. Keep dynamic output inside the correct text or attribute context and escape values where required.
NetSuite’s 2026.1 SuiteCloud updates include more explicit attention to secure development practices, including injection prevention, secure file handling, and JavaScript security patterns. Our overview of SuiteCloud Agent Skills for NetSuite 2026.1 provides additional context for teams modernizing their development controls. The practical takeaway for PDF work is direct: limit permissions, keep secrets out of templates, and review every dynamic value that enters the document.
When should you use source code instead of the visual editor?
Use source code when the requirement involves dynamic behavior, repeated lines, conditional content, custom data sources, advanced formatting, or precise page control. Use the visual editor for straightforward text, labels, basic tables, and small styling changes that it represents accurately.
Source editing is not automatically better. It introduces XML and FreeMarker failure points, so a simple label change does not justify a large code revision. The right decision depends on whether the requirement is static presentation or data-driven document behavior.
If a report needs interactive filtering, complex joins, or a user interface rather than a printable document, an Advanced PDF template may be the wrong tool. NetSuite reports, saved searches, Suitelets, or external document services may fit better. We explain that distinction in our guide to when a Suitelet is the right choice in NetSuite.
A practical review standard for production templates
Before publishing a template, we review four areas: data, markup, presentation, and governance.
The data review confirms every field, sublist, custom data source, and fallback condition. The markup review checks XML validity, FreeMarker closure, escaping, and unsupported HTML or CSS. The presentation review tests page breaks, long values, images, fonts, totals, and multiple currencies. The governance review confirms permissions, version history, assignment rules, and rollback procedures.
Keep a small test matrix rather than relying on one sample transaction. A template is production-ready only when it remains readable and accurate across the record conditions that matter to the business.
When the source becomes difficult to maintain, separate repeated logic into clearly named variables where supported, use consistent indentation, and add comments for non-obvious sections. Comments should explain why a workaround exists, not merely repeat what the next line does.
If you need help evaluating a template, correcting a rendering issue, or connecting Advanced PDF output to SuiteScript, contact Versich to discuss your NetSuite requirements.
Conclusion
NetSuite Advanced PDF source code is the control layer behind transaction documents. XML structure determines whether the file can render, FreeMarker connects the document to NetSuite data, CSS shapes the presentation, and SuiteScript can supply additional records or custom data sources.
The safest way to work is methodically: preserve the original template, verify the rendering context, test field references, isolate FreeMarker logic, validate XML, and use realistic records that expose page and data edge cases. With that process, source editing becomes a controlled way to improve invoices, sales orders, purchase orders, statements, and other NetSuite documents instead of a trial-and-error exercise.
