Auto-tag customers by purchased SKUs with Mechanic.

Mechanic is the one-tool-does-it-all automation app for Shopify. :)

Auto-tag customers by purchased SKUs

by Isaac Bowen (team@usemechanic.com)

Use this task to keep customers tagged with the SKUs of the products they've purchased, optionally ignoring product purchases that have been refunded. Add a tag prefix to make SKU tags easy to distinguish from your other customer tags.

Runs when an order is paid and when a refund is created. Configuration includes ignore refunded purchases and tag prefix.

15-day free trial – unlimited tasks

Documentation

Use this task to keep customers tagged with the SKUs of the products they've purchased, optionally ignoring product purchases that have been refunded. Add a tag prefix to make SKU tags easy to distinguish from your other customer tags.

This task will run whenever an order is paid, and whenever a refund is created.

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.

Events
when an order is paid (shopify/orders/paid)
when a refund is created (shopify/refunds/create)
Options
ignore refunded purchases (boolean), tag prefix
Script
{% if event.preview %}
  {% capture query %}
    query {
      orders(
        first: 5
      ) {
        pageInfo {
          hasNextPage
        }
        edges {
          cursor
          node {
            lineItems(first: 50) {
              edges {
                node {
                  sku
                  quantity
                }
              }
            }
            refunds {
              refundLineItems(first: 50) {
                edges {
                  node {
                    quantity
                    lineItem {
                      sku
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  {% endcapture %}

  {% assign result = query | shopify %}

  {% action "shopify" %}
    mutation {
      tagsAdd(
        id: "gid://shopify/Customer/1234567890"
        tags: "ABC123"
      ) {
        userErrors {
          field
          message
        }
      }

      tagsRemove(
        id: "gid://shopify/Customer/1234567890"
        tags: "DEF456"
      ) {
        userErrors {
          field
          message
        }
      }
    }
  {% endaction %}
{% else %}
  {% assign customers = array %}

  {% if event.topic contains "shopify/refunds/" %}
    {% assign customers[customers.size] = refund.order.customer %}
  {% elsif event.topic contains "shopify/orders/" %}
    {% assign customers[customers.size] = order.customer %}
  {% elsif event.topic == "mechanic/user/trigger" %}
    {% assign customers = shop.customers.search["orders_count:>0"] %}
  {% endif %}

  {% for customer in customers %}
    {% assign cursor = nil %}
    {% assign sku_quantities = hash %}

    {% for n in (0..250) %}
      {% capture query %}
        query {
          orders(
            first: 5
            after: {{ cursor | json }}
            query: {{ "customer_id:" | append: customer.id | json }}
          ) {
            pageInfo {
              hasNextPage
            }
            edges {
              cursor
              node {
                lineItems(first: 50) {
                  edges {
                    node {
                      sku
                      quantity
                    }
                  }
                }
                refunds {
                  refundLineItems(first: 50) {
                    edges {
                      node {
                        quantity
                        lineItem {
                          sku
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      {% endcapture %}

      {% assign result = query | shopify %}

      {% for order_edge in result.data.orders.edges %}
        {% for lineItem_edge in order_edge.node.lineItems.edges %}
          {% assign sku = lineItem_edge.node.sku %}

          {% if sku == blank %}
            {% continue %}
          {% endif %}

          {% assign sku_quantities[sku] = sku_quantities[sku] | default: 0 | plus: lineItem_edge.node.quantity %}
        {% endfor %}

        {% if options.ignore_refunded_purchases__boolean %}
          {% for refund in order_edge.node.refunds %}
            {% for refundLineItem_edge in refund.refundLineItems.edges %}
              {% assign sku = refundLineItem_edge.node.lineItem.sku %}

              {% if sku == blank %}
                {% continue %}
              {% endif %}

              {% assign sku_quantities[sku] = sku_quantities[sku] | default: 0 | minus: refundLineItem_edge.node.quantity %}
            {% endfor %}
          {% endfor %}
        {% endif %}
      {% endfor %}

      {% if result.data.orders.pageInfo.hasNextPage %}
        {% assign cursor = result.data.orders.edges.last.cursor %}
      {% else %}
        {% break %}
      {% endif %}
    {% endfor %}

    {
      "log": {
        "customer_id": {{ customer.id | json }},
        "sku_quantities": {{ sku_quantities | json }}
      }
    }

    {% assign tags_to_remove = array %}
    {% assign tags_to_add = array %}
    {% assign customer_tags = customer.tags | split: ", " %}

    {% for sku_and_quantity in sku_quantities %}
      {% assign sku = sku_and_quantity[0] %}
      {% assign sku_tag = options.tag_prefix | append: sku %}
      {% assign quantity = sku_and_quantity[1] %}

      {% if quantity > 0 %}
        {% unless customer_tags contains sku_tag %}
          {% assign tags_to_add[tags_to_add.size] = sku_tag %}
        {% endunless %}
      {% else %}
        {% if customer_tags contains sku_tag %}
          {% assign tags_to_remove[tags_to_remove.size] = sku_tag %}
        {% endif %}
      {% endif %}
    {% endfor %}

    {% assign tags_to_save = customer.tags | remove_tags: tags_to_remove | add_tags: tags_to_add %}

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

          {% if tags_to_remove != empty %}
            tagsRemove(
              id: {{ customer.admin_graphql_api_id | json }}
              tags: {{ tags_to_remove | json }}
            ) {
              userErrors {
                field
                message
              }
            }
          {% endif %}
        }
      {% endaction %}
    {% endif %}
  {% endfor %}
{% endif %}
Mechanic tasks are written in Liquid, which makes them easy to write and easy to modify. Learn more about our platform.
Defaults
Ignore refunded purchases
true