Add Option Name as a Variant Metafield for In Stock Variants, with Mechanic.

Mechanic is a development and ecommerce automation platform for Shopify. :)

Add Option Name as a Variant Metafield for In Stock Variants

This task populates variant metafields with your desired variant options for use by Online Store 2.0 filtering, taking into account whether or not a variant has inventory available for sale online. It runs when inventory levels are updated, and may also be run manually to scan all variants in your shop.

Runs Occurs whenever an inventory level is updated, Occurs when a user manually triggers the task, and Occurs when a bulk operation is completed. Configuration includes metafield namespace and option names and metafield keys.

15-day free trial – unlimited tasks

Documentation

This task populates variant metafields with your desired variant options for use by Online Store 2.0 filtering, taking into account whether or not a variant has inventory available for sale online. It runs when inventory levels are updated, and may also be run manually to scan all variants in your shop.

Configure it with a single metafield namespace (e.g. "my_fields") and one or more variant options (e.g. "Size") paired with their respective metafield key (e.g. "size_in_stock").

Important: To use OS 2.0 collection and search filtering, you must configure variant metafield definitions for each metafield key configured in this task. Read Shopify's documenation on adding metafield definitions for more info.

Developer details

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

(By the way, have you seen our documentation? Have you joined the Slack community?)

Open source
View on GitHub to contribute to this task
Subscriptions
shopify/inventory_levels/update
mechanic/user/trigger
mechanic/shopify/bulk_operation
Tasks use subscriptions to sign up for specific kinds of events. Learn more
Options
metafield namespace (required) , option names and metafield keys (keyval, required)
Code
{% assign metafield_namespace = options.metafield_namespace__required | strip %}
{% assign option_names_and_metafield_keys = options.option_names_and_metafield_keys__keyval_required %}
{% assign metafield_keys = option_names_and_metafield_keys | values %}

{% capture metafields_query %}
  {% for metafield_key in metafield_keys %}
    metafield_{{ metafield_key | md5 }}: metafield(
      namespace: {{ metafield_namespace | json }}
      key: {{ metafield_key | json }}
    ) {
      id
      value
    }
  {% endfor %}
{% endcapture %}

{% assign variants = array %}

{% if event.topic == "shopify/inventory_levels/update" %}
  {% capture query %}
    query {
      inventoryLevel(id: {{ inventory_level.admin_graphql_api_id | json }}) {
        item {
          variant {
            id
            displayName
            inventoryPolicy
            availableForSale
            sellableOnlineQuantity
            selectedOptions {
              name
              value
            }
            {{ metafields_query }}
          }
        }
      }
    }
  {% endcapture %}

  {% assign result = query | shopify %}

  {% assign variants[0] = result.data.inventoryLevel.item.variant %}

{% elsif event.topic == "mechanic/user/trigger" %}
  {% capture bulk_operation_query %}
    query {
      productVariants {
        edges {
          node {
            id
            displayName
            inventoryPolicy
            availableForSale
            sellableOnlineQuantity
            selectedOptions {
              name
              value
            }
            {{ metafields_query }}
          }
        }
      }
    }
  {% endcapture %}

  {% action "shopify" %}
    mutation {
      bulkOperationRunQuery(
        query: {{ bulk_operation_query | json }}
      ) {
        bulkOperation {
          id
          status
        }
        userErrors {
          field
          message
        }
      }
    }
  {% endaction %}

{% elsif event.topic == "mechanic/shopify/bulk_operation" %}
  {% assign variants = bulkOperation.objects %}
{% endif %}

{% if event.preview %}
  {% capture variants_json %}
    [
      {
        "id": "gid://shopify/ProductVariant/1234567890",
        "displayName": "Duffel Bag - Pleather / Large",
        "inventoryPolicy": "DENY",
        "availableForSale": true,
        "sellableOnlineQuantity": 1,
        "selectedOptions": [
          {
            "name": "Material",
            "value": "Pleather"
          },
          {
            "name": "Size",
            "value": "Large"
          }
        ]
      }
    ]
  {% endcapture %}

  {% assign variants = variants_json | parse_json %}
{% endif %}

