The problem ? legal products, but flagged words causing customs holds

Army & Outdoors sells outdoor and military gear. Some product titles include words that customs systems flag for inspection ? words like "combat", or specific gun part names. The products are entirely legal. Customs releases them on inspection. But the inspection itself adds days to the shipping timeframe, and every held parcel triggers a chain reaction:

  • Customer wonders why their order hasn't arrived ? customer service ticket
  • Tracking shows "held by customs" ? customer worries it's a problem
  • Eventually released ? late delivery, possibly bad review
  • Sometimes a refund or partial credit to keep the customer happy

The dispatch team had been manually editing customs declarations on individual parcels ? removing flagged words before printing labels. It worked but it didn't scale. Mistakes happened. Some parcels still went out with the original wording.

The real fix needed to be earlier in the pipeline: clean the data before it reaches StarshipIt at all.

The solution ? private Shopify app + StarshipIt API

The flagged-words admin UI

  • Built a private Shopify app with a simple admin interface
  • Manager maintains a list of flagged words ? the ones known to cause customs delays
  • List is editable in-app, no developer needed to add or remove words

The webhook flow

  1. An order is created on any of the 4 Shopify stores (NZ, AU, US, EU)
  2. orders/create webhook fires to the app
  3. HMAC verified, HTTP 200 returned immediately, work queued (the standard webhook reliability pattern)
  4. The processor reads each line item's product title and scans against the flagged-words list
  5. If no flagged words are present ? the processor skips this order. Nothing changes.
  6. If flagged words are detected ? the processor uses the StarshipIt API to update that order in StarshipIt, replacing the flagged words in the product title with cleaned text. The customs declaration that prints on the label uses the cleaned title.

What's clever about this

The Shopify storefront keeps the marketable product names. Customers see "Combat Knife" because that's what sells. The customs label sees "Outdoor Knife" because that's what doesn't get held.

Marketing wins (great product titles for the storefront and SEO). Operations win (parcels move). Customer service wins (no more "where's my parcel" tickets). All without anyone having to manually edit each label.

The technical bits worth noting

  • Manager-editable word list ? when a new flagged word is identified, the manager adds it via the admin UI. No deployment, no developer involvement. The list is authoritative ? whatever's in there gets cleaned, whatever isn't passes through unchanged.
  • Order-level intercept, not product-level edit ? the system never modifies the actual Shopify product title. Each order gets its own sanitised version sent to StarshipIt, leaving the storefront clean.
  • 4-store coverage ? the same webhook + processing pattern handles orders from NZ, AU, US, and EU. One word list applies across all stores.
  • Webhook reliability pattern ? HMAC verification, HTTP 200 first, queued processing. No retry storms even on high-volume sale days.
  • Idempotent ? if the cron processes the same order twice (e.g., after a restart), the StarshipIt update is a no-op the second time. No duplicate edits, no broken labels.
  • Logged for audit ? every cleaned order is logged with original vs cleaned title, so if a customs query ever comes back, we can prove the change.

The result

  • 300+ orders processed daily across 4 stores. The webhook quietly handles all of them.
  • 5+ years in production ? built early in my time at AAO, runs unattended.
  • Customs holds related to product titles dropped to near zero ? the parcels that DO get inspected now are inspected for legitimate reasons (random checks, prohibited categories), not because of word triggers.
  • Dispatch team stopped manually editing customs declarations. Hours per week back to the team.
  • Zero failures. No missed orders, no broken labels, no edge case that's brought it down.

Why this matters for your store

If you ship internationally and your products have any wording that could trip a customs filter ? military, knives, certain electronics, sometimes even fashion brands with trademark sensitivity ? you've probably already felt the pain of held parcels. The dispatch team's manual workaround works at low volume but breaks at scale.

The pattern here generalises. Anywhere your customer-facing product data needs to be different from what gets sent to a downstream system (customs, ERP, marketplace feeds), a small webhook + intercept layer can do that translation reliably.

I built this for AAO 5+ years ago and it's been running quietly ever since. If a customs-hold pattern is costing you time, this is fixable.