Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ This directory is built automatically. Each task's documentation is generated fr
* [Auto-tag products by their options](./auto-tag-products-by-their-options)
* [Auto-tag products by their publish date](./auto-tag-products-by-their-publish-date)
* [Auto-tag products in a manual collection](./auto-tag-products-in-a-manual-collection)
* [Auto-tag products marked "Continue selling when out of stock"](./auto-tag-products-marked-continue-selling-when-out-of-stock)
* [Auto-tag products that are missing costs](./auto-tag-products-that-are-missing-costs)
* [Auto-tag products that have a "compare at" price](./auto-tag-products-that-have-a-compare-at-price)
* [Auto-tag products that meet a sales threshold](./auto-tag-products-that-meet-a-sales-threshold)
Expand Down Expand Up @@ -509,6 +510,7 @@ This directory is built automatically. Each task's documentation is generated fr
* [Auto-tag products by their options](./auto-tag-products-by-their-options)
* [Auto-tag products by their publish date](./auto-tag-products-by-their-publish-date)
* [Auto-tag products in a manual collection](./auto-tag-products-in-a-manual-collection)
* [Auto-tag products marked "Continue selling when out of stock"](./auto-tag-products-marked-continue-selling-when-out-of-stock)
* [Auto-tag products that are missing costs](./auto-tag-products-that-are-missing-costs)
* [Auto-tag products that have a "compare at" price](./auto-tag-products-that-have-a-compare-at-price)
* [Auto-tag products that meet a sales threshold](./auto-tag-products-that-meet-a-sales-threshold)
Expand Down Expand Up @@ -628,6 +630,7 @@ This directory is built automatically. Each task's documentation is generated fr
* [Auto-sort collections by inventory levels](./auto-sort-collections-by-inventory-levels)
* [Auto-tag orders by product collections](./auto-tag-orders-by-product-collections)
* [Auto-tag products in a manual collection](./auto-tag-products-in-a-manual-collection)
* [Auto-tag products marked "Continue selling when out of stock"](./auto-tag-products-marked-continue-selling-when-out-of-stock)
* [Delete the oldest x products from a specific collection](./delete-the-oldest-x-products-from-a-specific-collection)
* [Maintain a collection of new products](./maintain-a-collection-of-new-products)
* [Maintain a collection of recently purchased products](./maintain-a-collection-of-recently-purchased-products)
Expand Down Expand Up @@ -1007,6 +1010,7 @@ This directory is built automatically. Each task's documentation is generated fr
* [Auto-connect new products to all locations](./auto-connect-new-products-to-all-locations)
* [Auto-sort collections by inventory levels](./auto-sort-collections-by-inventory-levels)
* [Auto-tag out-of-stock products](./auto-tag-out-of-stock-products)
* [Auto-tag products marked "Continue selling when out of stock"](./auto-tag-products-marked-continue-selling-when-out-of-stock)
* [Auto-tag products with incoming inventory](./auto-tag-products-with-incoming-inventory)
* [Backup inventory to SFTP in Shopify CSV format](./backup-scheduled-inventory-exports-in-shopifys-csv-format)
* [Create a product inventory CSV feed](./create-a-product-inventory-feed)
Expand Down Expand Up @@ -1384,6 +1388,7 @@ This directory is built automatically. Each task's documentation is generated fr
* [Auto-tag products by their options](./auto-tag-products-by-their-options)
* [Auto-tag products by their publish date](./auto-tag-products-by-their-publish-date)
* [Auto-tag products in a manual collection](./auto-tag-products-in-a-manual-collection)
* [Auto-tag products marked "Continue selling when out of stock"](./auto-tag-products-marked-continue-selling-when-out-of-stock)
* [Auto-tag products that are missing costs](./auto-tag-products-that-are-missing-costs)
* [Auto-tag products that have a "compare at" price](./auto-tag-products-that-have-a-compare-at-price)
* [Auto-tag products that meet a sales threshold](./auto-tag-products-that-meet-a-sales-threshold)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Auto-tag products marked "Continue selling when out of stock"

Tags: Auto-Tag, Collections, Inventory, Products

This task will automatically tag any products which have variants set to "continue selling when out of stock." This allows you to set up a product collection that includes "available" products and not just products with inventory greater than zero. Configure the task with a tag to apply, and Mechanic will take care of applying and removing the tag as appropriate.

