Custom JavaScript

Last updated March 23, 2026

The template editor provides an HTML tab and a CSS tab but no dedicated JavaScript tab. You can still use JavaScript by adding script tags directly in your HTML.

Using Script Tags

To use JavaScript in your templates, open a script tag in the HTML tab:

<script>
  // Write some JavaScript in here.
</script>

You can add as many script tags as needed, anywhere in your HTML.

Accessing Document Data

To make JavaScript more powerful in your templates, you can access your Document payload as a JavaScript object.

Start by enabling JavaScript injection for your template in its Settings tab:

Once enabled, a $docPayload object becomes available in your scripts. For example, given this payload:

{
  "movie": {
    "title": "12 Monkeys",
    "year": 1995
  }
}

You can access the data like this:

<script>
  const movieTitle = $docPayload.movie.title;
  const titleDiv = document.getElementById('mt');
  titleDiv.textContent = movieTitle;
</script>

<div id="mt"></div>

Data access limitation with JavaScript

When accessing data with JS, you cannot insert it using the {{movieTitle}} syntax. This syntax is specific to Liquid and is executed before your JS code runs.

That said, you can generate JS code using Liquid:

<script>
  const movieTitle = "{{movieTitle | upcase}}";
</script>

External Libraries

Paid account only

Including JavaScript based on their URL is only possible on a paid account. Documents including external JavaScript files will fail on a free account. See External Resources for the full list.

If you need a library that transforms text, applies filters to images, or inserts charts in your Document, you can import it like you would in a normal HTML page.

For example, to render a Markdown string from your payload using marked.js:

<div id="notes"></div>

<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
  document.getElementById('notes').innerHTML = marked.parse($docPayload.notes);
</script>

Any library loadable via CDN can be used in your templates this way.

Formatting Dates and Times

PDFMonkey’s engine runs on AWS servers located in Europe. The timezone of the server might not be the one you want your dates displayed in.

Use Liquid first

Most date formatting needs are covered by Liquid filters alone, no JavaScript required. Use the in_time_zone filter to set a timezone and the date filter to format a date.

If Liquid filters don’t cover your needs, JavaScript offers additional options.

toLocaleString(locales, options)

The toLocaleString method returns a string with a language-sensitive representation of a date.

The locales and options arguments let you specify the language whose formatting conventions should be used and customize the behavior of the function.

<script>
  // Displaying the current date (PDF generation date) using French conventions.
  //
  new Date().toLocaleString('fr-FR');
  //=> "25/10/2050, 12:34:56"

  // Displaying a date provided in your Document payload using US conventions.
  // Sample payload
  // { "someDate": "2050-10-25 12:34:56" }
  //
  new Date($docPayload.someDate).toLocaleString('en-US');
  //=> "10/25/2050, 12:34:56 PM"

  // Displaying a date using en-US conventions in a custom timezone.
  //
  let date = new Date(Date.UTC(2050, 1, 1, 12, 34, 56));
  new Date(date).toLocaleString('en-GB', { timeZone: 'Pacific/Honolulu' });
  //=> "01/02/2050, 02:34:56"
</script>

You can learn more about the toLocaleString method in its MDN documentation page.

Using a Library

Paid account only

Using an external JS library will only work on a paid account. On a free account preview and generation will be blocked.

If you need the help of a more powerful library, you can load the one you need. The most frequently used one is MomentJS but we recommend Luxon, a more recent iteration of the same idea by the actual author of MomentJS:

<script src="https://cdn.jsdelivr.net/npm/luxon@2.3.1/build/global/luxon.min.js"></script>
<script>
  let { DateTime } = luxon;
  let date = DateTime.fromISO("2050-01-01T12:34:56");
  date.plus({ days: 3 }).setZone('Pacific/Honolulu').toLocaleString(DateTime.DATETIME_HUGE);
  //=> "Tuesday, 4 January 2050, 01:34 Hawaii-Aleutian Standard Time"
</script>

Including Charts

Paid account only

Including JavaScript based on their URL is only possible on a paid account. Documents including external JavaScript files will fail on a free account. See External Resources for the full list.

You can use most charting libraries to generate charts in PDFMonkey. From our experience, Chart.js is the most reliable option —it renders consistently across PDF readers and offers a wide variety of chart types.

Two settings are essential for charts in PDFs:

  • animation: false —Animations don’t play in a PDF. If left enabled, the chart may render mid-transition, producing a blank or half-drawn graphic.
  • responsive: false —Disabling this lets you control the chart size through the canvas element’s width and height attributes, avoiding layout surprises.

Chart.js Example

The example below loads Chart.js from a CDN and renders a bar chart using data from the Document payload. It includes both critical settings mentioned above.

Given this payload:

{
  "chart": {
    "labels": ["Jan", "Feb", "Mar", "Apr", "May"],
    "values": [120, 190, 150, 210, 175]
  }
}

Add this to your template’s HTML:

<canvas id="myChart" width="500" height="300"></canvas>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.js"></script>
<script>
  new Chart(document.getElementById('myChart'), {
    type: 'bar',
    data: {
      labels: $docPayload.chart.labels,
      datasets: [{
        label: 'Monthly sales',
        data: $docPayload.chart.values,
        backgroundColor: '#4f8bc6'
      }]
    },
    options: {
      animation: false,
      responsive: false
    }
  });
</script>

Example bar chart rendered with Chart.js

You can adapt this example to any Chart.js chart type (line, pie, doughnut, radar, etc.) by changing the type value and adjusting the data structure.

ApexCharts compatibility

ApexCharts.js is known to produce black borders around charts in certain PDF readers, particularly on Windows and Android. If you use ApexCharts, test your output across multiple devices before going to production.

Debugging

If your JavaScript is not behaving as expected, use the Debug button at the top of the template editor. It opens the HTML version of your template, generated from your test data, directly in your browser.

This gives you a chance to inspect JS errors in the console and should help in understanding what is going wrong.

Browser Compatibility

Our current PDF engine (v5) is based on Chrome 133. You can check if a specific JS feature is available using the caniuse comparison table.

If your templates use an older engine version, check Our Engines to see which Chrome version applies to your engine.

Frequently asked questions

Can I use JavaScript in PDFMonkey templates?
Yes. Add script tags directly in the HTML tab of the template editor. Enable JavaScript injection in the template settings to access your document payload via the $docPayload object.
What JavaScript libraries are available in PDFMonkey?
Chart.js for charts and graphs, and Day.js for date formatting are built into the rendering engine. On paid plans, you can also load external JavaScript libraries from a CDN.
How do I access document data from JavaScript in PDFMonkey?
Enable JavaScript injection in the template settings. A $docPayload object then becomes available in your scripts, containing the full JSON payload you passed when creating the document.