Tom Sailors Contact
Guide · Inventory

Tracking fractional inventory in Shopify with Matrixify and Google Scripts

Published 2024-04-22 · Updated 2026-06-11

This is the code companion to the no-app fractional inventory solution: the two Google Apps Scripts that keep a true-decimal stock ledger in Google Sheets while Shopify's integer inventory stays safely rounded down. Published in 2024, still the working pattern in 2026 — Shopify inventory remains whole-numbers-only.

Setup

Script A — process incoming orders

Triggers on edit. Watches the order export tab, copies the order across, and subtracts each line item's decimal quantity from the matching SKU in "Precise Inventory".

function onEditScriptA(e) {
  var ss = e.source;
  var editedSheet = ss.getActiveSheet();
  var editedRange = e.range;

  // Check if the edited sheet is "Export from Shopify - Orders"
  if (editedSheet.getName() === "Export from Shopify - Orders") {
    var editedRow = editedRange.getRow();
    var lastColumn = editedSheet.getLastColumn();
    var orderData = editedSheet.getRange(editedRow, 1, 1, lastColumn).getValues()[0];

    // Get the "Import to Shopify - Products" sheet
    var importSheet = ss.getSheetByName("Import to Shopify - Products");
    var importLastRow = importSheet.getLastRow();

    // Copy the order to "Import to Shopify - Products"
    importSheet.appendRow(orderData);

    // Adjust corresponding inventory in the "Precise Inventory" sheet
    var preciseInventorySheet = ss.getSheetByName("Precise Inventory");
    var skuColumnIndex = 1; // Assuming SKU is in the first column

    // Loop through line items and adjust inventory
    for (var i = 2; i <= lastColumn; i++) {
      var sku = orderData[i];
      var quantity = orderData[i];

      // Find the row in "Precise Inventory" corresponding to the SKU
      var skuRange = preciseInventorySheet.getRange(2, skuColumnIndex, importLastRow - 1, 1);
      var skuValues = skuRange.getValues();
      for (var j = 0; j < skuValues.length; j++) {
        if (skuValues[j][0] === sku) {
          preciseInventorySheet.getRange(j + 2, 2).setValue(
            preciseInventorySheet.getRange(j + 2, 2).getValue() - quantity
          );
          break;
        }
      }
    }
  }
}

Script B — write revised figures to the import tab

Also triggers on edit. Matches SKUs between "Precise Inventory" and "Import to Shopify", inserting the revised values into the column Matrixify imports.

function onEditScriptB(e) {
  var ss = e.source;
  var editedSheet = ss.getActiveSheet();

  // Check if the edited sheet is "Import to Shopify - Products"
  if (editedSheet.getName() === "Import to Shopify - Products") {
    var lastRow = editedSheet.getLastRow();
    var lastColumn = editedSheet.getLastColumn();

    var preciseInventorySheet = ss.getSheetByName("Precise Inventory");
    var preciseInventoryRange = preciseInventorySheet.getRange("A2:B");
    var preciseInventoryValues = preciseInventoryRange.getValues();

    // Loop through each row in "Import to Shopify - Products"
    for (var i = 2; i <= lastRow; i++) {
      var sku = editedSheet.getRange(i, 1).getValue();
      var quantity = editedSheet.getRange(i, lastColumn).getValue();

      for (var j = 0; j < preciseInventoryValues.length; j++) {
        if (preciseInventoryValues[j][0] === sku) {
          preciseInventorySheet.getRange(j + 2, 2).setValue(quantity);
          break;
        }
      }
    }
  }
}

Notes from running this in production

Want the sturdier version of this?

The sheet works. When it stops being enough, the same logic moves into a small webhook-driven app. Email Tom with your volume and location count.

Email Tom →