{% comment %}
  -- save mutation inputs for setting and deleting metafields
{% endcomment %}

{% assign metafields_to_set = array %}
{% assign metafields_to_delete = array %}

{% for variant in variants %}
  {% assign is_in_stock = nil %}

  {% if variant.availableForSale %}
    {% if variant.sellableOnlineQuantity > 0 or variant.inventoryPolicy == "CONTINUE" %}
      {% assign is_in_stock = true %}
    {% endif %}
  {% endif %}

  {% for selected_option in variant.selectedOptions %}
    {% assign selected_option_name = selected_option.name | downcase %}

    {% for keyval in option_names_and_metafield_keys %}
      {% assign configured_option_name = keyval[0] | downcase %}

      {% if configured_option_name == selected_option_name %}
        {% assign set_metafield = nil %}
        {% assign metafield_key = keyval[1] %}
        {% assign metafield_alias = metafield_key | md5 | prepend: "metafield_" %}
        {% assign metafield = variant[metafield_alias] %}

        {% if metafield == blank %}
          {% if is_in_stock %}
            {% assign set_metafield = true %}
          {% endif %}

        {% elsif is_in_stock %}
          {% if metafield.value != selected_option.value %}
            {% assign set_metafield = true %}
          {% endif %}

        {% else %}
          {% assign metafield_to_delete = hash %}
          {% assign metafield_to_delete["ownerId"] = variant.id %}
          {% assign metafield_to_delete["namespace"] = metafield_namespace %}
          {% assign metafield_to_delete["key"] = metafield_key %}
          {% assign metafields_to_delete = metafields_to_delete | push: metafield_to_delete %}
        {% endif %}

        {% if set_metafield %}
          {% assign metafield_to_set = hash %}
          {% assign metafield_to_set["ownerId"] = variant.id %}
          {% assign metafield_to_set["namespace"] = metafield_namespace %}
          {% assign metafield_to_set["key"] = metafield_key %}
          {% assign metafield_to_set["type"] = "single_line_text_field" %}
          {% assign metafield_to_set["value"] = selected_option.value | append: "" %}
          {% assign metafields_to_set = metafields_to_set | push: metafield_to_set %}
        {% endif %}
      {% endif %}
    {% endfor %}
  {% endfor %}
{% endfor %}

{% unless event.topic == "mechanic/shopify/bulk_operation" %}
  {% log
    total_metafields_being_set: metafields_to_set.size,
    total_metafields_being_deleted: metafields_to_delete.size
  %}
{% endunless %}

{% comment %}
  -- metafields may be set 25 at a time
{% endcomment %}

{% if metafields_to_set != blank %}
  {% assign groups_of_metafields_to_set = metafields_to_set | in_groups_of: 25, fill_with: false %}

  {% for group_of_metafields_to_set in groups_of_metafields_to_set %}
    {% action "shopify" %}
      mutation {
        metafieldsSet(
          metafields: {{ group_of_metafields_to_set | graphql_arguments }}
        ) {
          metafields {
            id
            namespace
            key
            type
            value
            owner {
              ... on ProductVariant {
                id
              }
            }
          }
          userErrors {
            code
            field
            message
          }
        }
      }
    {% endaction %}
  {% endfor %}
{% endif %}

{% comment %}
  -- metafields may be deleted in batches of 250
{% endcomment %}

{% if metafields_to_delete != blank %}
  {% assign groups_of_metafields_to_delete = metafields_to_delete | in_groups_of: 250, fill_with: false %}

  {% for group_of_metafields_to_delete in groups_of_metafields_to_delete %}
    {% action "shopify" %}
      mutation {
        metafieldsDelete(
          metafields: {{ group_of_metafields_to_delete | graphql_arguments }}
        ) {
          deletedMetafields {
            ownerId
            namespace
            key
          }
          userErrors {
            field
            message
          }
        }
      }
    {% endaction %}
  {% endfor %}
{% endif %}
Task code is written in Mechanic Liquid, an extension of open-source Liquid enhanced for automation. Learn more