WordPress / WooCommerce Custom PHP Development Business Automation

Automated Invoice
Reminder System — Zero Plugins. Pure Code.

A wholesale distribution client needed WooCommerce to automatically chase unpaid orders with three professionally timed emails. The constraint was firm: no third-party plugins. I engineered the entire system from scratch — hooks, scheduler, HTML email templates, and admin UI included.

Client explicitly required: No third-party plugins allowed — every feature had to be built from scratch using WordPress and WooCommerce core only.

Problem & Solution

The client's WooCommerce store was losing revenue to unpaid orders with no follow-up mechanism. Every plugin solution was off the table — they needed a clean, custom-coded system they owned outright.

The Challenge

WooCommerce has no native payment chase system. Pending orders were expiring silently — no follow-up, no urgency, no revenue recovery process in place.

  • Zero automated payment follow-up of any kind
  • Unpaid orders abandoned without any communication
  • All plugin solutions were explicitly ruled out by the client
  • System must self-cancel the moment payment is received
  • Emails required professional branding, not generic WooCommerce templates

The Solution

I used WooCommerce's already-bundled Action Scheduler — a production-grade background job queue — to schedule and fire all three reminder jobs with precision timing and zero plugin overhead.

  • 3 escalating reminders at 24h, 96h and 144h
  • Immediately cancelled on any status change from pending
  • Post-meta flags prevent any duplicate sends
  • Re-pending orders handled cleanly — fresh cycle starts
  • Admin test buttons + live status panel on every order
⚠️

Why "No Plugins" Is the Harder — and Better — Choice

Any developer can reach for a plugin. Building a custom automation from first principles — understanding WordPress hooks, leveraging WooCommerce internals, handling every edge case in code — that is engineering. The client now owns a leaner system with zero licensing costs, zero plugin conflicts, and complete control over the logic forever.


Three-Stage Email Sequence

Each email escalates in urgency and tone — a friendly nudge at day 1, a firm notice at day 4, and a final void warning at day 6. All three are cancelled the instant the order is paid.

1
24 Hours After Order Goes Pending
Day 1

Friendly Payment Reminder

A polite, professionally branded reminder that an invoice is awaiting payment. Assumes the customer may have simply forgotten. Includes full invoice summary, amount due, issued date, and direct contact via email and WhatsApp.

📧 Subject: Invoice #XXX is 1 Day Past Due Tone: Professional & Friendly WhatsApp + Email link
2
96 Hours (4 Days) After Order Goes Pending
Day 4

Payment Past Due — Action Required

Elevated urgency with a prominent "Action Required" badge. Introduces a dedicated resolution channel for customers experiencing payment difficulties — reducing genuine abandonment while applying the right pressure on intentional non-payers.

📧 Subject: Invoice #XXX is 4 Days Past Due Tone: Firm Difficulty resolution offer
3
144 Hours (6 Days) After Order Goes Pending
Day 6 — Final

Final Notice — Invoice to Be Voided

The final and most urgent message. Clearly states the invoice will be voided without immediate action and warns of account standing implications for repeat non-payment. No further automated emails are sent after this stage.

📧 Subject: Final Notice — Invoice #XXX Tone: Urgent Void warning + account notice

How It Works Under the Hood

Every edge case is handled in code — re-pending orders, duplicate job runs, cancelled orders and admin testing all work flawlessly without any developer intervention after deployment.

01

Order status changes to "Pending Payment"

WooCommerce fires the woocommerce_order_status_changed hook. The system detects the "pending" new status, clears any previous reminder flags to cleanly handle re-pending edge cases, then immediately schedules all three background jobs into Action Scheduler's queue.

02

Action Scheduler processes each job in the background

Using WooCommerce's bundled Action Scheduler — the same engine WooCommerce uses internally for its own jobs — each reminder fires in an isolated background HTTP request. Completely independent of user page loads. No unreliable WP-Cron visitor-trigger dependency.

03

Real-time send guard validates state at fire time

The moment a job fires, the dispatcher performs two checks: is the order still pending? Has this reminder already been sent? Only if both conditions pass does the email go out — eliminating duplicate sends even if Action Scheduler retries a job.

04

Payment received — all queued jobs cancelled instantly

