About Me My Work Blog Contact
Back

How To Hide Out Of Stock Products on Shopify - No App

Posted on: 15 Mar 2025

Hide Out of Stock Products on Shopify

How To Hide Out Of Stock Products on Shopify - No App

Many Shopify store owners ask, "How do I hide out-of-stock products?" Unfortunately, Shopify does not offer a built-in solution, and most apps that do this require a paid subscription.

In this guide, I'll show you how to hide products with zero inventory using the Shopify Storefront API via a custom Ruby without affecting pagination.

Why Shopify Doesn't Support This by Default

Editing collection.liquid to exclude out-of-stock items can break pagination and filtering. You can go through and manually adjust each collection to filter out of stock products, but this is time-consuming and not scalable if your store has lots of collections.

Many users have asked Shopify for a native fix, but they have yet to implement one: Reddit Discussion.

Free & Fast Method: Shopify Storefront API

The best way to hide out-of-stock products is by programmatically updating collection rules to include an inventory filter.

Prerequisites

  • You must have Ruby installed on your computer.
  • Install the required gems: shopify_api (v14.8.0) and logger (v1.6.6).
  • Create a custom Shopify app with API access.

Step 1: Create a Shopify Custom App

  1. Log in to your Shopify store.
  2. Go to Settings > Apps and Sales Channels > Develop Apps.
  3. Create a Shopify Custom App App and Sales Channels Develop Apps
  4. Enable custom app development.
  5. Allow Custom App Development
  6. Create a new app and name it something like Hide Out of Stock.
  7. Create a New App
  8. Click API Credentials and allow read & write permissions for products.
  9. API Credentials Scopes Enable Scopes
  10. Use Shopify API version 2025-01.
  11. API Version
  12. Install the app and retrieve your Admin API Access Token.
  13. Install App Access Token

Step 2: Run the Ruby Script

Copy the script below and save it as hide-out-of-stock-products.rb.

Replace SHOP_NAME, ACESS_TOKEN and LIMIT with your values.


#!/usr/bin/env ruby
# frozen_string_literal: true

require 'shopify_api'
require 'logger'

# Shopify store credentials
SHOP_NAME = "your-store-name"
ACCESS_TOKEN = "YOUR_ACCESS_TOKEN" # Use the admin token, not the API secret

LIMIT = 5 # Adjust as needed

ShopifyAPI::Context.setup(
  api_key: "DUMMY_VALUE",
  host_name: "DUMMY_VALUE",
  scope: "DUMMY_VALUE",
  private_shop: "#{SHOP_NAME}.myshopify.com",
  api_secret_key: ACCESS_TOKEN,
  is_embedded: false,
  is_private: true,
  api_version: "2025-01"
)

session = ShopifyAPI::Auth::Session.new(
  shop: "#{SHOP_NAME}.myshopify.com",
  access_token: ACCESS_TOKEN
)
client = ShopifyAPI::Clients::Graphql::Admin.new(session: session)

# GraphQL query to get all collections and their filters
GET_COLLECTIONS_QUERY = <<-GRAPHQL
  {
    collections(first: 100) {
      edges {
        node {
          id
          title
          ruleSet {
            appliedDisjunctively
            rules {
              column
              relation
              condition
            }
          }
        }
      }
    }
  }
GRAPHQL

response = client.query(query: GET_COLLECTIONS_QUERY)
result = response.body
errors = result.dig("errors") || result.dig("data", "collectionUpdate", "userErrors") || []

if errors.any?
  puts "❌ Error fetching collections: #{errors}"
  exit
end

collections = result.dig("data", "collections", "edges") || []
index = 0

collections.each do |collection|
  index += 1
  break if index > LIMIT

  collection_id = collection["node"]["id"]
  title = collection["node"]["title"]
  rule_set = collection["node"]["ruleSet"]

  next if rule_set.nil?

  rules = rule_set["rules"] || []
  has_inventory_filter = rules.any? { |rule| rule["column"] == "VARIANT_INVENTORY" && rule["relation"] == "GREATER_THAN" && rule["condition"] == "0" }

  unless has_inventory_filter
    new_rules = rules + [{ "column" => "VARIANT_INVENTORY", "relation" => "GREATER_THAN", "condition" => "0" }]
    update_mutation = <<-GRAPHQL
      mutation {
        collectionUpdate(input: {
          id: "#{collection_id}",
          ruleSet: { appliedDisjunctively: false, rules: [#{new_rules.map { |r| "{ column: #{r['column']}, relation: #{r['relation']}, condition: #{r['condition'].inspect} }" }.join(", ")}] }
        }) {
          collection { id }
          userErrors { field message }
        }
      }
    GRAPHQL

    update_response = client.query(query: update_mutation)
    puts update_response.body.dig("data", "collectionUpdate", "userErrors") ? "❌ Error updating #{title}" : "✅ Updated: #{title}"
  end
end
puts "🎉 Finished processing collections."

Final Steps

  1. Open a terminal and navigate to the script folder.
  2. Run: gem install shopify_api
  3. Run: ruby ./hide-out-of-stock-products.rb

That's it! Your out-of-stock products will now be hidden automatically.

Need help? Feel free to contact me!

Let me know in the comments if you run into any issues or have questions.

About the Author

Hi, I'm Jordan Lagan, a full-stack software engineer and web develoepr. I've been writing code professionally since 2017.

I'm passionate about sharing what I learn and helping other developers grow. If you found this article helpful or have questions, feel free to reach out or learn more about me.