Auto-tag products by age, with Mechanic.

Mechanic is a development platform for Shopify. :)

Auto-tag products by age

This task scans every product in your store, and adds or removes the tags you configure, according to how many days have passed since the product was created. (Or published, if you prefer!)

Runs when a user triggers the task. Configuration includes product tags and age threshold in days, match product tags by minimum age, match product tags by maximum age, use product publish times instead of creation times, run daily, and run hourly.

15-day free trial – unlimited tasks

Documentation

This task scans every product in your store, and adds or removes the tags you configure, according to how many days have passed since the product was created. (Or published, if you prefer!)

Enable "Use product publish times instead of creation times" to have this task look at when the product was published to your online storefront, instead of when the product was created. When this option is enabled, unpublished products will have any of this task's tags removed.

Configure "Product tags and age threshold in days" with product tags on the left, and the product age (in days) to qualify on the right. Combine this setting with a choice between "Match product tags by minimum age" and "Match product tags by maximum age", to achieve tagging based on either minimum or maximum ages.

For example, a product tag of "new-5" with an age threshold of "5", combined with "Match product tags by maximum age" will be added to all products that were created/published within the last 5 days. Once a product ages beyond that threshold, running this task will remove that tag.

Run this task manually to scan your store's products on demand, or configure the task to run daily or hourly.

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)
Options
product tags and age threshold in days (keyval, number, required), match product tags by minimum age (boolean), match product tags by maximum age (boolean), use product publish times instead of creation times (boolean), run daily (boolean), run hourly (boolean)
Script
{% comment %}
  Preferred option order:

  {{ options.product_tags_and_age_threshold_in_days__keyval_number_required }}
  {{ options.match_product_tags_by_minimum_age__boolean }}
  {{ options.match_product_tags_by_maximum_age__boolean }}
  {{ options.use_product_publish_times_instead_of_creation_times__boolean }}
{% endcomment %}

{% if options.match_product_tags_by_minimum_age__boolean and options.match_product_tags_by_maximum_age__boolean %}
  {% error "Please choose either 'Match product tags by minimum age' or 'Match product tags by maximum age', but not both." %}
{% elsif options.match_product_tags_by_minimum_age__boolean == false and options.match_product_tags_by_maximum_age__boolean == false %}
  {% error "Please choose either 'Match product tags by minimum age' or 'Match product tags by maximum age', but not both." %}
{% endif %}

{% if event.preview %}
  {% assign now_s = "now" | date: "%s" | times: 1 %}
  {% assign preview_interval_s = options.product_tags_and_age_threshold_in_days__keyval_number_required.first.last | times: 24 | times: 60 | times: 60 %}

  {% if options.match_product_tags_by_minimum_age__boolean %}
    {% assign preview_time = now_s | minus: preview_interval_s | minus: 86400 | date: "%Y-%m-%d" %}
  {% elsif options.match_product_tags_by_maximum_age__boolean %}
    {% assign preview_time = now_s | minus: preview_interval_s | plus: 86400 | date: "%Y-%m-%d" %}
  {% endif %}

  {% assign products = array %}
  {% assign products[0] = hash %}
  {% assign products[0]["admin_graphql_api_id"] = "gid://shopify/Product/1234567890" %}
  {% assign products[0]["id"] = 1234567890 %}
  {% assign products[0]["created_at"] = preview_time %}
  {% assign products[0]["published_at"] = preview_time %}
{% else %}
  {% assign products = shop.products %}
{% endif %}

{% assign now_s = "now" | date: "%s" | times: 1 %}

{% for product in products %}
  {% assign product_tags = product.tags | split: ", " %}

  {% assign product_timestamp_s = product.created_at | date: "%s" | times: 1 %}
  {% if options.use_product_publish_times_instead_of_creation_times__boolean %}
    {% assign product_timestamp_s = product.published_at | date: "%s" | times: 1 %}
  {% endif %}

  {% assign product_age_d = now_s | minus: product_timestamp_s | divided_by: 86400 %}

  {% assign tags_to_add = array %}
  {% assign tags_to_remove = array %}

  {% for keyval in options.product_tags_and_age_threshold_in_days__keyval_number_required %}
    {% assign tag = keyval[0] %}
    {% assign tag_age_threshold_d = keyval[1] %}

    {% assign tag_age_threshold_met = false %}

    {% comment %}
      0 happens when we didn't have a valid datetime string to begin with. Happens
      when there's no published_at value.
    {% endcomment %}
    {% if product_timestamp_s != 0 %}
      {% if options.match_product_tags_by_minimum_age__boolean and product_age_d > tag_age_threshold_d %}
        {% assign tag_age_threshold_met = true %}
      {% elsif options.match_product_tags_by_maximum_age__boolean and product_age_d < tag_age_threshold_d%}
        {% assign tag_age_threshold_met = true %}
      {% endif %}
    {% endif %}

    {% comment %}
      {% log product_id: product.id, product_age_d: product_age_d, tag: tag, tag_age_threshold_d: tag_age_threshold_d, tag_age_threshold_met: tag_age_threshold_met %}
    {% endcomment %}

    {% if tag_age_threshold_met %}
      {% unless product_tags contains tag %}
        {% assign tags_to_add[tags_to_add.size] = tag %}
      {% endunless %}
    {% else %}
      {% if product_tags contains tag %}
        {% assign tags_to_remove[tags_to_remove.size] = tag %}
      {% endif %}
    {% endif %}
  {% endfor %}

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

        {% if tags_to_remove != empty %}
          tagsRemove(
            id: {{ product.admin_graphql_api_id | json }}
            tags: {{ tags_to_remove | json }}
          ) {
            userErrors {
              field
              message
            }
          }
        {% endif %}
      }
    {% 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
Product tags and age threshold in days
{"new-this-week"=>"7", "new-this-month"=>"30"}
Match product tags by maximum age
true
Use product publish times instead of creation times
true