---
title: Data Mapping
slug: data-mapping
docTags: 
createdAt: 2026-07-31T10:12:59.368Z
---

# JSONPath Data Mapping Guide

Data mapping in Peach allows you to extract information from incoming event payloads (like Shopify webhooks or custom API calls) and map them directly into variables, template placeholders, recipients, or deduplication keys.

This guide explains how to use **JSONPath** to map payload fields, from basic properties to complex structures and calculations.

***

## 1. Mappings Scopes in Peach

There are three main contexts where you will define data mappings in Peach:

1. **Recipient Mapping (**`recipient`**)**
   - **Purpose**: Tells Peach who should receive the message.
   - **Required fields**: Typically maps a phone number (e.g. `phone_number`) and optionally a name.
   - *Note*: If Peach cannot resolve the recipient's phone number, the automation will silently fail to send.
2. **Template Variables (**`variable`**)**
   - **Purpose**: Provides the dynamic content required by your WhatsApp template placeholders (e.g., `{{1}}`, `{{2}}` or named keys).
   - **Usage**: Maps keys like `customer_name` or `order_id` to their values in the webhook payload.
3. **Deduplication Key (**`dedup_key`**)**
   - **Purpose**: Prevents duplicate messages from being sent if the source system sends the same event multiple times.
   - **Usage**: Maps to a unique transaction ID (e.g. `$.order.id` or `$.checkout.token`).

***

## 2. Basic JSONPath Syntax

JSONPath is like XPath or CSS selectors, but for JSON objects. All JSONPaths in Peach must start with `$.` (which refers to the root of the event payload).

### Static Values (No `$.` Prefix)

If a value doesn't start with `$.`, Peach treats it as a static string fallback.

- **Example**: Mapping `first_name` to `Valued Customer` will always output `"Valued Customer"` regardless of the payload.

### Direct Path Matching

- **Payload**:

```json
{
  "customer": {
    "first_name": "Alice",
    "phone": "+1234567890"
  }
}
```

- **Mapping**: `$.customer.first_name` -> **Resolves to**: `"Alice"`
- **Mapping**: `$.customer.phone` -> **Resolves to**: `"+1234567890"`

***

## 3. Peach-Specific Features & Smart Defaults

Peach has built-in smarts to make mapping easier and more resilient.

### Subscriber & Contact Interchangeability

Peach automatically maps `subscriber` and `contact` as aliases.

- If your payload has a `contact` object but you write `$.subscriber.name`, it resolves correctly.
- Likewise, if your payload has a `subscriber` object and you write `$.contact.name`, it also resolves correctly.

### Recursive / Deep Scanning (`$..`)

If you don't know the exact path of a field, or if it can appear at different levels of the JSON structure, use `$..` to search recursively.

- **Payload**:

```json
{
  "customer": {
    "default_address": {
      "phone": "+1999999999"
    }
  }
}
```

- **Mapping**: `$..phone`
- **Resolves to**: `"+1999999999"` (Peach finds the first non-nil match in the object structure).

***

## 4. Working with Lists (Arrays)

If your payload contains lists of items (e.g., order line items), you can extract items or count them.

### Extracting a Specific Item (Index Subscript)

Use `[0]` to get the first item in a list (indexing starts at `0`).

- **Payload**:

```json
{
  "items": [
    { "title": "Blue T-Shirt" },
    { "title": "Red Socks" }
  ]
}
```

- **Mapping**: `$.items[0].title` -> **Resolves to**: `"Blue T-Shirt"`

### Joining Multiple Items

Use `[*]` to select all items. If multiple matches are found, Peach automatically joins them with a comma.

- **Mapping**: `$.items[*].title`
- **Resolves to**: `"Blue T-Shirt, Red Socks"`

### Array Length / Count Helpers

Peach supports `.length`, `.size`, and `.count` helpers directly at the end of your JSONPath.

- **Mapping**: `$.items.length` (or `$.items.size`, `$.items.count`)
- **Resolves to**: `2` (returns the count of items in the list).

***

## 5. Structured JSON Mapping (Fenced JSON Blocks)

Sometimes, you need to map complex parameters (like media file attachments with customized headers). You can provide structured JSON wrapped in markdown-style code fences: ` ```json ... ``` `. Peach will parse the JSON block and resolve any internal values starting with `$.` dynamically.

### Example: Media Headers

When sending a document or image template, you might need to map both the URL and the filename dynamically.

- **Value Input**:

````json
```json
{
  "link": "$.data.invoice.pdf_url",
  "filename": "$.data.invoice.display_name"
}
````

```javascript
```

- **Payload**:

```json
{
  "data": {
    "invoice": {
      "pdf_url": "https://example.com/inv_102.pdf",
      "display_name": "Invoice_August.pdf"
    }
  }
}
```

- **Resulting Output**:

```json
{
  "link": "https://example.com/inv_102.pdf",
  "filename": "Invoice_August.pdf"
}
```

***

## 6. Common Recipes & Examples

### Setup a Notification (Shopify Order Paid)

When setting up a stream trigger on a `Shopify Order Paid` event, use these common mappings:

- **Recipient Phone**: `$.customer.phone` or `$.customer.default_address.phone` (or `$..phone` for safety)
- **Deduplication Key**: `$.id` (using the Order ID to prevent double-processing)
- **Template Variable (Customer Name)**: `$.customer.first_name`
- **Template Variable (Item Summary)**: `$.line_items[*].title`
- **Template Variable (Item Count)**: `$.line_items.length`
