Auto-tag customers having a rolling minimum total spend, with Mechanic.

Mechanic is a development platform for Shopify. :)

Auto-tag customers having a rolling minimum total spend

Use this task to tag customers who reach a certain spending threshold, by scanning a rolling period of order history. Useful for rewarding customers who keep a consistent spend total.

Runs when a user triggers the task, every day at midnight, when an order is created, when an order is updated, and when an order is deleted. Configuration includes minimum total spent, customer tag to apply, days of order history to consider, and only monitor customers having this tag.

15-day free trial – unlimited tasks

Documentation

Use this task to tag customers who reach a certain spending threshold, by scanning a rolling period of order history. Useful for rewarding customers who keep a consistent spend total.

Run this task manually to scan all of your customers. This may take some time!

This task will also scan all customers on a nightly basis, and will run for a single customer every time a customer's order is paid or cancelled.

Note: By default, Mechanic only scans the last 60 days of order history. To change this, follow this tutorial.

Developer details

Mechanic is designed to benefit everybody: merchants, customers, developers, agencies, Gurus, 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.

Open source
View on GitHub to contribute to this task
Events
when a user triggers the task (mechanic/user/trigger)
every day at midnight (mechanic/scheduler/daily)
when an order is created (shopify/orders/create)
when an order is updated (shopify/orders/updated)
when an order is deleted (shopify/orders/delete)
Options
minimum total spent (number, required), customer tag to apply (required), days of order history to consider (number, required), only monitor customers having this tag
Script
{% comment %}
  express a preference for which option appears first
  {{ options.minimum_total_spent__number_required }}
  {{ options.customer_tag_to_apply__required }}
  {{ options.days_of_order_history_to_consider__number_required }}
{% endcomment %}

{% assign acceptable_order_financial_statuses = "paid partially_paid partially_refunded" | split: " " %}
{% assign acceptable_transaction_kinds = "sale capture refund" | split: " " %}

{% assign days_in_seconds = options.days_of_order_history_to_consider__number_required | times: 24 | times: 60 | times: 60 %}
{% assign min_created_at = "now" | date: "%s" | times: 1 | minus: days_in_seconds %}

{% if options.only_monitor_customers_having_this_tag == options.customer_tag_to_apply__required %}
  {% error "The two customer tag values must be different. Please change either 'Customer tag to apply' or 'Only monitor customers having this tag'." %}
{% endif %}

{% assign customers = shop.customers %}
{% if event.topic == "shopify/orders/create" or event.topic == "shopify/orders/updated" %}
  {% assign customers = array %}
  {% assign customers[0] = order.customer %}
{% endif %}

{% if event.preview %}
  {% capture customers_json %}
    [
      {
        "admin_graphql_api_id": "gid://shopify/Customer/1234567890",
        "email": "customer@example.com",
        "tags": {{ options.only_monitor_customers_having_this_tag | json }},
        "orders": {
          "any": [
            {
              "created_at": {{ min_created_at }},
              "financial_status": "paid",
              "transactions": [
                {
                  "status": "success",
                  "kind": "sale",
                  "amount": {{ options.minimum_total_spent__number_required | plus: 1 | json }}
                }
              ]
            }
          ]
        }
      }
    ]
  {% endcapture %}

  {% assign customers = customers_json | parse_json %}
{% endif %}

{% for customer in customers %}
  {% assign customer_tags = customer.tags | split: ", " %}

  {% if options.only_monitor_customers_having_this_tag != blank %}
    {% unless customer_tags contains options.only_monitor_customers_having_this_tag %}
      {% log "Customer does not have the required tag for monitoring; skipping." %}
      {% continue %}
    {% endunless %}
  {% endif %}

  {% assign customer_total = 0.0 %}
  {% assign customer_orders_count = 0 %}

  {% for customer_order in customer.orders.any %}
    {% assign customer_order_created_at_in_seconds = customer_order.created_at | date: "%s" | times: 1 %}
    {% if customer_order_created_at_in_seconds < min_created_at %}
      {% continue %}
    {% endif %}

    {% unless acceptable_order_financial_statuses contains customer_order.financial_status %}
      {% continue %}
    {% endunless %}

    {% for transaction in customer_order.transactions %}
      {% if transaction.status != "success" %}
        {% continue %}
      {% endif %}

      {% unless acceptable_transaction_kinds contains transaction.kind %}
        {% continue %}
      {% endunless %}

      {% if transaction.kind == "refund" %}
        {% assign customer_total = customer_total | minus: transaction.amount %}
      {% else %}
        {% assign customer_total = customer_total | plus: transaction.amount %}
      {% endif %}
    {% endfor %}

    {% assign customer_orders_count = customer_orders_count | plus: 1 %}
  {% endfor %}

  {% assign add_tag = false %}
  {% assign remove_tag = false %}

  {% capture log_line_prefix %}{{ customer.email | default: customer.id }} spent {{ customer_total }} across {{ customer_orders_count }} orders, {% endcapture %}

  {% if customer_total >= options.minimum_total_spent__number_required %}
    {% if customer_tags contains options.customer_tag_to_apply__required %}
      {% log %}{{ log_line_prefix | append: "qualifying them for the tag. They were already tagged, so there's nothing to do." | json }}{% endlog %}
    {% else %}
      {% log %}{{ log_line_prefix | append: "qualifying them for the tag" | json }}{% endlog %}
      {% assign add_tag = true %}
    {% endif %}
  {% else %}
    {% if customer_tags contains options.customer_tag_to_apply__required %}
      {% log %}{{ log_line_prefix | append: "and did not qualify for the tag" | json }}{% endlog %}
      {% assign remove_tag = true %}
    {% else %}
      {% log %}{{ log_line_prefix | append: "and did not qualify for the tag. They were not previously tagged, so there's nothing to do." | json }}{% endlog %}
    {% endif %}
  {% endif %}

  {% if add_tag or remove_tag %}
    {% action "shopify" %}
      mutation {
      {% if add_tag %}tagsAdd{% elsif remove_tag %}tagsRemove{% endif %}(
          id: {{ customer.admin_graphql_api_id | json }}
          tags: {{ options.customer_tag_to_apply__required | json }}
        ) {
          userErrors {
            field
            message
          }
        } 
      }
    {% endaction %}
  {% endif %}
{% endfor %}
Mechanic tasks are written in Liquid, which makes them easy to write and easy to modify. Learn more about our platform.
Defaults
Days of order history to consider
30