---
title: "Inventory triggers, step by step"
description: "Step-by-step Shopify Flow tutorials for per-location inventory changes, out of stock, back in stock and variant cost changes."
canonical: "https://docs.workflow-trigger-extensions.app/inventory-trigger-tutorials"
---

# Inventory triggers, step by step

Shopify's own inventory triggers work on the variant total and carry no location. These four know **where**: each event names the location and carries the quantity before and after. The fourth one watches the cost per item, which lives on the inventory item as well.

**On this page:** [Inventory Level Changed at Location](#inventory-level-changed-at-location), [Out of Stock at Location](#out-of-stock-at-location), [Back in Stock at Location](#back-in-stock-at-location), [Product Variant Cost Changed](#product-variant-cost-changed)

> [!TIP]
> **New to Shopify Flow?**
> Every example follows the same five moves: pick the trigger, add a condition, add an action, turn the workflow on, check Event History. [Your first workflow, step by step](https://docs.workflow-trigger-extensions.app/first-workflow-tutorial.md) shows each of them with screenshots.

![Shopify Flow's trigger picker inside Workflow Trigger Extensions, searched for at Location](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/6d24b69c6f033179.png)
*Where you find them: in Shopify Flow choose Select a trigger, open Workflow Trigger Extensions and search for "at Location".*

## Inventory Level Changed at Location

Fires whenever the **available** quantity of a variant changes at a location: a sale, a restock, a transfer, a manual correction.

| | |
| --- | --- |
| **Fires from** | Shopify webhook plus change detection |
| **Permission** | **Inventory Data Access** + **Product, Variant & Collection Data Access** |
| **Switched on** | Turning on a Flow workflow that uses it switches it on. Its own switch is on the app's **Triggers** page |

**Use it for**

- Low-stock alerts per location instead of per variant.
- Forward every stock movement to an ERP or a reporting sheet.
- React to large single drops that look like an error.

### What Inventory Level Changed at Location sends to your workflow

| Variable in Flow | Type | What it holds |
| --- | --- | --- |
| `product` | Product (Shopify) | The product whose variant inventory changed. A full Shopify product, so all of its fields and Flow's own product actions are available. |
| `inventoryLevel` | Object | The location, variant/SKU, and old/new/delta available quantity |
| `inventoryLevel.locationId` | ID |  |
| `inventoryLevel.locationName` | Text |  |
| `inventoryLevel.sku` | Text |  |
| `inventoryLevel.variantId` | ID |  |
| `inventoryLevel.variantTitle` | Text |  |
| `inventoryLevel.oldAvailable` | Number |  |
| `inventoryLevel.newAvailable` | Number |  |
| `inventoryLevel.delta` | Number |  |
| `eventId` | Text | The id of this event. Search for it in the app's Event History to see exactly what was sent. |

### Example: Low-stock alert for one warehouse

1. Pick **Inventory Level Changed at Location** as the trigger.
2. Add a **Condition** with three criteria: `inventoryLevel.locationName` **Equal to** `Main warehouse`, `inventoryLevel.newAvailable` **Less than** `5`, and `inventoryLevel.oldAvailable` **Greater than or equal to** `5`.
3. Add **Send internal email**: `{{product.title}} / {{inventoryLevel.variantTitle}} ({{inventoryLevel.sku}}) is down to {{inventoryLevel.newAvailable}} at {{inventoryLevel.locationName}}`.
4. Turn the workflow on.

> [!NOTE]
> **Good to know**
> - The third criterion is the point of having the old value: the alert fires **once**, when the level crosses 5, not on every sale below it.
> - This is a high-volume trigger on a busy store: every sale changes a level. If zero is all you care about, use the two triggers below instead.
> - `delta` is new minus old, so a sale of two is `-2`.

## Out of Stock at Location

Fires when the available quantity of a variant reaches **zero at one location**. The variant may still be in stock elsewhere.

| | |
| --- | --- |
| **Fires from** | Shopify webhook plus change detection |
| **Permission** | **Inventory Data Access** + **Product, Variant & Collection Data Access** |
| **Switched on** | Turning on a Flow workflow that uses it switches it on. Its own switch is on the app's **Triggers** page |

**Use it for**

- Tell a store manager that a shelf is empty while the warehouse still has stock.
- Request a transfer between locations.
- Switch a product to pre-order when the last location runs out.

### What Out of Stock at Location sends to your workflow

| Variable in Flow | Type | What it holds |
| --- | --- | --- |
| `product` | Product (Shopify) | The product whose variant went out of stock at the location. A full Shopify product, so all of its fields and Flow's own product actions are available. |
| `inventoryLevel` | Object | The location, variant/SKU, and old/new available quantity |
| `inventoryLevel.locationId` | ID |  |
| `inventoryLevel.locationName` | Text |  |
| `inventoryLevel.sku` | Text |  |
| `inventoryLevel.variantId` | ID |  |
| `inventoryLevel.variantTitle` | Text |  |
| `inventoryLevel.oldAvailable` | Number |  |
| `inventoryLevel.newAvailable` | Number |  |
| `inventoryLevel.delta` | Number |  |
| `eventId` | Text | The id of this event. Search for it in the app's Event History to see exactly what was sent. |

### Example: Request a transfer when a store runs out

1. Pick **Out of Stock at Location** as the trigger.
2. Add a **Condition**: `inventoryLevel.locationName` **Not equal to** `Main warehouse`.
3. Add **Send internal email** to logistics: `{{inventoryLevel.locationName}} is out of {{product.title}} / {{inventoryLevel.variantTitle}}`.
4. Turn the workflow on.

> [!NOTE]
> **Good to know**
> To act only when the variant is sold out **everywhere**, add **Get product variant data** and check its total inventory quantity.

## Back in Stock at Location

Fires when the available quantity of a variant goes from **zero to above zero** at a location.

| | |
| --- | --- |
| **Fires from** | Shopify webhook plus change detection |
| **Permission** | **Inventory Data Access** + **Product, Variant & Collection Data Access** |
| **Switched on** | Turning on a Flow workflow that uses it switches it on. Its own switch is on the app's **Triggers** page |

**Use it for**

- Send back-in-stock notifications or tell sales a waiting order can ship.
- Remove a `sold-out` tag or switch ads back on.

### What Back in Stock at Location sends to your workflow

| Variable in Flow | Type | What it holds |
| --- | --- | --- |
| `product` | Product (Shopify) | The product whose variant came back in stock at the location. A full Shopify product, so all of its fields and Flow's own product actions are available. |
| `inventoryLevel` | Object | The location, variant/SKU, and old/new available quantity |
| `inventoryLevel.locationId` | ID |  |
| `inventoryLevel.locationName` | Text |  |
| `inventoryLevel.sku` | Text |  |
| `inventoryLevel.variantId` | ID |  |
| `inventoryLevel.variantTitle` | Text |  |
| `inventoryLevel.oldAvailable` | Number |  |
| `inventoryLevel.newAvailable` | Number |  |
| `inventoryLevel.delta` | Number |  |
| `eventId` | Text | The id of this event. Search for it in the app's Event History to see exactly what was sent. |

### Example: Remove the sold-out tag when stock returns

1. Pick **Back in Stock at Location** as the trigger.
2. Add **Remove product tags** with `sold-out`.
3. Optional: add **Send internal email** with `{{inventoryLevel.newAvailable}}` units at `{{inventoryLevel.locationName}}`.
4. Turn the workflow on.

> [!NOTE]
> **Good to know**
> It fires per location. A product that is restocked at three locations sends three events.

## Product Variant Cost Changed

Fires when the **cost per item** of a variant changes, with the old and new cost, `delta`, `percentChange` and `direction`.

| | |
| --- | --- |
| **Fires from** | Shopify webhook plus change detection |
| **Permission** | **Inventory Data Access** + **Product, Variant & Collection Data Access** |
| **Switched on** | Turning on a Flow workflow that uses it switches it on. Its own switch is on the app's **Triggers** page |

**Use it for**

- Re-check margins when a supplier raises prices.
- Flag variants whose cost now exceeds a share of the price.

### What Product Variant Cost Changed sends to your workflow

| Variable in Flow | Type | What it holds |
| --- | --- | --- |
| `product` | Product (Shopify) | The product whose variant cost changed. A full Shopify product, so all of its fields and Flow's own product actions are available. |
| `variantCostChange` | Object | The variant/SKU and the old and new cost per item |
| `variantCostChange.variantId` | ID |  |
| `variantCostChange.variantTitle` | Text |  |
| `variantCostChange.sku` | Text |  |
| `variantCostChange.oldCost` | Money (amount, currencyCode) |  |
| `variantCostChange.newCost` | Money (amount, currencyCode) |  |
| `variantCostChange.delta` | Number | New value minus old value. Null when either side is unknown |
| `variantCostChange.percentChange` | Number | Change as a percentage of the old value (-12.5 = dropped by 12.5 percent). Null when the old value is 0 or unknown |
| `variantCostChange.direction` | Text | increase, decrease or unchanged |
| `eventId` | Text | The id of this event. Search for it in the app's Event History to see exactly what was sent. |

### Example: Review the price when cost rises by more than 5 percent

1. Pick **Product Variant Cost Changed** as the trigger.
2. Add a **Condition**: `variantCostChange.percentChange` **Greater than** `5`.
3. Add **Add product tags** with `margin-review` and **Send internal email** with `{{variantCostChange.oldCost.amount}} -> {{variantCostChange.newCost.amount}}` for `{{variantCostChange.sku}}`.
4. Turn the workflow on.

> [!NOTE]
> **Good to know**
> - Cost lives on the inventory item, which is why this trigger needs **Inventory Data Access** rather than only product access.
> - When you switch it on the app reads the current cost of every variant once, so that the first real change fires.

## Next steps

All four need **Inventory Data Access** and **Product Data Access** (the event carries the product as a reference). Granting Inventory access also asks for Locations access, so events can name the location.

- [Complete trigger reference](https://docs.workflow-trigger-extensions.app/trigger-reference.md) - every trigger on one page.
- [Choosing the right trigger](https://docs.workflow-trigger-extensions.app/choosing-the-right-trigger.md) - which one fits your case.
- [Custom triggers](https://docs.workflow-trigger-extensions.app/custom-triggers.md) - when no built-in trigger fits, write your own.
- [Event history and troubleshooting](https://docs.workflow-trigger-extensions.app/event-history-and-troubleshooting.md) - see what fired and what it carried.
