No. 07 · Business · 2026
Inventory Tracker
SalmonCat's order and inventory workbook, and the Google Apps Script that now files every Shopify order into it and opens a Discord ticket for fulfillment, so nobody copies a CSV by hand.
- Role
- Builder
- Runs on
- Google Apps Script
- Live since
- June 2026
In this issue
- (1)The spreadsheet that held it together
- (2)Orders that file themselves
- (3)Rows that stay true
- (4)Next: stock that counts itself
Inventory Tracker · Ops tooling
The spreadsheet that held it together
SalmonCat’s inventory lived in spreadsheets far longer than it should have. One workbook tracked every order, every kit and every part through the launch and the years after it. It was the load-bearing piece of the whole operation, held together with the flimsiest tool we had, and a proper system from day one would have saved real money and real stress. I’d build that first next time.
By 2026 the problem had changed shape. I was in Japan, and my brother was packing and shipping orders in the US. The workbook itself still worked: an Orders Master tab took the raw Shopify export, and a formula-driven Order sheet fanned each order out into lines and removed duplicate order numbers. But every order still went through three steps by hand before anyone could ship it.
What every order went through
The first three steps were copying and messaging. The tracker took those over; buying the label stays a person's job.
- 01Now automated Download the CSV Export the new orders from Shopify
- 02Now automated Paste into Orders Master The formulas take it from there
- 03Now automated Message my brother Which order, what to pack
- 04 Buy the label In Shopify
- 05 Ship it From the US
Hand-kept numbers drift, too. When I counted stock in April 2026, the master list said there were no Aizome bodies left. The shelf had five.
Orders that file themselves
A Google Apps Script bound to the order sheet now does the middle of the job. Every ten minutes it asks Shopify for any order newer than the last one it saw, writes it into Orders Master, and posts one Discord ticket per order to the fulfillment channel. There’s no server: it runs on Google’s infrastructure, for free.
Where an order goes now
Nothing is copied by hand between Shopify and the person packing the box.
Writing rows the way a person would
Multi-item orders are written the way Shopify’s own CSV export writes them: the first row carries the order’s fields and its first item, and each further item gets a continuation row. That makes the new rows exactly what the sheet already expected, so none of the formulas downstream had to change. Columns are found by their header names at run time, so reordering the sheet can’t break it.
A three-item order in Orders Master
| A | B | C | D | E | ⋯ | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Name | Financial Status | Paid at | Paid Date (Clean) | Lineitem quantity | Lineitem name | Lineitem sku | Lineitem price | Total | ||
| 2 | #SCS2041 | [email protected] | paid | 2026-07-14T09:12:44-07:00 | 2026-07-14 | 1 | Aozora Base Kit - Hakushi / Brass | AZ-001 | 130.00 | 159.68 | |
| 3 | #SCS2041 | [email protected] | 1 | Extra Plate - Polycarbonate | PL-003 | 12.99 | |||||
| 4 | #SCS2041 | [email protected] | 1 | PCB Foam | FM-001 | 1.69 |
A ticket for the person shipping
Each order opens its own thread in a Discord forum channel, @-mentioning my brother, with everything he needs to pack it and a link straight to buying the label. Right after checkout, Shopify sometimes returns a new order before its line items have landed. The script waits three seconds and asks again; if the order is still empty, it stays out of the sheet and its ticket is flagged instead of passing for a normal one.
#orders › #SCS2041 — Jordan Lee
#orders › #SCS2042 — Sam Ortiz
What stays manual, on purpose
Buying the shipping label stays in Shopify, and the label PDF goes into the order’s Discord thread. A PDF in the thread means clear to ship.
Shipped
I built it on 2026-06-29 and checked it against real past orders with a local dry-run harness. Shopify had retired the old custom-app tokens in January 2026, so it authenticates through a Partners app. It went live on 2026-06-30 and processed four real orders on its first run.
Rows that stay true
Writing an order once isn’t enough: it gets paid, shipped, tagged, and sometimes cancelled. So every run ends with a second pass. The script asks Shopify for every order changed since its last run, finds that order’s rows by their Shopify ID, and brings them up to date: fulfillment status, ship date, payment status and tags on the order’s first row, and each item’s own fulfillment status on its row. The ship date gets the same live formula as the payment date, so the time from payment to shipment now tracks itself. A cancelled order’s rows are deleted outright.
A one-off repair job covers the past. It scans the last 30 days of orders, matches them against the sheet by ID, and adds any that are missing, without posting their tickets a second time.
Next: stock that counts itself
The last manual piece is the stock itself. A sold base kit should take its parts off the inventory list, but a kit isn’t one item. It’s a bill of materials, and its parts depend on each other.
What one base kit takes
RuleThe badge has to be the same metal as the plate.
That rule is what a part-by-part count hides. In April 2026 there were plates for 178 kits and bodies and PCBs for 80, but only 68 matching badges, 40 brass and 28 aluminum.
Kits the April 2026 stock could make, part by part
A kit needs one of each part, in matching metal. Whichever runs out first sets the limit.
SalmonCat inventory count, 16 April 2026.
See the numbers
| Measure | Value |
|---|---|
| Plates, brass + aluminum | 178 |
| Bodies | 80 |
| Hotswap PCBs | 80 |
| Badges, A + B grade | 68 |
| Kit limit 68 | 68 |
So the badges ran out first, and 12 bodies had no matching badge set. That’s the number a tracker should show without anyone working it out by hand, and it’s the next thing to build: decrement each part as an order comes in, and report how many complete kits are left.