I built a Shopify admin-integrated application to manage period inventory cycle counts for inventory at my wife’s brick and mortar Shopify shop. Aside from the portion of the app that integrates directly in the administrative portal, it also has an accompanying iOS app for traveling the floor and stock room to scan and count all products. I believe we’ve solved many of the problems that would regularly be encountered while performing this sort of routine task.
My Question - What is everyone already using? I don’t want to introduce a new product where something else already checks the boxes that I have, so I’m curious as to how folks are solving this problem today?
I work in technology (primarily in systems integration) and believe I’ve provided an efficient workflow for this routine activity while adding value while saving time.
I’d also be happy to provide a brief video walk through or one-sheet if anyone is interested in what I’ve built.
Your timing is better than you probably realize. Stocky goes away after August 31, so a week from now. That is what most POS Pro shops were using for stocktakes and it came free with the plan, which is a big part of why nothing else got much traction in that slot.
Shopify’s transition page is worth reading closely because it splits cleanly. Transfers, purchase orders, quantity adjustments and historical inventory reporting all landed in Admin natively. Counting did not. What is native now is Quick count in POS, and Shopify describes it as spot checking specific products or zones, up to 1,000 items in a single session. For a full audit the documented path is export to CSV, count offline, reimport.
So the honest answer to what people are using is that a lot of them are about to find out. The two routes I see are splitting a full count into a pile of Quick count sessions by zone, or the spreadsheet round trip.
One angle I would chase this month specifically. Suppliers cannot be exported out of Stocky at all, and Shopify’s own warning is that Stocky data might not be retrievable if you uninstall. Anyone leaving has a gap on September 1. If your app can take a Stocky export and stand the supplier records back up, that is a reason for someone to pick you in the next two weeks rather than shopping around next quarter.
Also curious how you handle a count where two people are on the floor scanning at the same time. That is where the CSV route falls over and where I would expect the real differentiation to sit.
@smccarty Landscape question is well covered above so Ill go at the technical side, since three things decide whether a count app is trustworthy and theyre all easy to get wrong.
Write to on_hand, not available. On hand is the total of committed, unavailable and available. If you count 10 units on the shelf and set available to 10 while one is committed to an open order, youve just told Shopify there are 11. Counting and available are different concepts and a stocktake is always an on_hand statement.
Use the compare and set behaviour rather than opting out of it. inventorySetQuantities only writes if the persisted quantity still matches the compareQuantity you send, otherwise it errors. Theres an ignoreCompareQuantity flag to skip that check and its tempting when you hit errors, but skipping it is exactly how a count silently overwrites a sale that happened while someone was walking the floor.
That also answers the two scanners question above. With compare and set, the second write just fails rather than clobbering the first, so the real design problem isnt preventing the collision, its what your iOS app does when it gets that error. Silently retrying with a fresh compare value is wrong, because the number changed for a reason. Surfacing it as recount this SKU is the right behaviour and its the sort of thing that only shows up once two people are actually on the floor.
Third, put a count session identifier in referenceDocumentUri on every write. Its accepted on inventorySetQuantities, inventoryAdjustQuantities and inventoryMoveQuantities, and it means a merchant can later trace any adjustment back to the specific count that caused it. For an audit thats the difference between a tool and a system of record, and its close to free to implement.
One thing to check if you built this a while ago. inventorySetOnHandQuantities is deprecated in favour of inventorySetQuantities with name set to on_hand. Worth confirming which one youre calling before you put it in front of anyone.
You indicated you thought you were solving a problem that nobody else has built an app for yet. I welcome any sort of competition (there’s a lot since Stocky is going away), but FyreTrail does offer Cycle Counts as well with the inventory counting section.
Other features include:
Mobile Login: Allows you to login with an iPad, walk around the store and scan items for the count.
Multi-user Counting: so you can attack any count type with multiple people at once.
Live Adjustment Tracking: FyreTrail automatically tracks when you started, when you ended and analyzes the inventory changes during that timeframe that you were counting and allows you to apply all or to pick and choose what you wanted to apply.
Full end of count summary: At the end of your count, you can review by category, brand, etc. export, compare levels and identify missed items. You can even apply the changes back to Shopify to maintain consistent inventory levels.
One thing worth adding to the write-path advice above, from the other side of the same problem: after the count is submitted, read the levels back from Shopify and compare them to what you sent. Bulk inventory writes fail partially and quietly more often than people expect, and a count that says “applied” is not the same as a count that landed.
The second habit that pays for itself is snapshotting the levels immediately before the count starts. Without that, a discrepancy the next morning is unattributable: you cannot tell a miscount from a sale, a return or another app writing at the same time. With it, the difference is arithmetic.
Neither needs a vendor. A saved export and a diff of the two files does the job, and it is the cheapest way to make counts trustworthy.
Agreed on reading levels back after you apply. The gap that bit us sits earlier, between snapshot and apply.
A merchant this month, around 4,000 variants, counted across several days. Sales kept happening the whole time.
Our apply step sent changeFromQuantity based on stock as of the start of the count, and the inventoryAdjustQuantities idempotency guard rejected the whole batch because the current quantity no longer matched. That is the loud failure. The quiet one is worse. Send a blind delta instead, and one sale mid-count silently lands you on the wrong number.
The fix was simple once we saw it. Re-read the live quantity for every line right before applying, then set the target to the counted number: delta is counted minus current, changeFromQuantity is current. A sale mid-count becomes a non-event, because a stocktake sets stock to what you counted.
One more lesson. On big catalogs a count stretches over days, and that widens the window. Letting people cut a count into slices, a few hundred at a time, one vendor, in-stock only, shrinks the exposure more than any clever API handling does.
I build Binly. This cost one of our merchants real data before we shipped the fix.