Liquid script step

The Liquid script step runs a whole script written in Liquid, the template language you may know from Shopify themes. One script can read your store, decide, and change it. It suits people who think in Liquid rather than in JavaScript, and jobs that would otherwise take a query, a loop, a condition and an action.

For Liquid inside ordinary fields, see Liquid in every field.

Add it

  1. Press + and pick Liquid script.
  2. Write the Liquid script. Insert a variable at the end adds a variable from the picker. A script can be 50 KB at most.
  3. Optional: add options, values the script reads as options.NAME.

Read the store: the shopify filter

Write a GraphQL query, pipe it through shopify, and you get the answer at once as data and errors:

{% capture query %}
  query {
    product(id: {{ event.payload.admin_graphql_api_id | json }}) {
      id
      tags
      variants(first: 50) { nodes { id price compareAtPrice } }
    }
  }
{% endcapture %}

{% assign result = query | shopify %}
{% assign product = result.data.product %}

The filter only takes queries. A mutation is refused there.

Change the store: the action tag

A mutation goes into an action tag:

{% unless product.tags contains "sale" %}
  {% action "shopify" %}
    mutation {
      tagsAdd(id: {{ product.id | json }}, tags: ["sale"]) {
        userErrors { field message }
      }
    }
  {% endaction %}
{% endunless %}

Actions are collected while the script runs and performed afterwards, in order. So a script cannot read the answer of its own action. The first action that fails stops the rest, and userErrors fail the step.

Only {% action "shopify" %} with a GraphQL mutation is supported. For any other call use an HTTP request step, for email a Send email step. The editor lists other action types as a problem.

Other tags and filters

Syntax What it does
{% log %} Writes a line into the step's logs, up to 100 lines
{% error "message" %} Fails the step with your message
parse_json Turns JSON text into an object or a list
json Turns a value into JSON text
keys, values The keys or the values of an object
graphql_arguments Writes an object as GraphQL arguments
array, hash Empty list and empty object to start from: {% assign found = array %}
event.preview true in a preview, so a script can behave differently in a test

Standard Liquid works as usual: assign, capture, if, unless, case, for with break, and the standard filters. Including other templates (render, include) is not available, and an unknown filter is an error rather than silently ignored.

Options

Options are named values next to the script, so you can change a tag or a threshold without touching the code. The script reads them as options.NAME. An option's value is a field like any other and takes variables.

A name that ends in __number, __boolean or __array (one entry per line) is converted to that type.

What the step returns

Variable Holds
steps.<id>.output.output What the script printed. When that is JSON, it is parsed, so later steps can read its fields or repeat over a list
steps.<id>.output.logs The log lines
steps.<id>.output.actions One entry per action: type, ok and data, the answer of the mutation

A script that only prepares data simply prints JSON at the end:

{{ found | json }}

Limits

  • 20 seconds per step.
  • 50 Shopify calls per step, queries and actions together.
  • 256 KB of output.
  • The script runs with the permissions you granted, and with the workflow's Shopify Admin API version. See Every Shopify mutation and query.

A script reads one page per query. Page through a long list with a for loop over a range and break, within the 50 calls, or let a scheduled workflow work in portions.

Liquid script or code?

Liquid script Run function
Language Liquid JavaScript
Calls other systems No Yes, with ctx.fetch
Runs in a preview Yes: reads run, changes are listed No
Time limit 20 seconds 5 seconds

See Run code and functions.

The template Tag products that are on sale is a complete example.