> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pipedform.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Submission Notification

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.

<Note>
  This is available on the **Pro** plan and above.
</Note>

## 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](https://handlebarsjs.com/guide/).

## Available Context Variables

When rendering your email template, PipedForm provides the following context:

| Variable         | Type                | Description                                                    |
| ---------------- | ------------------- | -------------------------------------------------------------- |
| `formName`       | `string`            | The name of your form                                          |
| `unsubscribeUrl` | `string`            | URL for the recipient to unsubscribe from future notifications |
| `reportSpamUrl`  | `string`            | URL for the recipient to report the submission as spam         |
| `ip`             | `string` (optional) | The submitter's IP address, if available                       |
| `originUrl`      | `string` (optional) | The URL of the page the form was submitted from, if available  |
| `fields`         | `object`            | The submitted form data, keyed by field name                   |

## Example Context

```typescript theme={null}
{
  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: 'john@gmail.com',
    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:

| Helper     | Description                                                                                                                            |   |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------- | - |
| `json`     | Serializes a value to a JSON string. Accepts an optional `indent` argument (e.g. `{{json this indent=2}}`) to pretty-print the output. |   |
| `isArray`  | Returns `true` if the given value is an array. Useful inside `{{#if}}` to branch on field type.                                        |   |
| `isObject` | Returns `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:

```handlebars theme={null}
{{#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:

```handlebars theme={null}
{{#if ip}}
  <p>Submitted from IP: {{ip}}</p>
{{/if}}

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

## Full Example

```handlebars theme={null}
<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>
```

<Warning>
  **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.
</Warning>
