Hide out-of-stock products, with Mechanic.

Mechanic is an automation development platform for Shopify. :)

Hide out-of-stock products

by Isaac Bowen (team@usemechanic.com)

Whenever inventory for a product is updated, this task scans all variants and all fulfillment locations, adds up all inventory related to that product, and makes sure the product is hidden if the total inventory meets your "out of stock" threshold. Optionally, it'll send you an email when it does so.

Runs when a user triggers the task and when an inventory level is updated. Configuration includes email notification recipient, out of stock inventory quantity, and only monitor products with these tags.

15-day free trial – unlimited tasks

Documentation

Whenever inventory for a product is updated, this task scans all variants and all fulfillment locations, adds up all inventory related to that product, and makes sure the product is hidden if the total inventory meets your "out of stock" threshold.

To scan your entire catalog for out of stock products, use the "Run task" button. Otherwise, this task will run whenever an inventory level is updated.

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 a user triggers the task (mechanic/user/trigger)
when an inventory level is updated (shopify/inventory_levels/update)
Options
email notification recipient (email), out of stock inventory quantity (number, required), only monitor products with these tags (array)
Script
{% if event.preview %}
  {% action "shopify" %}
    [
      "update",
      ["product", 12345],
      {
        "published": false
      }
    ]
  {% endaction %}

  {% if options.email_notification_recipient__email != blank %}
    {% capture email_subject %}
      Out of stock: Short Sleeve T-shirt
    {% endcapture %}

    {% capture email_body %}
      Hi there,

      Your product is out of stock!

      <a href="https://{{ shop.domain }}/admin/products/12345">Manage this product</a>

      Thanks,
      - Mechanic, for {{ shop.name }}
    {% endcapture %}

    {% action "email" %}
      {
        "to": {{ options.email_notification_recipient__email | json }},
        "subject": {{ email_subject | unindent | strip | json }},
        "body": {{ email_body | unindent | strip | newline_to_br | json }}
      }
    {% endaction %}
  {% endif %}
{% elsif event.topic == "mechanic/user/trigger" %}
  {% assign unpublished_product_links = array %}
  {% assign cursor = nil %}

  {% for n in (0..100) %}
    {% capture query %}
      query {
        products(
          first: 250
          query: "published_status:published"
          after: null
        ) {
          pageInfo {
            hasNextPage
          }
          edges {
            cursor
            node {
              tags
              publishedAt
              totalInventory
              legacyResourceId
              title
            }
          }
        }
      }
    {% endcapture %}

    {% assign result = query | shopify %}

    {% for edge in result.data.products.edges %}
      {% assign product_data = edge.node %}

      {% assign product_qualifies = true %}

      {% if product_data.publishedAt == blank %}
        {% assign product_qualifies = false %}
      {% elsif product_data.totalInventory > options.out_of_stock_inventory_quantity__number_required %}
        {% assign product_qualifies = false %}
      {% elsif options.only_monitor_products_with_these_tags__array != blank %}
        {% assign product_tags_qualify = false %}

        {% for tag in options.only_monitor_products_with_these_tags__array %}
          {% if product_data.tags contains tag %}
            {% assign product_tags_qualify = true %}
            {% break %}
          {% endif %}
        {% endfor %}

        {% if product_tags_qualify == false %}
          {% assign product_qualifies = false %}
        {% endif %}
      {% endif %}

      {% if product_qualifies %}
        {% action "shopify" %}
          [
            "update",
            ["product", {{ product_data.legacyResourceId | json }}],
            {
              "published": false
            }
          ]
        {% endaction %}

        {% capture link %}<li><a href="https://{{ shop.domain }}/admin/products/{{ product_data.legacyResourceId }}">{{ product_data.title }}</a> ({{ product_data.totalInventory }})</li>{% endcapture %}
        {% assign unpublished_product_links[unpublished_product_links.size] = link %}
      {% endif %}
    {% endfor %}

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

  {% if unpublished_product_links != empty and options.email_notification_recipient__email != blank %}
    {% capture email_subject %}
      Found {{ unpublished_product_links.size }} {{ unpublished_product_links.size | pluralize: "product", "products" }} out of stock
    {% endcapture %}

    {% capture email_body %}
      Hi there,
      <br><br>
      These products were found to be under your out of stock minimum quantity ({{ options.out_of_stock_inventory_quantity__number_required }}), when adding up the inventory for each product. Each product has been unpublished, and is no longer available in your online storefront.
      <br>
      <ul>{{ unpublished_product_links | join: "" }}</ul>
      <br>
      Thanks,
      <br>
      - Mechanic, for {{ shop.name }}
    {% endcapture %}

    {% action "email" %}
      {
        "to": {{ options.email_notification_recipient__email | json }},
        "subject": {{ email_subject | unindent | strip | json }},
        "body": {{ email_body | unindent | strip | json }}
      }
    {% endaction %}
  {% endif %}
{% elsif event.topic contains "shopify/inventory_levels/" %}
  {% capture query %}
    query {
      inventoryLevel(
        id: {{ inventory_level.admin_graphql_api_id | json }}
      ) {
        item {
          variant {
            product {
              legacyResourceId
              publishedAt
              tags
              title
              totalInventory
            }
          }
        }
      }
    }
  {% endcapture %}

  {% assign result = query | shopify %}
  {% assign product_data = result.data.inventoryLevel.item.variant.product %}

  {% assign product_qualifies = true %}

  {% if product_data.publishedAt == blank %}
    {"log": "Product is already unpublished."}
    {% assign product_qualifies = false %}
  {% elsif product_data.totalInventory > options.out_of_stock_inventory_quantity__number_required %}
    {"log": "Product is not out of stock."}
    {% assign product_qualifies = false %}
  {% elsif options.only_monitor_products_with_these_tags__array != blank %}
    {% assign product_tags_qualify = false %}

    {% for tag in options.only_monitor_products_with_these_tags__array %}
      {% if product_data.tags contains tag %}
        {% assign product_tags_qualify = true %}
        {% break %}
      {% endif %}
    {% endfor %}

    {% if product_tags_qualify == false %}
      {"log": "Product does not have a qualifying tag."}
      {% assign product_qualifies = false %}
    {% endif %}
  {% endif %}

  {% if product_qualifies %}
    {% action "shopify" %}
      [
        "update",
        ["product", {{ product_data.legacyResourceId | json }}],
        {
          "published": false
        }
      ]
    {% endaction %}

    {% if options.email_notification_recipient__email != blank %}
      {% capture email_subject %}
        Out of stock: {{ product_data.title }}
      {% endcapture %}

      {% capture email_body %}
        Hi there,

        Your product is out of stock! This product has been unpublished, and is no longer available in your online storefront.

        <a href="https://{{ shop.domain }}/admin/products/{{ product_data.legacyResourceId }}">Manage this product</a>

        Thanks,
        - Mechanic, for {{ shop.name }}
      {% endcapture %}

      {% action "email" %}
        {
          "to": {{ options.email_notification_recipient__email | json }},
          "subject": {{ email_subject | unindent | strip | json }},
          "body": {{ email_body | unindent | strip | newline_to_br | json }}
        }
      {% endaction %}
    {% endif %}
  {% endif %}

  {"log": {"product": {{ product_data | json }}}}
{% endif %}
Mechanic tasks are written in Liquid, which makes them easy to write and easy to modify. Learn more about our platform.
Defaults
Out of stock inventory quantity
0