Auto-tag orders by shipment status, with Mechanic.

Mechanic is a development and ecommerce automation platform for Shopify. :)

Auto-tag orders by shipment status

Easily segment your orders by shipment status. Tagging your orders as "Delivered", or "Out for delivery", or "Attempted delivery", or any other status, allows you to stay on top of your order flow. And, adding these tags makes it easier to wire up additional automation, keeping the connection live between your customers and their orders.

Runs Occurs whenever a fulfillment is created, Occurs whenever a fulfillment is updated, Occurs when a user manually triggers the task, and Occurs when a bulk operation is completed. Configuration includes shipping statuses and tags and limit to orders matching this query for manual runs.

15-day free trial – unlimited tasks

Documentation

Easily segment your orders by shipment status. Tagging your orders as "Delivered", or "Out for delivery", or "Attempted delivery", or any other status, allows you to stay on top of your order flow. And, adding these tags makes it easier to wire up additional automation, keeping the connection live between your customers and their orders.

This task monitors fulfillments for your orders. Whenever a fulfillment is updated, this task removes any shipment-related tags that might already be on the order, then adds whatever tag is relevant for the current shipment status. If there are multiple fulfillments for the order, and they have different statuses, this task will add more than one tag. Use the "Run task" button to scan all orders. To process orders older than 60 days, enable "Read all orders".

This task comes pre-configured with friendly tags, but feel free to update the tag names on the right-hand side. Do not modify the labels on the left! These correspond directly to shipment statuses as they're recorded by Shopify.

For a reference on Shopify's fulfillment statuses, see the FulfillmentDisplayStatus documentation. (More details may be available in the REST documentation for Fulfillment.shipment_status.)

The "Limit to orders matching this query for manual runs" option uses the same query syntax as the "Orders" section of the Shopify admin area. For example, to only include paid orders, use this query:

financial_status:paid

Developer details

Mechanic is designed to benefit everybody: merchants, customers, developers, agencies, Shopifolks, everybody.

That’s why we make it easy to configure automation without code, why we make it easy to tweak the underlying code once tasks are installed, and why we publish it all here for everyone to learn from.

(By the way, have you seen our documentation? Have you joined the Slack community?)

Open source
View on GitHub to contribute to this task
Subscriptions
shopify/fulfillments/create
shopify/fulfillments/update
mechanic/user/trigger
mechanic/shopify/bulk_operation
Tasks use subscriptions to sign up for specific kinds of events. Learn more
Options
shipping statuses and tags (keyval, required), limit to orders matching this query for manual runs
Code
{% comment %}
Options ordering:
  {{ options.shipping_statuses_and_tags__keyval_required }}
  {{ options.limit_to_orders_matching_this_query_for_manual_runs }}
{% endcomment %}

{% if event.topic contains "shopify/fulfillments/" %}
  {% capture query %}
    query {
      order(id: {{ fulfillment.order.admin_graphql_api_id | json }}) {
        id
        tags
        fulfillments {
          displayStatus
        }
      }
    }
  {% endcapture %}

  {% assign result = query | shopify %}

  {% if event.preview %}
    {% capture result_json %}
      {
        "data": {
          "order": {
            "id": "gid://shopify/Order/1234567890",
            "tags": [],
            "fulfillments": [
              {
                "displayStatus": "IN_TRANSIT"
              },
              {
                "displayStatus": "CANCELED"
              },
              {
                "displayStatus": "OUT_FOR_DELIVERY"
              }
            ]
          }
        }
      }
    {% endcapture %}

    {% assign result = result_json | parse_json %}
  {% endif %}

  {% assign orders = array %}
  {% assign orders[0] = result.data.order %}

{% elsif event.topic == "mechanic/user/trigger" %}
  {% assign orders_query = nil %}

  {% if options.limit_to_orders_matching_this_query_for_manual_runs != blank %}
    {% assign orders_query = options.limit_to_orders_matching_this_query_for_manual_runs %}
  {% endif %}

  {% capture bulk_operation_query %}
    query {
      orders(
        query: {{ orders_query | json }}
      ) {
        edges {
          node {
            id
            tags
            fulfillments {
              displayStatus
            }
          }
        }
      }
    }
  {% endcapture %}

  {% action "shopify" %}
    mutation {
      bulkOperationRunQuery(
        query: {{ bulk_operation_query | json }}
      ) {
        bulkOperation {
          id
          status
        }
        userErrors {
          field
          message
        }
      }
    }
  {% endaction %}

{% elsif event.topic == "mechanic/shopify/bulk_operation" %}
  {% if event.preview %}
    {% capture objects_jsonl %}
      {"id":"gid:\/\/shopify\/Order\/1234567890","tags":[],"fulfillments":[{"displayStatus":"IN_TRANSIT"},{"displayStatus":"CANCELED"},{"displayStatus":"OUT_FOR_DELIVERY"}]}
      {"id":"gid:\/\/shopify\/Order\/2345678901","tags":[],"fulfillments":[{"displayStatus":"DELIVERED"}]}
    {% endcapture %}

    {% assign bulkOperation = hash %}
    {% assign bulkOperation["objects"] = objects_jsonl | parse_jsonl %}
  {% endif %}

  {% assign orders = bulkOperation.objects %}
{% endif %}

{% for order in orders %}
  {% assign tags_to_add = array %}
  {% assign tags_to_remove = array %}

  {% assign display_statuses = order.fulfillments | map: "displayStatus" %}

  {% for keyval in options.shipping_statuses_and_tags__keyval_required %}
    {% assign shipping_status = keyval.first %}
    {% assign tag = keyval.last %}

    {% if display_statuses contains shipping_status %}
      {% unless order.tags contains tag %}
        {% assign tags_to_add[tags_to_add.size] = tag %}
      {% endunless %}
    {% elsif order.tags contains tag %}
      {% assign tags_to_remove[tags_to_remove.size] = tag %}
    {% endif %}
  {% endfor %}

  {% if tags_to_add != empty or tags_to_remove != empty %}
    {% action "shopify" %}
      mutation {
        {% if tags_to_add != empty %}
          tagsAdd(
            id: {{ order.id | json }}
            tags: {{ tags_to_add | json }}
          ) {
            userErrors {
              field
              message
            }
          }
        {% endif %}

        {% if tags_to_remove != empty %}
          tagsRemove(
            id: {{ order.id | json }}
            tags: {{ tags_to_remove | json }}
          ) {
            userErrors {
              field
              message
            }
          }
        {% endif %}
      }
    {% endaction %}
  {% endif %}
{% endfor %}
Task code is written in Mechanic Liquid, an extension of open-source Liquid enhanced for automation. Learn more
Defaults
Shipping statuses and tags
{"ATTEMPTED_DELIVERY"=>"Delivery attempted", "CANCELED"=>"Fulfillment Canceled", "CONFIRMED"=>"Delivery confirmed", "DELIVERED"=>"Delivery complete", "FAILURE"=>"Delivery failed", "FULFILLED"=>"Fulfilled", "IN_TRANSIT"=>"Delivery in transit", "LABEL_PRINTED"=>"Shipping label printed", "LABEL_PURCHASED"=>"Shipping label purchased", "LABEL_VOIDED"=>"Shipping label voided", "MARKED_AS_FULFILLED"=>"Marked as fulfilled", "NOT_DELIVERED"=>"Not delivered", "OUT_FOR_DELIVERY"=>"Out for delivery", "PICKED_UP"=>"Picked up", "READY_FOR_PICKUP"=>"Delivery ready for pickup", "SUBMITTED"=>"Submitted"}