-
Notifications
You must be signed in to change notification settings - Fork 38
Auto-tag products marked "Continue selling when out of stock" #520
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
timdmackey
wants to merge
1
commit into
lightward:main
Choose a base branch
from
timdmackey:task/auto-tag-products-with-continue-selling
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+268
−0
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
docs/auto-tag-products-marked-continue-selling-when-out-of-stock/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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/)! |
192 changes: 192 additions & 0 deletions
192
docs/auto-tag-products-marked-continue-selling-when-out-of-stock/script.liquid
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 %} | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line 94 inadvertently left in from development? |
||
|
|
||
| {% 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 %} | ||
24 changes: 24 additions & 0 deletions
24
tasks/auto-tag-products-marked-continue-selling-when-out-of-stock.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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" | ||
| ] | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI only, no change needed... the original task this new one is based on was developed before Shopify increased the variant query limit on a single product object to 2048. This inner paginated query could be reduced to a single query for all variants. I checked the
requestedQueryCostand it only went up to 18 from 14 when increasing the 250 to 2048.