# How to set up an abandoned cart campaign

Shoppers who add items to a cart and leave without buying are some of the easiest conversions to recover. They've already shown intent.

This guide shows how to send them an abandoned cart email in Pushwoosh: fire the `PW_AbandonedCart` event from your store, show the left-behind items in the email with the [Products](/product/content/email-content/drag-and-drop-email-editor/blocks/#products) block, and trigger the send from a Customer Journey.

## What is PW_AbandonedCart

`PW_AbandonedCart` marks that a user left items in their cart without buying. It is not a built-in [default event](/product/audience-data-and-segmentation/events/default-events/). It is a shared event name used across Pushwoosh e-commerce integrations so journeys, the Products block, and segments all work the same way.

* **[Magento integration](/product/integrations/magento-integration/):** sends `PW_AbandonedCart` and `PW_OrderCreated` for you automatically.
* **Any other store or custom backend:** your team sends both events via [postEvent](/developer/api-reference/user-centric-api/#postevent) with the names and attributes in [How to send abandoned cart reminders](#how-to-send-abandoned-cart-reminders).

### What happens when you send PW_AbandonedCart

Sending `PW_AbandonedCart` does two things on the Pushwoosh side:

1. It's recorded like any other custom event, so you can see it in [Event statistics](/product/audience-data-and-segmentation/events/) and use it in [segments](/product/audience-data-and-segmentation/segmentation/create-segments/by-events/).
2. Pushwoosh stores the cart contents and tags the user with:
   * **PW_AbandonedCartID:** an identifier for the current cart, used to fetch its contents at send time.
   * **PW_AbandonedCartDate:** the `abandonedDate` value from the event payload.

### What happens when you send PW_OrderCreated

When the shopper places an order, send `PW_OrderCreated` (or `PW_OrderUpdated`). Pushwoosh clears `PW_AbandonedCartID` and `PW_AbandonedCartDate` for that user right away. It does not match `orderId` values: any order from the user removes both tags, even if the purchase was for a different cart.

**Example:** A shopper abandons cart `ORDER-100`, then buys `ORDER-200` before the reminder goes out. Pushwoosh clears the tags, so they won't get a reminder about `ORDER-100`.

<Aside type="note" title="What appears in the reminder email">
The Products block reads the cart stored on the user profile at send time. It does not use the item list from the `PW_AbandonedCart` event that started the journey.

* **Same `orderId`:** each new `PW_AbandonedCart` overwrites the stored cart. The reminder shows the latest items.
* **Different `orderId`:** Pushwoosh stores a separate cart. Items are not merged.
</Aside>

## How to send abandoned cart reminders

Follow these steps to create the events, send them from your store, build the email, and launch the Customer Journey.

### Create the events in your Control Panel

1. Go to **Audience → Events** in your Pushwoosh Control Panel and click **Create Event**.
2. Create a custom event named `PW_AbandonedCart` with these attributes:

   | Attribute | Type |
   | :---- | :---- |
   | `email` | string |
   | `orderId` | string |
   | `customerId` | string |
   | `orderUrl` | string |
   | `abandonedDate` | date |
   | `createdDate` | date |
   | `totalPrice` | decimal (price) |
   | `shippingAmount` | decimal (price) |
   | `taxAmount` | decimal (price) |
   | `discountAmount` | decimal (price) |
   | `currency` | string |

3. Repeat for `PW_OrderCreated` with a single `orderId` attribute.

<Aside type="caution" title="Use the correct attribute types">
Pushwoosh only stores attributes you declared when you created the event, and only in the types you chose. Extra fields, missing fields, or values that don't match the type are dropped without an error. `postEvent` still returns success, so you won't see in the response that data was lost.

For abandoned cart to work, match the types in the table above:

* **Money fields** (`totalPrice`, `shippingAmount`, `taxAmount`, `discountAmount`): use **decimal (price)**. Declared as **string**, the cart is not stored and no tags are set. Declared as **integer**, `129.90` becomes `129`.
* **Dates** (`abandonedDate`, `createdDate`): use **date**.
* **`items`:** do not add it to the event definition. Send it in the JSON payload as an array of objects. Use real JSON numbers for `price` and `quantity`, not quoted strings.
</Aside>

[Learn more about creating custom events](/product/audience-data-and-segmentation/events/custom-events/#creating-custom-events).

### Send the events from your backend

<Aside type="caution" icon="setting" title="Developer assistance needed">
You'll need your development team's help to send events from your store or backend. Please share this guide with them.
</Aside>

Ask your development team to call [postEvent](/developer/api-reference/user-centric-api/#postevent) whenever a cart is abandoned, using this attribute schema:

```json
{
  "request": {
    "hwid": "8f65b16df378e7a6bece9614e1530fb2",
    "application": "XXXXX-XXXXX",
    "event": "PW_AbandonedCart",
    "attributes": {
      "email": "shopper@example.com",
      "orderId": "ORDER-10293",
      "customerId": "CUST-4471",
      "orderUrl": "https://yourstore.com/cart/restore/ORDER-10293",
      "abandonedDate": "2026-07-28T10:15:00Z",
      "createdDate": "2026-07-28T09:40:00Z",
      "totalPrice": 129.90,
      "shippingAmount": 9.90,
      "taxAmount": 0,
      "discountAmount": 0,
      "currency": "USD",
      "items": [
        {
          "productId": "SKU-4821",
          "name": "Wireless headphones",
          "quantity": 1,
          "price": 119.90,
          "sku": "SKU-4821",
          "description": "Over-ear, noise-cancelling",
          "imageUrl": "https://yourstore.com/media/sku-4821.jpg",
          "productUrl": "https://yourstore.com/products/sku-4821",
          "category": "Audio"
        }
      ]
    },
    "userId": "shopper@example.com"
  }
}
```

When the cart converts into an order, send `PW_OrderCreated` with just the `orderId` to clear the cart tags:

```json
{
  "request": {
    "hwid": "8f65b16df378e7a6bece9614e1530fb2",
    "application": "XXXXX-XXXXX",
    "event": "PW_OrderCreated",
    "attributes": {
      "orderId": "ORDER-10293"
    },
    "userId": "shopper@example.com"
  }
}
```

<Aside type="tip">
If you use the [Magento integration](/product/integrations/magento-integration/#abandoned-cart-sync-configuration), you don't need to send these events from your backend. Magento sends `PW_AbandonedCart` and `PW_OrderCreated` for you on a schedule.
</Aside>

### Add a Products block to your email

1. Open the [email content editor](/product/content/email-content/drag-and-drop-email-editor/) and add a [Products](/product/content/email-content/drag-and-drop-email-editor/blocks/#products) block to the canvas.
2. In the settings panel, set **Source** to [Cart](/product/content/email-content/drag-and-drop-email-editor/blocks/#show-items-from-the-cart).

<Aside type="note">
The Products block **Cart** source needs **Content Templates** on your plan and an [API access token](/developer/api-reference/api-access-token/). See [Products block](/product/content/email-content/drag-and-drop-email-editor/blocks/#products).
</Aside>

3. Set **Max products shown** to limit how many cart items appear in the email.

<img src="/lifecycle-marketing-campaigns-how-to-set-up-an-abandoned-cart-campaign-1.webp" alt="Products block settings with Source set to Cart and Max products shown"/>

4. Style the grid and card template as needed. See [Style the grid](/product/content/email-content/drag-and-drop-email-editor/blocks/#style-the-grid).

<img src="/lifecycle-marketing-campaigns-how-to-set-up-an-abandoned-cart-campaign-2.webp" alt="Products block on the email canvas with card template and grid style settings" width="580"/>

When the email sends, the Products block looks up each recipient's stored cart using their `PW_AbandonedCartID` tag. It then fills the block with the current cart items: image, title, price, and a link back to the cart. The layout comes from the card template you set in the editor. Recipients without that tag (nothing abandoned, or already ordered) skip the block instead of showing empty content, so it's safe to use in a broader campaign too.

<Aside type="tip">
The Cart source is available in the email content editor. To remind shoppers with a push instead, use a [Push](/product/customer-journey/journey-elements/channels/push/) step with [personalization](/product/personalization/dynamic-content/) that references the cart details from the event.
</Aside>

### Build the Customer Journey

1. Add a [Trigger-based Entry](/product/customer-journey/journey-elements/entry-elements/trigger-based-entry/) using the `PW_AbandonedCart` event.
2. Add a [Wait for Trigger](/product/customer-journey/journey-elements/flow-controls/wait-for-trigger/) step. Set its waiting period to an hour or two. Name the branch **Order placed** and add the `PW_OrderCreated` event to it.

<Aside type="caution">
Set the waiting period on **Wait for Trigger** itself. Do not add a separate **Time Delay** step before it.

**Wait for Trigger** only starts listening for `PW_OrderCreated` once the shopper reaches that step. If **Time Delay** comes first and the shopper places an order during that delay, the order event goes undetected. The shopper moves to the **Not triggered** branch, but `PW_OrderCreated` has already cleared `PW_AbandonedCartID`. The Products block finds no cart and skips it. The shopper still receives the abandoned cart email with no products, even though they already completed their purchase.
</Aside>

3. Route the **Order placed** branch to [Exit](/product/customer-journey/journey-elements/flow-controls/exit/). The user already bought, so don't remind them.
4. Route the **Not triggered** branch to the [Email](/product/customer-journey/journey-elements/channels/email/) step. Save the email you built in [Add a Products block to your email](#add-a-products-block-to-your-email) as [email content](/product/content/email-content/), then select it as this step's content.

<img src="/lifecycle-marketing-campaigns-how-to-set-up-an-abandoned-cart-campaign-3.webp" alt="Customer Journey canvas with Trigger-based Entry, Wait for Trigger with Order placed and Not triggered branches, Email and Exit steps, and no Time Delay"/>

### Test before you launch

1. Send a test `PW_AbandonedCart` event for a test device. Don't set the `PW_AbandonedCartID` tag manually: the Products block loads cart contents from the stored cart that the event creates, not from the tag value. Without a real event, the block renders empty.
2. Preview the email and confirm the layout and product content before sending to real shoppers.