Calculate Shipping Fees by Distance with a Directions API
Compute real shipping fees from actual route distance and time using GoGoDuk's /v1/directions — motorbike-optimized routing for Vietnam, free forever.
A flat shipping fee sounds simple, but it drifts off quickly: far orders lose money, while nearby customers see an inflated price and abandon the cart. A fairer model charges by the actual distance and time of the route. This guide pulls those two numbers from GoGoDuk's Directions API and turns them into a shipping-fee formula — with motorbike-optimized routing, the way most delivery riders in Vietnam actually travel.
Why real road distance beats straight-line
Many apps compute fees from the straight-line (Haversine) distance between two coordinates. The problem: straight-line distance is almost always shorter than the real route. A shop in District 1 delivering to Thu Duc (HCMC) might be only ~9 km as the crow flies, but the real motorbike route — bridges, one-way streets, roundabouts — is meaningfully longer. Charging by straight-line distance means subsidizing every long-haul order.
This is a different model from zone-based pricing, where you split the city into districts/wards and assign each a fixed fee. If that fits you better, see Build delivery zones. A quick rule of thumb:
- Zone-based — simple and predictable; good when you serve a handful of inner districts.
- Distance-based — precise and fair; good when your delivery radius is wide or you want fees to reflect each order's true cost.
Get distance & duration from /v1/directions
The endpoint returns a Google Directions–compatible shape, so the two fields
we need sit right in routes[0].legs[0].
Request
Call it directly with curl or fetch — the TypeScript SDK doesn't wrap
directions yet, so use a raw request. Example: a District 1 shop delivering to a
customer in Thu Duc:
origin/destination—lat,lngformat.vehicle— currentlymotobike(default);caris coming later.- Required key scope:
routing:read.
Response
Trimmed JSON — we only care about distance.value and duration.value of the
first leg:
Watch the units — this is the easiest place to introduce a bug:
distance.valueis in meters (divide by 1000 for km).duration.valueis in seconds (divide by 60 for minutes).
The shipping-fee formula
Keep the fee logic in a pure function — easy to test and reuse. The VND numbers below are illustrative only — not GoGoDuk's pricing, and not any courier's tariff; swap in your own policy.
A time-based surcharge
duration.value lets you add a surcharge for routes that take longer (peak hours,
traffic) — distance and duration complement each other:
Handling ESTIMATED routes
When the engine can't connect two points (islands, broken road network, off
coordinates), GoGoDuk doesn't return an error — it returns an estimated route
with status: "ESTIMATED": distance becomes the straight-line distance times a
road factor, and duration is estimated from an average speed. You always get a
number to bill against, but handle it transparently:
Two common approaches: (1) still quote a fee but mark it "estimated", or (2) for high-value orders, require staff confirmation before checkout.
Production notes
- Compute the fee on the backend, not the client. If browser JavaScript computes it, a customer can tamper with the price before submitting the order.
- Cache by
origin→destinationpair. The same shop delivering to the same address has a fixed distance — cache it instead of calling on every request. - Point-to-point only for now — there's no distance-matrix endpoint. For an
order with multiple drops, call
/v1/directionsonce per leg (batch matrix is on the roadmap, not yet available). - When a customer drops a pin instead of typing an address, use reverse geocoding to get the province/district and coordinates first, then feed those coordinates into directions.
When not to build this yourself
Honestly: Google Directions and Goong Directions are both mature and rock-solid —
if you already pay for one and you're happy, there's no need to switch. GoGoDuk's
edge for this problem is being free forever plus a motorbike routing profile
tuned for Vietnamese roads, so distance (and therefore the fee) matches how riders
actually travel. Note the car profile isn't live yet; if your fleet is cars, wait
for that update.
Wrapping up
The whole formula reduces to: call /v1/directions → read distance.value
(meters) and duration.value (seconds) → feed them into a tiered fee function,
add a time surcharge if you need one, and handle ESTIMATED routes separately.
- Read the Directions API docs.
- Create an API key in the dashboard with the
routing:readscope. - See also the Directions API announcement.
Questions, or want to show off what you built? Join our Telegram support group.
Want to use GoGoDuk?
Free forever — 100 requests/day per account, no credit card. Higher limits on request.
Sign up →