Workflow

Why we ditched our spreadsheet macros for a real fetcher

For about a year we tried to run our AliExpress tracking workflow entirely inside Google Sheets — using Apps Script, custom menus, and a chain of formulas. It mostly worked. It also mostly broke at the worst times. Here's what we learned.

The naive approach: Apps Script + UrlFetchApp

The first version was 200 lines of Apps Script. A custom menu added "Update tracking" to the toolbar. Click it, and a script looped through column H, hit AliExpress's API for each one, parsed the response, and wrote tracking + status back to the row. Simple.

It worked on day one. It broke on day three:

  • 30-second timeout. Google Apps Script's UrlFetchApp calls cap a single execution at 6 minutes, and 30s per call. With 200 pending orders and AE taking 1-2s per call, we hit the wall every time.
  • No retries. AE rate limits with a "frequency exceeds the limit" error. Apps Script had no concept of "wait and try again" — those orders just got skipped.
  • OAuth refresh nightmare. AliExpress access tokens expire every 24h. Apps Script's secure storage is awkward; we ended up with a token-refresh script that ran on a daily trigger and broke whenever Google rotated their service account quotas.
  • Sharing it was impossible. Every store needed its own script project, its own deployment URL, and its own OAuth credential. We had three eBay accounts and three different broken setups.

The middleware version: Apps Script + a PHP backend

The next iteration moved the API calls out of Apps Script entirely. Apps Script's only job became: "tell my backend which orders are pending, then accept the results back and write them to the sheet". A PHP backend on Hostinger handled the actual AE/eBay calls, retries, token refresh, and rate limiting.

This worked much better. But the seam between the sheet and the backend introduced its own problems:

  • Sheet data validation on dropdown columns silently rejected writes. Cells stayed empty. We didn't notice for a week.
  • The auto-chain (process 25, fetch next 25) would loop on the same rows if writes didn't stick.
  • Refund detection required pulling two different AE endpoints and combining them — too much for an Apps Script project to coordinate.

What actually works: a real fetcher

Eventually we accepted that what we wanted wasn't a spreadsheet macro — it was a real application that happened to write to a spreadsheet. The split that finally stuck:

  • The sheet is the database — it stores order rows. Read it, write to it, but never depend on Apps Script for logic.
  • A PHP backend does eBay and AliExpress calls, token refresh, rate-limit retries, refund derivation, carrier mapping.
  • A web UI kicks off batches, shows progress, and lets you debug a single AE Order ID end-to-end.
  • A skip list tracks which IDs were already touched in the current run, so the auto-chain advances even when writes fail silently.

That's the architecture Fetch Order Tracking is built on. We didn't set out to build a product — we set out to fix a broken Apps Script. The product was the result of finally giving up on macros.

What we'd tell ourselves a year ago

  1. Don't put your API calls in Apps Script. Use a real backend.
  2. The Refund column is more important than the Tracking column. Get refund detection right first.
  3. Test your write logic against a sheet that has data validation. Half your writes will fail silently otherwise.
  4. Build a debug endpoint that fetches one order ID and dumps the raw AE response. You'll use it weekly.

Try the fetcher More guides