Run code and functions

The Run function step runs your own JavaScript in a secure sandbox. Use it when a calculation, a data format or a decision is easier to write in code than to click together. The code gets the event and the results of all earlier steps, and what it returns is the step's result.

Two ways to bring the code

In the step, Code offers:

  • Write the code in this step - the JavaScript lives in the workflow. Good for code only this workflow needs.
  • Run a saved function - pick a Function from your Functions page. Good for code several workflows share. A saved function has its own editor, instant test, versions and templates, and can also run on its own schedule or be called over the API.

Under code in a step, Save as function turns it into a saved function; the step then runs that function.

What the code looks like

export default async function (input, ctx) {
  const order = input.event.payload
  const heavy = order.line_items.filter((line) => line.grams > 5000)

  ctx.log("heavy lines", heavy.length)

  return { heavy: heavy.length > 0, skus: heavy.map((line) => line.sku) }
}

Later steps read the result as steps.<id>.output.heavy and steps.<id>.output.skus.

What the code receives

Name Holds
input.event The trigger's event: topic, payload, and changes for change triggers
input.steps The results of all earlier steps, by step id
input.loop Inside a Repeat for each: the current item and its position
input.<your field> The fields of the step's Input (JSON)
secrets.NAME A secret from the Secrets page
ctx.log(...) Writes to the function run's logs
ctx.fetch(url, options) Calls other systems over HTTPS. The only way to the network
ctx.shopify.graphql(query, variables) Calls the Shopify Admin API with the permissions you granted
ctx.kv The shop's key-value store: get, set, delete, increment, list
ctx.storage Larger JSON documents between runs: get, set, delete, list

Input (JSON): settings per step

Input (JSON) is optional. It is a JSON object whose fields the code reads as input.tag, input.total and so on. That way one saved function serves many workflows, each with its own settings.

{ "tag": "vip", "total": {{ event.payload.total_price | json }} }
  • Add the json filter to text values.
  • The names event, steps and loop are taken: they always hold the run's own data.
  • The input is kept with the function run in the run history, next to the logs. So it cannot carry secrets: the code reads those as secrets.NAME itself, and the editor refuses an input that reads a secret.

Store data from code

export default async function (input, ctx) {
  const data = await ctx.shopify.graphql(
    `query ($id: ID!) { order(id: $id) { id name displayFinancialStatus } }`,
    { id: input.event.payload.admin_graphql_api_id },
  )
  return data
}

Your store's access token never enters the sandbox. The call goes through the app with a short-lived token that is valid for this one run and only for the permissions you granted. Changes made this way are noted for Loop protection like those of any other step.

Often a Shopify query step before the code is simpler: the code then finds the answer in input.steps. See Every Shopify mutation and query.

Testing

  • In a preview, code does not run, because nobody can know what it would change. The step reports that it was previewed. Choose Run for real to run it.
  • Test this step runs the step alone, or with the steps it depends on.
  • A saved function has its own test in the function editor, with sample input.

Logs and failures

  • A code step's run is listed in Run history under Function runs, with its input, output and logs. Code written in a step is named Workflow step: plus the step's name.
  • Code that throws, or takes longer than 5 seconds, fails the step with the error message.
  • Code that ran and failed is not repeated automatically, because it may already have changed something. Only a busy or unreachable sandbox is retried. See Automatic retries.
  • Function runs inside a workflow do not count on their own. The workflow run is what counts against your plan.