Tag products by their price ranges with Mechanic.

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

Tag products by their price ranges

by Isaac Bowen (team@usemechanic.com)

Some themes (like Mogo!) support browsing products by price range. Under the hood, this functionality is powered by tags that look like "rprice-1-100". This Mechanic task watches for new and updated products, making sure that the product range tags stay in sync with prices available for each product. And, if you run the task manually, it'll update the tags for all products in your shop.

Runs when a user triggers the task, when a product is created, and when a product is updated. Configuration includes range maximum, range minimum, and range increment.

15-day free trial – unlimited tasks

Documentation

This task adds tags that specify the price ranges that describe the product. For example, when this task is configured with a range minimum of 0 and a range maximum of 100, a product with a price of 50.00 would receive the tag rprice-0-100 (and others!). Configure this tag with a maximum and minimum, and the number of steps between that you'd like Mechanic to observe.

Out of the box, this task will run on product create and update. You can also use the "Run Task" button to request a run across all products in your shop.

Developer details

Events
when a user triggers the task (mechanic/user/trigger)
when a product is created (shopify/products/create)
when a product is updated (shopify/products/update)
Options
range maximum (required, number), range minimum (required, number), range increment (required, number)
Script
{% if event.preview %}
  {
    "action": {
      "type": "shopify",
      "options": [
        "update",
        ["product", 1234567890],
        {
          "tags": "2XL, Black, Blue, hoodie, L, M, S, XL, rprice-0-50, rprice-0-75, rprice-0-100, rprice-0-125, rprice-0-150, rprice-0-175, rprice-0-200, rprice-25-50, rprice-25-75, rprice-25-100, rprice-25-125, rprice-25-150, rprice-25-175, rprice-25-200"
        }
      ]
    }
  }
{% else %}
  {% if event.topic == "mechanic/user/trigger" %}
    {% comment %}
      When running manually, process all products in the shop
    {% endcomment %}
    {% assign loop_set = shop.products %}
  {% elsif event.topic == "shopify/products/create" or event.topic == "shopify/products/update" %}
    {% comment %}
      Otherwise, just run the current product, populating a throwaway value in the loop set
    {% endcomment %}
    {% assign loop_set = "current_product" %}
    {% assign current_product = product %}
  {% endif %}

  {% comment %}
    The variable populated by a forloop can't be reassigned, so use something other than "product" here
  {% endcomment %}
  {% for loop_item in loop_set %}
    {% if event.topic == "shopify/products/create" or event.topic == "shopify/products/update" %}
      {% assign product = current_product %}
    {% else %}
      {% assign product = loop_item %}
    {% endif %}

    {% assign product_tags = product.tags | split: ", " %}
    {% assign product_tags_without_rprice = "" %}
    {% for product_tag in product_tags %}
      {% assign product_tag_parts = product_tag | split: "-" %}
      {% unless product_tag_parts.first == "rprice" %}
        {% capture product_tags_without_rprice %}{% if product_tags_without_rprice != blank %}{{ product_tags_without_rprice }}, {% endif %}{{ product_tag }}{% endcapture %}
      {% endunless %}
    {% endfor %}

    {% assign rprice_tags = "" %}

    {% assign range_max = options.range_maximum__required_number | round %}
    {% assign range_min = options.range_minimum__required_number | round %}
    {% assign range_increment = options.range_increment__required_number | round %}
    {% assign range_steps = range_max | minus: range_min | divided_by: range_increment %}

    {% for i in (0..range_steps) %}
      {% for j in (i..range_steps) %}
        {% if j <= i %}
          {% continue %}
        {% endif %}

        {% assign step_min = i | times: range_increment | plus: range_min %}
        {% assign step_max = j | times: range_increment | plus: range_min %}

        {% for variant in product.variants %}
          {% assign variant_price = variant.price | divided_by: 1 %}
          {% if variant_price >= step_min and variant_price <= step_max %}
            {% capture rprice_tags %}{% if rprice_tags != blank %}{{ rprice_tags }}, {% endif %}rprice-{{ step_min }}-{{step_max }}{% endcapture %}
          {% endif %}
        {% endfor %}
      {% endfor %}
    {% endfor %}

    {% comment %}remove duplicates{% endcomment %}
    {% assign rprice_tags = rprice_tags | split: ", " | uniq | join: ", " %}

    {% capture product_tags_to_save %}{% if product_tags_without_rprice != blank %}{{ product_tags_without_rprice }}, {% endif %}{{ rprice_tags }}{% endcapture %}

    {% assign product_tags_to_save = product_tags_to_save | split: ", " | sort | join: ", " %}

    {"log": {{ product_tags_to_save | json }}}
    {"log": {{ product.tags | json }}}

    {% if product_tags_to_save != product.tags %}
      {
        "action": {
          "type": "shopify",
          "options": [
            "update",
            ["product", {{ product.id | json }}],
            {
              "tags": {{ product_tags_to_save | json }}
            }
          ]
        }
      }
    {% endif %}

    {% if event.topic == "shopify/products/create" or event.topic == "shopify/products/update" %}
      {% break %}
    {% endif %}
  {% endfor %}
{% endif %}
Yep, that’s just Liquid! If this is interesting to you, check out our documentation! Mechanic is hugely developer-friendly. :)
Defaults
Range maximum
200
Range minimum
0
Range increment
25