Old and new values everywhere, scheduled custom triggers, and a faster interface
Knowing that something changed is rarely enough. A workflow usually needs to know what it was before: did the price go down or up, by how much, which tag was added, what the metafield said yesterday. This release makes the old and the new value available across the app, and lets a custom trigger start a workflow when nothing happened at all.
Old and new values, everywhere
- Metafield triggers now carry the previous value. Every metafield trigger (generic, product, variant, order, customer) hands Flow
Metafield.previousValuenext toMetafield.value. It is empty when the metafield was just created. See Metafield triggers. - Price, unit price and cost changes come with the numbers. Flow conditions cannot do arithmetic, so Variant Price Changed, Variant Unit Price Changed and Product Variant Cost Changed now also deliver
delta(new minus old),percentChangeanddirection(increase, decrease, unchanged). "Price dropped by more than 10%" is now one condition, with no code. - Product Update, Order Update and Customer Update tell you what changed. They used to say only that the record was updated. They now carry
changes: the list of changed fields and, for each, the old and the new value. Tracked fields are title, description, status, tags, vendor, type and handle for products; payment status, fulfillment status, line items, tags, note and additional details for orders; tags, note and account state for customers. Long values are shortened. The list is empty when the update was outside those fields, for example an inventory change. - Draft Order Line Items Changed now delivers the same line-by-line diff as the order trigger: what was added, removed, or changed in quantity, price or variant.
- Your own custom trigger code sees the old and the new value too. A custom trigger on Product Update, Order Update or Customer Update now receives
payload._changes: every tracked field that changed, each witholdValueandnewValue. So your code can fire on a transition rather than a state - "status went from draft to active", "the order became paid" - which a condition on the current value cannot express. The sample event you capture in the editor shows the field.
Everything is additive. Workflows you have already built keep working unchanged. The full field list per trigger is in the trigger reference.
Choose which changes fire an Update trigger
Product Update, Order Update and Customer Update have a new setting, behind the gear next to their switch on the Triggers page: Which changes fire this.
- Nothing checked: the trigger fires on every update, exactly as it always has.
- Fields checked: it fires only when one of them changed. Every other update is skipped and does not count towards your plan.
This is also the clean way to stop a workflow from triggering itself. A workflow that starts on Product Update and then writes a product metafield used to start itself again. Narrow the trigger to the fields you care about and that second update no longer fires.
Your other triggers are not affected by this choice. Narrowing Order Update to payment status does not change when Order Tags Added fires.
Custom triggers that run on a schedule
Shopify Flow reacts when something happens. It cannot react when something does not happen, and it cannot see anything outside your store. A custom trigger now can. The editor asks What makes this run: One Shopify event, or On a schedule. On a schedule, your code runs every 30 seconds up to once a day. It remembers what it saw on the last run, can read your store and call anything on the public internet, and decides for itself what counts as a change.
Start from a template and edit the numbers at the top:
- Product, order or customer not updated for N days - stale catalogue reviews, stuck orders, win-back. Each record fires once per quiet period; anything already overdue when you switch it on does not fire all at once.
- A value outside Shopify changed - a supplier stock feed, an exchange rate, a price list. Fires with the value before and after, and the difference and percentage for numbers.
- New item in an RSS or Atom feed - supplier news, a listing feed, a status page.
- No orders for N hours - a heartbeat for your store. Fires once when orders stop and once when they return.
The first run of a scheduled trigger only remembers what it sees, so switching one on never floods your workflows. It appears in Shopify Flow as Custom Trigger, filtered by its handle, and the record comes along as its id. Every run counts towards your plan, whether or not it fires - the editor shows how many runs an interval adds up to. Test runs your code once without firing anything.
Templates for event-based custom triggers
Custom triggers that listen to a Shopify event now have templates as well. Pick one under Start from a template and it selects the event and fills in the code. Each one reads the value before and after the change:
- A product, order or customer field changed from one value to another - for example status went from draft to active, or an order became paid.
- Price dropped by more than N percent - a real markdown, not every price edit.
- Stock fell below a threshold - fires once, at the moment stock crosses the line, not on every sale while it is already low.
- Product metafield number crossed a threshold - a rating fell below 3, a margin went above 40.
- Order paid by a high-value customer - reads the customer's lifetime spend from your store with
ctx.shopify()and fires only above the amount you set.
A record's trigger events on its own admin page
New admin blocks show the latest trigger events about the record you are looking at, right on its page in the Shopify admin, each with a short old -> new line such as price: 100.00 -> 85.00. From there you can open the event, or a view of Event History for that one record.
Available for products, variants, orders, draft orders, customers, collections, companies and company locations. Add the block once from the page's customise menu. Triggers that handle personal data are listed without their values. How to add it, with an example on a product, an order and a customer page: Trigger events on a record's admin page.
More AI providers for Generate with AI
Generate with AI now works with Google Gemini and OpenRouter in addition to Anthropic and OpenAI. OpenRouter gives you models from many companies with one key, including any model id you type in. Connect a key on Developer -> Connections: get a Gemini API key or get an OpenRouter API key. As before, generation runs on your own provider account and the key is encrypted and never shown again.
A faster interface, built on Shopify's web components
Every page of the app has been rebuilt on Shopify's new admin web components, the same building blocks the Shopify admin itself uses.
- Faster to load. The app no longer ships its own copy of an interface library. The components come from Shopify, are shared with the rest of your admin and are usually already in your browser's cache, so each page has far less to download before it appears.
- Feels like the admin. Buttons, tables, switches, dialogs and forms look and behave exactly like the ones you use everywhere else in Shopify, including keyboard navigation and screen readers.
- Stays current. When Shopify improves its components, the app picks the improvement up without an update from us.
Nothing moved: every page, setting and link is where it was.
Also in this release
- Grant all and Revoke all on the Permissions page. Grant all asks for every missing permission in a single Shopify dialog instead of one per card. Revoke all asks you to confirm first and tells you what it means: your triggers stay switched on, they just cannot fire until you grant access again.
- Custom trigger code can call the public internet with
ctx.fetch(), not only your store withctx.shopify(). Internal addresses are refused. - Your custom triggers and your storefront triggers now behave the same: click the row to edit, status on the right.
- The Triggers page shows how many triggers are on next to its title, and the four typed metafield triggers now have their own switches in the list.
- Required fields are marked on the custom trigger, storefront trigger and connection forms.
- Fixed: a date filter in Event History could not be cleared. Removing the date chip or choosing Clear all left the dates applied. Both now clear them.
- Event History rows are plain text rather than blue links. The whole row is still clickable.

