# How to set up product recommendations in email

Setting the Products block's **Source** to **Recommendations** can rank products by **Bestsellers**, **Back in stock**, **Price drop**, **New arrivals**, **Bought together**, or **Based on what they viewed**, without you picking products or writing a catalog rule. See [Get recommended products](/product/content/email-content/drag-and-drop-email-editor/blocks/#get-recommended-products) for every field this source adds. Three of those strategies need data from outside your catalog to work: **Bestsellers** reads your order history, and **Bought together** and **Based on what they viewed** read what shoppers have looked at and bought. This guide covers what to send so each strategy has something to rank.

<Aside type="tip">
Already sending `PW_AbandonedCart` and `PW_OrderCreated` for [abandoned cart recovery](/product/how-to-guides/email-marketing-campaigns/how-to-set-up-an-abandoned-cart-campaign/)? Keep reading. **Bestsellers** needs one more field on `PW_OrderCreated` that the abandoned cart guide doesn't cover.
</Aside>

## Before you begin

Make sure your account's catalog has products in it. Go to **Content → Product Catalog** and connect a feed, import a CSV, or add products by hand. [Learn how to populate your catalog](/product/content/product-catalog/#ways-to-populate-your-catalog).

<Aside type="caution" icon="setting" title="Developer assistance needed">
Sending the events below requires your development team's help, unless your store integration already sends them for you. Please share this guide with them.
</Aside>

<Aside type="note" title="New accounts see the regular catalog first">
Every strategy below needs history to accumulate before it can rank anything. Until then, the block shows the regular catalog instead. See the note under [Get recommended products](/product/content/email-content/drag-and-drop-email-editor/blocks/#get-recommended-products).
</Aside>

## Which strategies need events

Three of the six strategies rank products from events you send; the other three rank directly off your catalog and need nothing from you.

| Strategy | Needs events? | Data source |
| :---- | :---- | :---- |
| **Back in stock** | No | Catalog stock changes |
| **Price drop** | No | Catalog price changes |
| **New arrivals** | No | Catalog "added" date |
| **Bestsellers** (7/30 days) | Yes | `PW_OrderCreated` / `PW_OrderUpdated` with `items` |
| **Based on what they viewed** | Yes | Any event carrying a product ID |
| **Bought together** | Yes | Any event carrying a product ID, plus a device tag |

A stock or price change in your feed, or the next scheduled sync, updates **Back in stock**, **Price drop**, and **New arrivals** automatically. Nothing to send for those three.

## Bestsellers: add items to your order events

**Bestsellers (7 days)** and **Bestsellers (30 days)** rank products by how many units sold in that window. They read the `items` array on `PW_OrderCreated` and `PW_OrderUpdated`, specifically each item's `productId` and `quantity`.

If you already send `PW_OrderCreated` to [clear abandoned cart tags](/product/how-to-guides/email-marketing-campaigns/how-to-set-up-an-abandoned-cart-campaign/#what-happens-when-you-send-pw_ordercreated), that minimal call (just `orderId`) still clears the cart, but it gives Bestsellers nothing to count. Add the order's line items to the same call:

```json
{
  "request": {
    "hwid": "8f65b16df378e7a6bece9614e1530fb2",
    "application": "XXXXX-XXXXX",
    "event": "PW_OrderCreated",
    "attributes": {
      "orderId": "ORDER-10293",
      "items": [
        {
          "productId": "SKU-4821",
          "quantity": 1
        },
        {
          "productId": "SKU-5190",
          "quantity": 2
        }
      ]
    },
    "userId": "shopper@example.com"
  }
}
```

`productId` must match the ID your [Product Catalog](/product/content/product-catalog/) uses for that item, so Bestsellers can look up the product to show. Extra item fields (price, name, and so on) are ignored for this strategy. Only `productId` and `quantity` count toward the ranking. Send the same `items` array on `PW_OrderUpdated` for order edits, refunds, or partial cancellations, since Bestsellers recounts from whatever the latest event for that order says.

<Aside type="caution" title="Send quantity as a number">
Use a real JSON number for `quantity`, not a quoted string. Pushwoosh stores each attribute value only in the type it was first declared or inferred with; a mismatched value is dropped silently, and `postEvent` still returns success. See [Use the correct attribute types](/product/how-to-guides/email-marketing-campaigns/how-to-set-up-an-abandoned-cart-campaign/#create-the-events-in-your-control-panel) for the same caution on `PW_AbandonedCart`.
</Aside>

<Aside type="note">
**Bestsellers** ranks by order history specifically. Views and cart activity don't count. For a ranking that includes browsing and cart activity too, use **Based on what they viewed** or **Bought together** instead.
</Aside>

## Based on what they viewed and Bought together: track product activity

Both strategies build from the same signal: events that carry a product ID. You don't need a dedicated "product viewed" event name — any [custom event](/product/audience-data-and-segmentation/events/custom-events/) sent via [postEvent](/developer/api-reference/user-centric-api/#postevent) counts, as long as its `attributes` include one of these keys:

* A single product, as a top-level attribute: `product_id`, `productId`, `productid`, `item_id`, or `sku`.
* Multiple products, as a `products` array where each item has `product_id`, `productId`, `id`, or `sku`.

For example, fire your existing product-view event with a product ID attribute already on it:

```json
{
  "request": {
    "hwid": "8f65b16df378e7a6bece9614e1530fb2",
    "application": "XXXXX-XXXXX",
    "event": "ProductViewed",
    "attributes": {
      "product_id": "SKU-4821",
      "category": "Audio"
    },
    "userId": "shopper@example.com"
  }
}
```

**Based on what they viewed** ranks each shopper's own recently interacted-with products — no further setup needed once the events above are flowing.

**Bought together** ranks products frequently purchased alongside one anchor product, across your whole account's history. It needs one more thing: a **Product tag**, a [device tag](/developer/api-reference/tags/) that holds the current anchor product's ID. Set the field's name when you configure the strategy in the [Products block](/product/content/email-content/drag-and-drop-email-editor/blocks/#get-recommended-products) (for example `PW_LastViewedProductID`), then keep that tag updated on each device. For example, [set it](/developer/api-reference/tags/) to the product's ID whenever the shopper views a product. Without the tag set on a recipient, the block falls back to the regular catalog for them.

<Aside type="caution" title="Tag name rules">
The tag name only accepts letters, digits, underscores, and spaces, since it has to be addressable in Liquid. See [Bought together needs a Product tag](/product/content/email-content/drag-and-drop-email-editor/blocks/#get-recommended-products).
</Aside>

## Confirm your events are landing

Before you add the block, check that Pushwoosh is actually receiving the events above: go to **Audience → Events**, open the event you sent (`PW_OrderCreated` or the custom event carrying a product ID), and confirm recent hits show up. See [Event statistics](/product/audience-data-and-segmentation/events/).

<Aside type="note">
An empty Products block can mean either "the events never arrived" or "not enough history has accumulated yet" (see the note above). Event statistics rules out the first cause before you chase the second.
</Aside>

## Add the block to your email

Add a [Products](/product/content/email-content/drag-and-drop-email-editor/blocks/#products) block to your [email content](/product/content/email-content/drag-and-drop-email-editor/create-email-content-with-drag-and-drop-editor/), set **Source** to **Recommendations**, and pick a **Strategy**. See [Get recommended products](/product/content/email-content/drag-and-drop-email-editor/blocks/#get-recommended-products) for every field in the settings panel. Click **Refresh preview** to check the canvas fills with real products before you send.