Mechanic turns Liquid from a templating language, into a programming language.

By nature, this document is basically wholly for developers. But – and we mean this – we're all about education. If you're curious, dive in! And message us with that button in the corner if you have questions. :)

For developers

Each task script is expected to render a stream of JSON objects that can be used to generate actions. Put another way, your script should render a series of JSON objects, one right after the other, separated by nothing other than whitespace. (Under the hood, we use Yajl for parsing.)

Learn more about the actions that Mechanic supports.

Your Liquid code always has access to these standard variables:

  • event  – Represents the incoming event. Use event.topic  to get the current event topic, and  to get the event's payload. (Find samples of these payloads in the Shopify docs.) And, super importantly, use event.preview  to determine if Mechanic is running your script for the purpose of showing the merchant what the script can do.
  • options  – Represents any options that the task was configured with. Read on to learn more about options.
  • cache  – Allows you to access values that you've stored in your keyval cache. Learn about using the "cache" action.

There are also additional variables for things like the current shop, and objects that related to the event that your task is processing.

Learn more about Liquid in Mechanic, and the Liquid objects available available to you.

Take note! If you're used to writing Shopify templates in Liquid, remember that Mechanic uses Shopify's Admin API representation for these objects, not the storefront Liquid representation! This usually means that you'll have access to more data than you would in a storefront template.

For an example, compare the storefront customer object with the customer API response.

For more general comparisons, compare Shopify's webhook reference and admin API reference.


Mechanic will pick up on any mention your script makes of a variable lookup that resembles, and it'll make that option key available to the merchant – in the task interface – for easy configuration.

Option keys must only contain numbers, lowercase letters, and underscores.

As an example, this script:

  "action": {
    "type": "echo",
    "options": {
      "color": {{ options.color | json }}

… will generate an interface element that looks like this:

But wait! It gets better! If you throw a double-underscore after the option key and add one of several flags, Mechanic will enforce validations and/or construct the form element differently.

A flagged option key looks like foo__bar_baz , where foo  is the option name, and bar  and baz  are the flags.

Real-world example: Use

{{ options.to__email_required }}
 in your script to render an option field labeled "To", that requires a valid email to be entered.

Available flags:

  • required  – Guarantees that the merchant must fill in this option before the task can be saved.
  • multiline  – Renders a textarea, into which multiple lines of text can be entered.
  • email  – Renders an input element of type email.
  • number  – Renders an input element of type number , with step="1".
  • code  – Renders a textarea that's formatted for code.
  • keyval  – Allows the merchant to add labeled values, which are made available to the script as a key => value data structure, where each value is evaluated with the option's other flags.
  • array  – allows the merchant to add a series of values, where each value is evaluated with the option's other flags. If the merchant adds a fifth element, a "Manage in bulk" option will appear, allowing for a larger set of elements to be pasted into a simple text box.


To inform the merchant of a misconfiguration, or some other condition that should prevent your task from running, render an object with a single key: "error".

Here's an example:

{% if options.mutually_exclusive_1 and options.mutually_exclusive_2 %}
  {"error": "Please fill in one of the two options, but not both!"}
{% endif %}

If this error is encountered during a task preview, the error will be presented to the merchant.

If this error is encountered during an actual task run, the error will be reflected in the task's status, and no actions will run (even if actions were rendered alongside the error).

If multiple errors are generated, only the first error will be reflected in the task's status.



This script doesn't change its results based on the event – it sends the same email every time.

  "action": {
    "type": "email",
    "options": {
      "to": "",
      "subject": "Hello world",
      "body": "It's a mighty fine day!"




This script sends an email offering a heads-up that a customer has been created, or updated, or deleted.

{% capture email_body %}
Customer attributes:

{{ customer | json }}
{% endcapture %}

  "action": {
    "type": "email",
    "options": {
      "to": "",
      "subject": "Customer {{ }} was {{ event.topic }}d",
      "body": {{ email_body | json }}




This script loops through every line item in the order, and – for every line item having a SKU – emails the appropriate team about that line item. This script could generate zero, one, or a hundred emails!

{% assign teams_to_email = "" %}

{% for line_item in order.line_items %}
  {% if line_item.sku == blank %}{% continue %}{% endif %}

  {% assign team = line_item.sku | split: "-" | last %}

  {% capture subject %}New order for a {{ team }} product{% endcapture %}

    "action": {
      "type": "email",
      "options": {
        "to": "{{ team }}",
        "subject": {{ subject | json }},
        "body": {{ line_item | json | json }}
{% endfor %}

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.