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 vip tag" 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

  1. Pick the event it listens to - any Shopify event the app already receives.
  2. Capture a real payload. Make that change in your store and the app grabs the exact event body.
  3. Write a transform - return an object to fire, return null to skip.
  4. Test it against the captured event, and see precisely what your workflow would receive.
  5. 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 null and 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.
Only fire for high-value orders that just got the vip tagjavascript
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