Skip to main content
Customize the content of your submission notification emails using Handlebars, a simple templating language that lets you insert dynamic data from your form submission directly into the email body.
This is available on the Pro plan and above.

Setting Up Your Email Template

Go to your form’s Settings page, then navigate to the Email Configuration > Email Template section. You can edit your template using the built-in editor, which supports Handlebars syntax.

Available Context Variables

When rendering your email template, PipedForm provides the following context:
VariableTypeDescription
formNamestringThe name of your form
unsubscribeUrlstringURL for the recipient to unsubscribe from future notifications
reportSpamUrlstringURL for the recipient to report the submission as spam
ipstring (optional)The submitter’s IP address, if available
originUrlstring (optional)The URL of the page the form was submitted from, if available
fieldsobjectThe submitted form data, keyed by field name

Example Context

{
  formName: 'My Form',
  unsubscribeUrl: 'https://example.com/unsubscribe',
  reportSpamUrl: 'https://example.com/report-spam',
  ip: '127.0.0.1',
  originUrl: 'https://example.com',
  fields: {
    Name: 'John',
    Email: '[email protected]',
    Message: 'This is message from john.',
    Hobbies: ['Reading', 'Gaming', 'Traveling'],
    Company: {
      name: 'Acme Inc',
      role: 'Software Engineer',
    },
    Files: [
      { name: 'File.png', url: 'https://storage.pipedform.com/submission/019f40ed-65aa-754b-90dd-504b87836506.png' },
      { name: 'File2.png', url: 'https://storage.pipedform.com/submission/019f40ed-2046-7985-9628-8ff55ce6a67c.png' },
    ],
  },
}

Custom Helpers

In addition to Handlebars’ built-in helpers {{#each}}, {{#if}}, {{#unless}}, etc.), PipedForm provides the following custom helpers:
HelperDescription
jsonSerializes a value to a JSON string. Accepts an optional indent argument (e.g. {{json this indent=2}}) to pretty-print the output.
isArrayReturns true if the given value is an array. Useful inside {{#if}} to branch on field type.
isObjectReturns true if the given value is an object. Useful inside {{#if}} to branch on field type.

Rendering Submission Fields

Since field values can be strings, arrays, nested objects, or file attachments, PipedForm’s pre-built template uses isArray and isObject to render each field appropriately:
{{#each fields}}
  <div>
    <p>
      {{@key}}
    </p>
    <p>
      {{#if (isArray this)}}
        {{#each this}}
          {{#if url}}
            <a href='{{url}}'>
              {{#if name}}
                {{name}}
              {{else}}
                {{url}}
              {{/if}}
            </a>
          {{else}}
            <code>{{json this indent=2}}</code>
          {{/if}}
          {{#unless @last}}, {{/unless}}
        {{/each}}
      {{else if (isObject this)}}
        <code style='white-space: pre;'>
          {{~json this indent=2~}}
        </code>
      {{else}}
        {{this}}
      {{/if}}
    </p>
  </div>
{{/each}}
This template handles all field types dynamically:
  • Strings and numbers - rendered directly ({{this}}).
  • Arrays - each item is rendered individually. If an item has a url (like a file attachment), it’s rendered as a link using name as the label (or the URL itself if name is missing). Otherwise, the item is rendered as formatted JSON.
  • Objects (like Company) - rendered as pretty-printed JSON using the json helper.

Optional Variables

ip and originUrl may not always be present. Use {{#if}} to render them conditionally:
{{#if ip}}
  <p>Submitted from IP: {{ip}}</p>
{{/if}}

{{#if originUrl}}
  <p>Submitted from: {{originUrl}}</p>
{{/if}}

Full Example

<h1>New submission for {{formName}}</h1>

{{#each fields}}
  <div>
    <p>{{@key}}</p>
    <p>
      {{#if (isArray this)}}
        {{#each this}}
          {{#if url}}
            <a href='{{url}}'>{{#if name}}{{name}}{{else}}{{url}}{{/if}}</a>
          {{else}}
            <code>{{json this indent=2}}</code>
          {{/if}}
          {{#unless @last}}, {{/unless}}
        {{/each}}
      {{else if (isObject this)}}
        <code style='white-space: pre;'>{{~json this indent=2~}}</code>
      {{else}}
        {{this}}
      {{/if}}
    </p>
  </div>
{{/each}}

{{#if ip}}<p>IP: {{ip}}</p>{{/if}}
{{#if originUrl}}<p>Origin: {{originUrl}}</p>{{/if}}

<hr />
<p>
  <a href="{{unsubscribeUrl}}">Unsubscribe</a> |
  <a href="{{reportSpamUrl}}">Report as Spam</a>
</p>
Notes:
  • Field names in fields match the name attribute of your form’s inputs exactly, including capitalization.
  • Field values can be strings, arrays, nested objects, or file attachment arrays ({name, url}[]) - use isArray and isObject to handle each type appropriately.
  • Always include {{unsubscribeUrl}} and {{reportSpamUrl}} links in your template to comply with email best practices.