The "shopify" action

Anything that Shopify allows developers to do, Mechanic lets you automate. This means that you can create, update, or delete nearly anything in your Shopify account.

The "shopify" action has three styles of usage:

  • Resourceful REST, which uses Shopify's REST admin API in a style reminiscent of ActiveResource
  • Explicit REST, which uses Shopify's REST admin API with explicitly defined values for HTTP method, url, and body
  • GraphQL, which uses Shopify's GraphQL admin API

Use resourceful REST if it's easy to do so – its job is to keep simple things simple. Use explicit REST if you need to get really specific about how your API request works. Use GraphQL when you need a feature not available in the REST API, or if it's otherwise more convenient/natural to do so.

Tip: if you're working with tags, always use GraphQL, to avoid accidentally overwriting tags added or removed by a simultaneously-running task (see How do I add or remove tags for Shopify resources?).

Resourceful REST

Accepts an array of options, containing these elements in order:

  1. Operation
    Must be one of "create" , "update" , or "delete" .
  2. Resource specification
    When creating, use a single string (e.g. "customer" ).
    When updating or deleting, use an array (e.g. ["customer", 123] ).
  3. An object of attributes
    Only applies to creating and updating.

A task which tags a customer upon ordering might look like this:

{% action "shopify" %}
  [
    "update",
    [
      "customer",
      {{ order.customer.id | json }}
    ],
    {
      "tags": {{ order.customer.tags | add_tag: "ordered" | json }}
    }
  ]
{% endaction %}

Explicit REST

Accepts an array of options, containing these elements in order:

  1. Operation
    Must be one of "post" , "put" , or "delete" 
  2. Request path
    Literally, the path you want to request from Shopify – the entire path. For example, /admin/orders.json .
  3. An object of attributes
    Same as the resourceful options style except that it must be wrapped in a parent object, with a single key named after the resource type. (This wrapping is required by Shopify regardless, but it's handled automatically during resourceful usage. Here, it's something you need to handle manually.)

A task which tags a customer upon ordering might look like this:

{% action "shopify" %}
  [
    "put",
    "/admin/customers/{{ order.customer.id }}.json",
    {
      "customer": {
        "tags": {{ order.customer.tags | add_tag: "ordered" | json }}
      }
    }
  ]
{% endaction %}

GraphQL

Accepts a valid GraphQL query.

A task which tags a customer upon ordering might look like this:

{% assign customer = shop.customers[order.customer.id] %}

{% action "shopify" %}
  mutation {
    tagsAdd(
      id: {{ customer.admin_graphql_api_id | json }}
      tags: "ordered"
    ) {
      userErrors {
        field
        message
      }
    }
  }
{% endaction %}

The "shopify" action may also be used with tag syntax:

{% capture query %}...{% endcapture %}

{% action "shopify" query %}

Using GraphQL variables

Because GraphQL queries (excluding whitespace) are limited to 50,000 characters, you may encounter scenarios in which you need to fall back to GraphQL variables to provide larger inputs.

To provide these variables, supply the "shopify" action with a JSON object containing a "query" key and a "variables" key.

{% capture query %}
  mutation DeleteProduct($productId: ID!) {
    productDelete(
      input: {
        id: $productId
      }
    ) {
      userErrors {
        field
        message
      }
    }
  }
{% endcapture %}

{% action "shopify" %}
  {
    "query": {{ query | json }},
    "variables": {
      "productId": "gid://shopify/Product/1234567890"
    }
  }
{% endaction %}

Here's a more detailed example, showing how the query and variables may be built up separately, and provided to the action using concise tag syntax:

{% capture query %}
  mutation SetCustomerMetafield(
    $customerId: ID!
    $metafieldNamespace: String!
    $metafieldKey: String!
    $metafieldId: ID
    $metafieldValue: String!
  ) {
    customerUpdate(
      input: {
        id: $customerId
        metafields: [
          {
            id: $metafieldId
            namespace: $metafieldNamespace
            key: $metafieldKey
            valueType: STRING
            value: $metafieldValue
          }
        ]
      }
    ) {
      userErrors {
        field
        message
      }
      customer {
        metafield(
          namespace: $metafieldNamespace
          key: $metafieldKey
        ){
          id
        }
      }
    }
  }
{% endcapture %}

{% assign customer_id = 806736592949 %}
{% assign customer = shop.customers[customer_id] %}
{% assign existing_metafield = customer.metafields.test | where: "key", "test" | first %}

{% assign variables = hash %}
{% assign variables["customerId"] = customer.admin_graphql_api_id %}
{% assign variables["metafieldNamespace"] = "test" %}
{% assign variables["metafieldKey"] = "test" %}
{% assign variables["metafieldId"] = existing_metafield.admin_graphql_api_id %}
{% assign variables["metafieldValue"] = "now" | date: "%s" %}

{% action "shopify" query: query, variables: variables %
Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.