> For the complete documentation index, see [llms.txt](https://docs.datajet-app.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.datajet-app.com/functions/functions/discounts.md).

# Discounts

Apply automatic product and order discounts at checkout with JavaScript.

A discount function applies automatic discounts to cart lines or the whole order. Your code inspects the cart and returns a list of operations with discount candidates.

```javascript
var candidates = input.cart.lines.map(function (line) {
  return {
    targets: [{ cartLine: { id: line.id } }],
    value: { percentage: { value: 10 } },
  };
});

return {
  operations: [
    { productDiscountsAdd: { selectionStrategy: 'FIRST', candidates: candidates } },
  ],
};
```

The cart lines are in `input.cart.lines`, each with an `id` your candidates target. The discount's own settings are in `input.discount` (`discountClasses`).

{% hint style="info" %}
The function's **title** is shown to buyers at checkout as the discount name — pick something merchant-shippable like `10% off accessories`.
{% endhint %}

### Operations

Return an array of operations, or `{ operations: [...] }`. Each operation is an object with exactly one of these keys:

| Operation         | Shape                                                                        | Effect                          |
| ----------------- | ---------------------------------------------------------------------------- | ------------------------------- |
| Product discounts | `{ productDiscountsAdd: { selectionStrategy: 'FIRST', candidates: [...] } }` | Discounts individual cart lines |
| Order discounts   | `{ orderDiscountsAdd: { selectionStrategy: 'FIRST', candidates: [...] } }`   | Discounts the order subtotal    |

Each candidate is:

```javascript
{
  message: 'Loyalty discount',                 // optional, shown next to the discount
  targets: [{ cartLine: { id: line.id } }],    // product discounts target cart lines
  // targets: [{ orderSubtotal: { excludedCartLineIds: [] } }],  // order discounts
  value: { percentage: { value: 10 } },        // or { fixedAmount: { amount: '10.0' } }
}
```

`selectionStrategy` decides what happens when several candidates match the same target: `FIRST` applies the first one, `MAXIMUM` the largest. Returning an empty array applies no discount. Operations of any other shape are ignored.

### How DataJet manages the discount

* Discount functions appear in the Shopify admin under **Discounts** as automatic discounts.
* The function covers the **product** and **order** discount classes; discount codes and shipping discounts are not part of discount functions.
* Enabling in the Functions Console activates the discount immediately (no start/end scheduling); disabling deactivates it.
* DataJet discounts combine with other product, order and shipping discounts.
* Shopify allows at most **25 active automatic discounts per store** — this cap is shared with the discounts the merchant creates outside DataJet.

### Examples

**10% off products with a tag** (use the *Product* family with the `hasProductTags` variable):

```javascript
var candidates = [];

input.cart.lines.forEach(function (line) {
  var product = line.merchandise && line.merchandise.product;
  var tagged = product && product.hasTags && product.hasTags.some(function (t) { return t.hasTag; });
  if (tagged) {
    candidates.push({
      message: 'Sale',
      targets: [{ cartLine: { id: line.id } }],
      value: { percentage: { value: 10 } },
    });
  }
});

if (!candidates.length) return { operations: [] };
return { operations: [{ productDiscountsAdd: { selectionStrategy: 'FIRST', candidates: candidates } }] };
```

**Order discount above a threshold from vars** (use the *General* or *Cart* family; set `MIN_ORDER_TOTAL` and `ORDER_DISCOUNT_PERCENT` as code variables):

```javascript
var total = parseFloat(input.cart.cost.totalAmount.amount);
var min = parseFloat(vars.MIN_ORDER_TOTAL || '200');
var percent = parseFloat(vars.ORDER_DISCOUNT_PERCENT || '5');

if (total < min) return { operations: [] };

return {
  operations: [
    {
      orderDiscountsAdd: {
        selectionStrategy: 'FIRST',
        candidates: [
          {
            message: percent + '% off orders over ' + min,
            targets: [{ orderSubtotal: { excludedCartLineIds: [] } }],
            value: { percentage: { value: percent } },
          },
        ],
      },
    },
  ],
};
```

### Notes

* Discount functions don't use the **Run on** steps — they run whenever the cart changes.
* All amounts are in the presentment currency (what the buyer pays).
* If your code throws, no discount is applied (fail open).
* See also: [Cart and Checkout Validation](/functions/functions/cart-and-checkout-validation.md), [Delivery Customization](/functions/functions/delivery-customization.md), [Payment Customization](/functions/functions/payment-customization.md).