A second hook listener watches for any status transition away from pending. The moment an order becomes processing, on-hold, completed or cancelled, all three queued reminder actions are removed from the Action Scheduler queue via as_unschedule_action — immediately and automatically.

05

Admin panel: live reminder status + manual test triggers

Each pending order's edit page displays a live status widget showing which reminders have fired (with exact timestamps) and which are queued (with countdown). Dedicated order action buttons allow any reminder to be manually triggered for QA testing without touching a line of code.

Core scheduling logic — the moment an order goes pending, three precisely timed background jobs are queued:

order-reminders.php
// Fires on every order status transition
add_action( 'woocommerce_order_status_changed', 'schedule_reminder_emails', 10, 4 );

function schedule_reminder_emails( $order_id, $old_status, $new_status, $order ) {

    // Only act when transitioning TO pending
    if ( $new_status !== 'pending' ) return;

    // Clear any existing scheduled jobs + sent flags (handles re-pending edge case)
    cancel_reminder_emails( $order_id );
    delete_post_meta( $order_id, '_reminder_1_sent' );
    delete_post_meta( $order_id, '_reminder_2_sent' );
    delete_post_meta( $order_id, '_reminder_3_sent' );

    $args = [ 'order_id' => $order_id ];

    // Queue Reminder 1 — fires 24 h after pending status is set
    as_schedule_single_action( time() + ( 24 * HOUR_IN_SECONDS ),  'reminder_email_1', $args );

    // Queue Reminder 2 — fires 96 h (4 days) after pending status is set
    as_schedule_single_action( time() + ( 96 * HOUR_IN_SECONDS ),  'reminder_email_2', $args );

    // Queue Reminder 3 — fires 144 h (6 days) after pending status is set
    as_schedule_single_action( time() + ( 144 * HOUR_IN_SECONDS ), 'reminder_email_3', $args );
}

Stack & Approach

No unnecessary dependencies. Every tool used is either native to WordPress, bundled with WooCommerce, or standard PHP — making this system maintenance-free and future-proof.

⚙️

Action Scheduler

WooCommerce's production-grade background job processor. Battle-tested at millions of jobs — far more reliable than WP-Cron for time-sensitive email delivery.

🪝

WooCommerce Hooks

Custom filter and action callbacks hooked to woocommerce_order_status_changed for real-time scheduling and instant job cancellation on payment.

📧

wp_mail + HTML Templates

Three fully custom HTML email templates — one per reminder stage — with correct urgency escalation, brand colours, and structured invoice detail layouts.

🛡️

Post Meta State Flags

Idempotency guards stored as order post meta ensure no reminder is ever sent twice — even if Action Scheduler retries a failed job or the order re-enters pending.

🔧

WooCommerce Order Actions

Custom entries injected into the WooCommerce order action dropdown allow any reminder to be triggered manually for QA — no custom admin page required.

📊

Live Admin Status Panel

A status widget on every pending order page displays exactly which reminders have fired (with timestamps) and which are queued with time remaining.


What the Client Got

A fully autonomous payment recovery system running silently in the background — 100% custom-built, zero ongoing maintenance, zero recurring costs, and complete code ownership.

Fully Automated Cash Flow Recovery

Every pending order is now automatically chased at the right time with the right urgency — without any manual work from the client ever.

🔒

Zero Plugin Dependency

No licences to renew, no plugin update conflicts to manage, and no third-party servers ever handling sensitive customer order data.

Every Edge Case Handled

Re-pending orders, duplicate job runs, simultaneous status changes — every scenario was anticipated and guarded against in the initial build, in code.

🎨

Professional Branded Emails

Three custom HTML email templates far beyond WooCommerce defaults — branded, responsive, with escalating urgency designed to convert at each stage.

"My client came with a hard constraint — no plugins, make it reliable, make it look professional. That's exactly the kind of engineering problem I enjoy. The result is a system that requires zero maintenance and will keep recovering revenue for their business indefinitely."

Muhammad Abdullah Hashmi  ·  Full-Stack WordPress, WooCommerce & PHP Developer  ·  8 Years Experience

Available for New Projects

Have a similar challenge?

I specialise in custom WordPress, WooCommerce and PHP solutions built exactly to your business requirements — without the plugin bloat or recurring licence costs.