If a customer types a PO Box (or APO/FPO/DPO) as the shipping address, UPS and FedEx won't deliver. The cleanest fix is to automatically hide all non-USPS rates whenever a PO Box is detected. You can do this with a tiny, safe, copy-paste "must-use" plugin — no paid plugins required.

Why This Matters

  • USPS delivers to PO Boxes.
  • UPS/FedEx do not — you'll get delivery failures, manual re-shipments, or angry emails.
  • Many stores leave all carriers visible, which confuses customers and creates support headaches.

The goal: If PO Box → only show USPS. Easy for the customer, safe for you.

Do You Need This?

Check these quick signs:

  • You see orders with "PO Box" in the shipping address.
  • You've had delivery failures because a non-USPS service was chosen for a PO Box.
  • You want to prevent mistakes instead of catching them after the label prints.

If that's you, keep reading — this takes 5 minutes.

The Fast, Free Solution (No Coding Skills Required)

We'll add a tiny "must-use" (MU) plugin. MU plugins are just PHP files you drop into a folder — no settings screen, no updates to break it, and you can delete it anytime.

Step 1 — Open your site files
Go to your hosting File Manager (or SFTP) and navigate to: wp-content/

Step 2 — Create the MU plugins folder (if it doesn't exist)
Create a folder named: mu-plugins

Step 3 — Create a new file
Inside mu-plugins, create ccms-po-box-filter.php

Step 4 — Copy-paste this code and save

<?php
/**
 * Plugin Name: CCMS – PO Box filter (USPS-only)
 * Description: If the ship-to address is a PO Box (incl. APO/FPO/DPO), remove all non-USPS rates.
 * Version: 1.0.0
 * Author: CCMS
 */

add_filter('woocommerce_package_rates', function ($rates, $package) {
    $is_po_box = (function(array $dest): bool {
        $fields = [];
        foreach (['address_1','address_2','company'] as $k) {
            if (!empty($dest[$k])) $fields[] = (string)$dest[$k];
        }
        if (!$fields) return false;
        $hay = strtolower(trim(preg_replace('/\s+/', ' ', implode(' ', $fields))));
        $norm = preg_replace('/[\.#,\-]/', ' ', $hay);
        $norm = preg_replace('/\s+/', ' ', $norm);
        $patterns = [
            '/\b(p\s*\.?\s*o\s*\.?\s*|po\s+|p\s+o\s+)(box|bx)\b/i',
            '/\bpost\s+office\s+box\b/i',
            '/\b(p\s*\.?\s*o\s*\.?\s*b(?:ox)?)\b/i',
            '/\b(apo|fpo|dpo)\b/i',
        ];
        foreach ($patterns as $rx) {
            if (preg_match($rx, $norm)) return true;
        }
        return false;
    })($package['destination'] ?? []);
    if (!$is_po_box) return $rates;
    foreach ($rates as $id => $rate) {
        $label = method_exists($rate,'get_label') ? $rate->get_label() : ($rate->label ?? '');
        $lab = strtolower((string)$label);
        $is_usps = (strpos($lab,'usps') !== false) || (strpos($lab,'stamps.com') !== false);
        if (!$is_usps) { unset($rates[$id]); continue; }
    }
    return $rates;
}, 1200, 2);

That's it. When a PO Box is present, checkout will show USPS-only. For normal addresses, nothing changes.

How to Test

  1. Go to checkout and use a test address: Address 1: P.O. Box 123
  2. Check the shipping methods: only USPS should show.
  3. Switch Address 1 to a normal street (e.g., 123 Main St) and re-calculate: UPS/FedEx should reappear.

If something looks off, just delete the file — everything goes back to normal.

FAQs

Will this break APO/FPO/DPO military addresses?
No — those are treated like PO Boxes and will see USPS-only options, which is correct.

What about hybrid services (like "Ground Saver" / "SmartPost")?
Those aren't reliable for PO Boxes in standard Woo setups. Hiding non-USPS across the board for PO Boxes is the safest choice.

Can I undo this easily?
Yes. Delete ccms-po-box-filter.php from mu-plugins.

Will this conflict with my other shipping rules?
No. The filter runs after most rules (priority 1200) and only removes non-USPS when a PO Box is detected.