Mechanic is a development and ecommerce automation platform for Shopify. :)
Does exactly as it says: this task will publish all active products to the sales channel(s) of your choice, on demand. Optionally, filter products by a search query, or choose to have this task run hourly or daily.
Runs Occurs when a user manually triggers the task and Occurs when a bulk operation is completed. Configuration includes sales channel names, only publish products matching this query, test mode, run hourly, and run daily.
Does exactly as it says: this task will publish all active products to the sales channel(s) of your choice, on demand. Optionally, filter products by a search query, or choose to have this task run hourly or daily.
Note: this task comes with a "test mode", which is enabled by default. Run the task at least once in this mode to make sure it would publish the products you expect, and then disable the test mode.
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?)
mechanic/user/trigger mechanic/shopify/bulk_operation {% if options.run_hourly__boolean %} mechanic/scheduler/hourly {% elsif options.run_daily__boolean %} mechanic/scheduler/daily {% endif %}
{% assign sales_channel_names = options.sales_channel_names__required_array %} {% assign products_query = options.only_publish_products_matching_this_query %} {% assign test_mode = options.test_mode__boolean %} {% comment %} -- get all of the sales channel names (i.e. publications aka app catalogs) in the shop {% endcomment %} {% capture query %} query { publications( first: 250 catalogType:APP ) { nodes { id catalog { ... on AppCatalog { apps(first: 1) { nodes { title } } } } } } } {% endcapture %} {% assign result = query | shopify %} {% if event.preview %} {% capture result_json %} { "data": { "publications": { "nodes": [ { "id": "gid://shopify/Publication/1234567890", "catalog": { "apps": { "nodes": [ { "title": {{ sales_channel_names.first | json }} } ] } } } ] } } } {% endcapture %} {% assign result = result_json | parse_json %} {% endif %} {% comment %} -- save the publication IDs for all of the configured sales channel names {% endcomment %} {% assign publication_ids = array %} {% assign available_sales_channel_names = array %} {% for publication in result.data.publications.nodes %} {% assign publication_name = publication.catalog.apps.nodes.first.title %} {% assign available_sales_channel_names = available_sales_channel_names | push: publication_name %} {% if sales_channel_names contains publication_name %} {% assign publication_ids = publication_ids | push: publication.id %} {% endif %} {% endfor %} {% if publication_ids == blank %} {% error message: "None of the sales channel configured in this task exist in the shop. Check the list of available channels and verify each configured channel exists.", configured_sales_channel_names: sales_channel_names, available_sales_channel_names: available_sales_channel_names %} {% break %} {% elsif publication_ids.size != sales_channel_names.size %} {% comment %} -- using action error here so the task will continue with any other configured and matched sales channels {% endcomment %} {% action "echo" __error: "One or more configured sales channel names do not match any of the publication names available in this shop.", configured_sales_channel_names: sales_channel_names, available_sales_channel_names: available_sales_channel_names %} {% endif %} {% if event.topic == "mechanic/user/trigger" or event.topic contains "mechanic/scheduler/" %} {% comment %} -- get all active products in the shop; optionally filter the products with configured query {% endcomment %} {% unless products_query contains "status:active" %} {% assign products_query = products_query | append: " status:active" | strip %} {% endunless %} {% capture bulk_operation_query %} query { products ( query: {{ products_query | json }} ) { edges { node { __typename id {% for publication_id in publication_ids %} publishedOnPublication{{ forloop.index }}: publishedOnPublication( publicationId: {{ publication_id | json }} ) {% endfor %} } } } } {% endcapture %} {% action "shopify" %} mutation { bulkOperationRunQuery( query: {{ bulk_operation_query | json }} ) { bulkOperation { id status } userErrors { field message } } } {% endaction %} {% elsif event.topic == "mechanic/shopify/bulk_operation" %} {% if event.preview %} {% capture jsonl_string %} {"__typename":"Product","id":"gid://shopify/Product/1234567890"} {% endcapture %} {% assign bulkOperation = hash %} {% assign bulkOperation["objects"] = jsonl_string | parse_jsonl %} {% endif %} {% assign products = bulkOperation.objects | where: "__typename", "Product" %} {% assign product_ids_and_publication_ids = array %} {% comment %} -- process all products returned by the bulk op query {% endcomment %} {% for product in products %} {% for publication_id in publication_ids %} {% assign published_key = "publishedOnPublication" | append: forloop.index %} {% unless product[published_key] %} {% assign product_ids_and_publication_ids[product_ids_and_publication_ids.size] = array | push: product.id, publication_id %} {% endunless %} {% endfor %} {% endfor %} {% if test_mode %} {% log message: "Test mode: publishing actions logged only.", publishing_actions_count: product_ids_and_publication_ids.size, product_ids_and_publication_ids: product_ids_and_publication_ids %} {% break %} {% endif %} {% for keyval in product_ids_and_publication_ids %} {% action "shopify" %} mutation { publishablePublish( id: {{ keyval[0] | json }} input: { publicationId: {{ keyval[1] | json }} } ) { userErrors { field message } } } {% endaction %} {% endfor %} {% endif %}
["Online Store"]
true