Custom triggers
The built-in triggers cover the changes most stores care about. A custom trigger covers the rest: you pick a Shopify event, write a few lines of JavaScript to decide whether it matters and what to send, and it becomes a trigger you can use in Shopify Flow.
Two things it solves that a built-in trigger cannot:
- Fire only on your condition. "Only when an order over 500 EUR gets the
viptag" is one line of code, instead of a workflow that runs on every order and then filters. - Send exactly the fields you want. Reshape the event into the values your workflow actually uses, rather than reading them back out one by one.
How it works
- Pick the event it listens to - any Shopify event the app already receives.
- Capture a real payload. Make that change in your store and the app grabs the exact event body.
- Write a transform - return an object to fire, return
nullto skip. - Test it against the captured event, and see precisely what your workflow would receive.
- Switch it on.
Writing the transform
Your code receives payload (the raw event body), plus topic and shop.
- Return an object and the trigger fires, carrying that object.
- Return
nulland the event is skipped. This is how filtering works - there is no separate filter language to learn. - Leave the code empty and it fires on every event of that type.
const total = parseFloat(payload.total_price || "0");
const tags = (payload.tags || "").split(",").map(t => t.trim());
if (total < 500) return null;
if (!tags.includes("vip")) return null;
return {
orderId: payload.admin_graphql_api_id,
orderNumber: payload.name,
total,
currency: payload.currency,
customerEmail: payload.email,
};Using it in Shopify Flow
Every custom trigger arrives in Flow as the same trigger: Custom Trigger. Add it to a workflow, then add a condition on Trigger handle equals your trigger's handle.
That handle is shown on the trigger's page and never changes, even if you rename the trigger - so your workflow keeps working.
Each key your transform returns becomes a field on the trigger, and the whole object is also available as JSON if you would rather parse it yourself.
Does a custom trigger use my plan allowance?▾
Yes - each time it fires it counts as one event, exactly like a built-in trigger. Events your code skips by returning null do not count, so a well-filtered custom trigger can use far less of your allowance than a broad built-in one.
Can I change the handle later?▾
No, and that is deliberate. Your Flow workflow filters on the handle, so changing it would silently stop that workflow running. You can rename the trigger freely - the handle stays put.
What happens if my code has a bug?▾
The event is skipped and the error is recorded on the trigger, so you can see what went wrong. A failing transform never blocks anything else - your other triggers, custom or built-in, carry on unaffected.
Where does my code run?▾
In an isolated sandbox, separate from the rest of the app, with a short time limit and no access to your store's credentials. It only ever sees the event payload you captured.
Can it fire on events the app does not already receive?▾
Not at first. A custom trigger listens to the events the app already subscribes to for your store, which depends on the permissions you have granted. Broader event coverage is planned.
Next steps
- Developer API, MCP and trigger simulation - manage and test triggers from your own code or an AI assistant.
- How triggers work - the built-in triggers and how they fire.