* View in the task library: [tasks.mechanic.dev/auto-tag-products-marked-continue-selling-when-out-of-stock](https://tasks.mechanic.dev/auto-tag-products-marked-continue-selling-when-out-of-stock)
* Task JSON, for direct import: [task.json](../../tasks/auto-tag-products-marked-continue-selling-when-out-of-stock.json)
* Preview task code: [script.liquid](./script.liquid)

## Default options

```json
{
"tag_for_continue_selling_products__required": "continue-selling"
}
```

[Learn about task options in Mechanic](https://learn.mechanic.dev/core/tasks/options)

## Subscriptions

```liquid
shopify/products/create
shopify/products/update
mechanic/user/trigger
```

[Learn about event subscriptions in Mechanic](https://learn.mechanic.dev/core/tasks/subscriptions)

## Documentation

This task will automatically tag any products which have variants set to "continue selling when out of stock." This allows you to set up a product collection that includes "available" products and not just products with inventory greater than zero. Configure the task with a tag to apply, and Mechanic will take care of applying and removing the tag as appropriate.

Run this task manually to update your entire product catalog at once.

## Installing this task

Find this task [in the library at tasks.mechanic.dev](https://tasks.mechanic.dev/auto-tag-products-marked-continue-selling-when-out-of-stock), and use the "Try this task" button. Or, import [this task's JSON export](../../tasks/auto-tag-products-marked-continue-selling-when-out-of-stock.json) – see [Importing and exporting tasks](https://learn.mechanic.dev/core/tasks/import-and-export) to learn how imports work.

## Contributions

Found a bug? Got an improvement to add? Start here: [../../CONTRIBUTING.md](../../CONTRIBUTING.md).

## Task requests

Submit your [task requests](https://mechanic.canny.io/task-requests) for consideration by the Mechanic community, and they may be chosen for development and inclusion in the [task library](https://tasks.mechanic.dev/)!
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
{% assign tag_for_continue_selling_products = options.tag_for_continue_selling_products__required %}

{% comment %}
-- for product create/update, filter the products query with the product ID that caused the event
{% endcomment %}

{% if event.topic contains "shopify/products/" %}
{% assign search_query = product.id | prepend: "id:" %}
{% endif %}

{% comment %}
-- query product(s) in the shop; variants will be queried separately as needed to support up to 2K variants
{% endcomment %}

{% assign cursor = nil %}
{% assign products = array %}

{% for n in (1..100) %}
{% capture query %}
query {
products(
first: 250
after: {{ cursor | json }}
query: {{ search_query | json }}
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
tags
}
}
}
{% endcapture %}

{% assign result = query | shopify %}

{% if event.preview %}
{% capture result_json %}
{
"data": {
"products": {
"nodes": [
{
"id": "gid://shopify/Product/1234567890"
}
]
}
}
}
{% endcapture %}

{% assign result = result_json | parse_json %}
{% endif %}

{% assign products = products | concat: result.data.products.nodes %}

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

{% comment %}
-- process each product by querying as many variants as needed to determine whether the product should be tagged
{% endcomment %}

{% for product in products %}
{% assign product_set_to_continue_selling = nil %}
{% assign cursor = nil %}

{% for n in (1..8) %}
{% capture query %}
query {
product(id: {{ product.id | json }}) {
variants(
first: 250
after: {{ cursor | json }}
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
inventoryPolicy
}
}
}
}
{% endcapture %}
{% action "echo" query %}

{% assign result = query | shopify %}

{% if event.preview %}
{% capture result_json %}
{
"data": {
"product": {
"variants": {
"nodes": [
{
"inventoryPolicy": "CONTINUE"
}
]
}
}
}
}
{% endcapture %}

{% assign result = result_json | parse_json %}
{% endif %}

{% assign variants = result.data.product.variants.nodes %}

{% comment %}
-- check batch of variants to see if any is marked "continue selling"
{% endcomment %}

{% for variant in variants %}
{% if variant.inventoryPolicy == "CONTINUE" %}
{% assign product_set_to_continue_selling = true %}
{% break %}
{% endif %}
{% endfor %}

{% comment %}
-- only query for more variants if the product has not yet qualified as "continue selling" AND if there are more variants
{% endcomment %}

{% if product_set_to_continue_selling %}
{% break %}
{% elsif result.data.product.variants.pageInfo.hasNextPage %}
{% assign cursor = result.data.product.variants.pageInfo.endCursor %}
{% else %}
{% break %}
{% endif %}
{% endfor %}

{% comment %}
-- adjust tags on product as needed
{% endcomment %}

{% assign tag_to_add = nil %}
{% assign tag_to_remove = nil %}

{% if product_set_to_continue_selling %}
{% unless product.tags contains tag_for_continue_selling_products %}
{% assign tag_to_add = tag_for_continue_selling_products %}
{% endunless %}

{% else %}
{% if product.tags contains tag_for_continue_selling_products %}
{% assign tag_to_remove = tag_for_continue_selling_products %}
{% endif %}

{% endif %}

{% if tag_to_add or tag_to_remove %}
{% action "shopify" %}
mutation {
{% if tag_to_add %}
tagsAdd(
id: {{ product.id | json }}
tags: {{ tag_to_add | json }}
) {
userErrors {
field
message
}
}
{% endif %}

{% if tag_to_remove %}
tagsRemove(
id: {{ product.id | json }}
tags: {{ tag_to_remove | json }}
) {
userErrors {
field
message
}
}
{% endif %}
}
{% endaction %}
{% endif %}
{% endfor %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"docs": "This task will automatically tag any products which have variants set to \"continue selling when out of stock.\" This allows you to set up a product collection that includes \"available\" products and not just products with inventory greater than zero. Configure the task with a tag to apply, and Mechanic will take care of applying and removing the tag as appropriate.\n\nRun this task manually to update your entire product catalog at once.",
"halt_action_run_sequence_on_error": false,
"name": "Auto-tag products marked \"Continue selling when out of stock\"",
"online_store_javascript": null,
"options": {
"tag_for_continue_selling_products__required": "continue-selling"
},
"perform_action_runs_in_sequence": false,
"preview_event_definitions": [],
"script": "{% assign tag_for_continue_selling_products = options.tag_for_continue_selling_products__required %}\n\n{% comment %}\n -- for product create/update, filter the products query with the product ID that caused the event\n{% endcomment %}\n\n{% if event.topic contains \"shopify/products/\" %}\n {% assign search_query = product.id | prepend: \"id:\" %}\n{% endif %}\n\n{% comment %}\n -- query product(s) in the shop; variants will be queried separately as needed to support up to 2K variants\n{% endcomment %}\n\n{% assign cursor = nil %}\n{% assign products = array %}\n\n{% for n in (1..100) %}\n {% capture query %}\n query {\n products(\n first: 250\n after: {{ cursor | json }}\n query: {{ search_query | json }}\n ) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n id\n tags\n }\n }\n }\n {% endcapture %}\n\n {% assign result = query | shopify %}\n\n {% if event.preview %}\n {% capture result_json %}\n {\n \"data\": {\n \"products\": {\n \"nodes\": [\n {\n \"id\": \"gid://shopify/Product/1234567890\"\n }\n ]\n }\n }\n }\n {% endcapture %}\n\n {% assign result = result_json | parse_json %}\n {% endif %}\n\n {% assign products = products | concat: result.data.products.nodes %}\n\n {% if result.data.products.pageInfo.hasNextPage %}\n {% assign cursor = result.data.products.pageInfo.endCursor %}\n {% else %}\n {% break %}\n {% endif %}\n{% endfor %}\n\n{% comment %}\n -- process each product by querying as many variants as needed to determine whether the product should be tagged\n{% endcomment %}\n\n{% for product in products %}\n {% assign product_set_to_continue_selling = nil %}\n {% assign cursor = nil %}\n\n {% for n in (1..8) %}\n {% capture query %}\n query {\n product(id: {{ product.id | json }}) {\n variants(\n first: 250\n after: {{ cursor | json }}\n ) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n inventoryPolicy\n }\n }\n }\n }\n {% endcapture %}\n {% action \"echo\" query %}\n\n {% assign result = query | shopify %}\n\n {% if event.preview %}\n {% capture result_json %}\n {\n \"data\": {\n \"product\": {\n \"variants\": {\n \"nodes\": [\n {\n \"inventoryPolicy\": \"CONTINUE\"\n }\n ]\n }\n }\n }\n }\n {% endcapture %}\n\n {% assign result = result_json | parse_json %}\n {% endif %}\n\n {% assign variants = result.data.product.variants.nodes %}\n\n {% comment %}\n -- check batch of variants to see if any is marked \"continue selling\"\n {% endcomment %}\n\n {% for variant in variants %}\n {% if variant.inventoryPolicy == \"CONTINUE\" %}\n {% assign product_set_to_continue_selling = true %}\n {% break %}\n {% endif %}\n {% endfor %}\n\n {% comment %}\n -- only query for more variants if the product has not yet qualified as \"continue selling\" AND if there are more variants\n {% endcomment %}\n\n {% if product_set_to_continue_selling %}\n {% break %}\n {% elsif result.data.product.variants.pageInfo.hasNextPage %}\n {% assign cursor = result.data.product.variants.pageInfo.endCursor %}\n {% else %}\n {% break %}\n {% endif %}\n {% endfor %}\n\n {% comment %}\n -- adjust tags on product as needed\n {% endcomment %}\n\n {% assign tag_to_add = nil %}\n {% assign tag_to_remove = nil %}\n\n {% if product_set_to_continue_selling %}\n {% unless product.tags contains tag_for_continue_selling_products %}\n {% assign tag_to_add = tag_for_continue_selling_products %}\n {% endunless %}\n\n {% else %}\n {% if product.tags contains tag_for_continue_selling_products %}\n {% assign tag_to_remove = tag_for_continue_selling_products %}\n {% endif %}\n\n {% endif %}\n\n {% if tag_to_add or tag_to_remove %}\n {% action \"shopify\" %}\n mutation {\n {% if tag_to_add %}\n tagsAdd(\n id: {{ product.id | json }}\n tags: {{ tag_to_add | json }}\n ) {\n userErrors {\n field\n message\n }\n }\n {% endif %}\n\n {% if tag_to_remove %}\n tagsRemove(\n id: {{ product.id | json }}\n tags: {{ tag_to_remove | json }}\n ) {\n userErrors {\n field\n message\n }\n }\n {% endif %}\n }\n {% endaction %}\n {% endif %}\n{% endfor %}\n",
"subscriptions": [
"shopify/products/create",
"shopify/products/update",
"mechanic/user/trigger"
],
"subscriptions_template": "shopify/products/create\nshopify/products/update\nmechanic/user/trigger",
"tags": [
"Auto-Tag",
"Collections",
"Inventory",
"Products"
]
}