Sacks.ie: DPD Ireland Shipping Integration
Custom WooCommerce plugin booking DPD Ireland shipments and printing labels in bulk for this Irish retailer, replacing a manual, one-parcel-at-a-time process.
Results & Metrics
Outcomes from replacing a manual, one-parcel-at-a-time courier process with a direct integration.
One Button, Every Parcel Booked and Labelled
Sacks Online Ltd run a busy Irish e-commerce store shipping bulk bags and sandbags nationwide, and every parcel meant re-typing a customer’s address into DPD’s portal by hand before printing one label at a time. No existing plugin fit: WooCommerce shipping plugins on the market target DPD UK and DPD Netherlands, entirely different platforms from DPD Ireland’s API, and the only off-the-shelf route was paid middleware sitting between the shop and the courier. Since DPD Ireland’s API is just three endpoints (authorise, create consignment, track), building directly was cheaper and cleaner, and the client owns the result outright with no recurring fee.
What I built
A self-contained WooCommerce plugin providing:
- One-click label creation from the order screen, with parcel count and weight prefilled from the order’s own data
- Bulk label creation and printing: select a batch of orders, create every consignment, and print them all as one job
- A label icon on the orders list showing the consignment number, so a label can be reprinted without opening the order
- Automatic consignment creation on a chosen order status, running in the background so checkout is never delayed
- Customer-facing tracking links on the order and in notification emails
- A test and live environment switch, with the interface making it unmistakable which one is active
The interesting problems
Most of the value in an integration like this isn’t the happy path. It’s the details that quietly produce wrong outcomes months later.
Northern Ireland is not the UK for customs
Northern Ireland addresses arrive in WooCommerce with a GB country code and a BT postcode, and the obvious mapping, GB means UK means a customs declaration, would have been wrong for a large share of orders. Under the Windsor Framework, Ireland to Northern Ireland stays inside the EU customs area for goods, while Ireland to GB mainland doesn’t, so the plugin classifies destinations on postcode as well as country. I verified this against the courier’s live routing rather than the documentation: the test label came back reading “NORTHERN IRELAND” despite the GB code we sent.


A rejected shipment can look exactly like a success
The courier’s API returns HTTP 200 with a status of “OK” even when it has rejected a consignment, with the rejection buried in a per-consignment error field, and the rejected record still carries a tracking number. Reading the tracking number and assuming success would have recorded failed shipments as booked, so the parser checks the overall status, then the per-consignment error, and only then reads the tracking number, covered by tests built from the API’s own rejection samples.
Three more details worth getting right
- The label lives behind a second request. The API returns a URL rather than the label itself, and since that URL arrives inside a response body, it’s validated against the courier’s whole domain before being fetched, guarding against a classic server-side request forgery.
- One special character, one silently deleted field. PHP’s DOMDocument::createElement() parses rather than escapes its value, so a customer trading as “Caffè & Sons Ltd” produced an empty business name element with no error or warning. A test built from hostile input caught it before it reached a real address.
- The label format followed the printer, not the spec. ZPL looked obvious for the warehouse’s Zebra printer until it turned out to be USB-connected to one PC, where a browser can’t push raw ZPL without extra software. The courier’s PDF prints straight through the Windows driver, so batching moved into the plugin instead, merging each run into one multi-page PDF.
Testing
Courier APIs are awkward to develop against: every call is stateful, and on a live account every consignment costs money. A headless test harness runs the plugin’s real classes with WordPress replaced by lightweight stubs, exercising the whole pipeline from the command line against DPD’s pre-production environment, backed by around seventy unit assertions built from the API’s own sample payloads. Credentials stay out of the database in favour of configuration constants, and every logged request is scrubbed of credentials and session tokens.
Built Once, Owned Outright
The warehouse now selects a day's orders, presses one button, and prints every label as a single job, with tracking numbers recorded automatically and no monthly fee standing between the shop and the courier.
More work
MRC Recruiting: Live Job Board Integration
Custom WordPress plugin syncing MRC Recruiting's Recruit CRM postings straight onto their site: a searchable job board, detail pages, and automatic removal of closed roles, with no manual re-entry.
What’s On: Reykjavík Events Platform
Figma design turned into a pixel-accurate WordPress and Elementor build for Reykjavík's event guide since 1994, with a continuously updated events calendar pulled live from an external API.
Iceland Review: Editorial Platform Rebuild
Iceland's leading English-language news portal and travel adviser, rebuilt on WordPress with ad revenue treated as a core requirement from day one, not bolted on afterward.