Compatibility
Compatibility
Easy PDF Invoices for WooCommerce is designed to fit into your existing WooCommerce stack without breakage. This page covers what works out of the box, what needs configuration, what's known to work with which third-party plugins, and what doesn't apply.
WooCommerce features
High-Performance Order Storage (HPOS)
Fully compatible. The plugin declares custom_order_tables compatibility on before_woocommerce_init and uses WooCommerce CRUD methods exclusively ($order->get_meta(), $order->update_meta_data()).
There are no get_post_meta() calls on orders, no WP_Query against shop_order post type, no wp_posts joins. Tested with HPOS enabled and disabled.
Block Checkout (Cart and Checkout blocks)
Fully compatible. The plugin declares cart_checkout_blocks compatibility. There's no checkout interaction — the plugin attaches PDFs after order creation, regardless of which checkout the customer used.
Classic Checkout
Works the same as Block Checkout. No special handling needed.
Order status workflows
The plugin hooks into woocommerce_order_status_changed at priority 10 and resolves the document type per status. See Document Types for the full status → document mapping.
Custom order statuses from third-party plugins are handled through the epdi_document_type filter — by default, custom statuses are treated as Invoice unless the order is paid (then Receipt).
Refunds (full and partial)
- Full refund (status moves to refunded) → Credit Note generated automatically.
- Partial refund (refund recorded, status unchanged) → existing document regenerates with refund line item in totals.
customer_refunded_order and customer_partially_refunded_order email IDs.
Coupons and discounts
Discounts appear as line items in the totals section. The template uses $order->get_total_discount() and renders coupon codes if available.
Multi-currency
Each order renders in its own currency through wc_price(). The template passes 'currency' => $order->get_currency() to ensure correct formatting.
Tested with:
- WooCommerce's built-in multi-currency (geo-based pricing).
- WOOCS — WooCommerce Currency Switcher.
- WPML Multi-currency.
- Aelia CurrencySwitcher.
_order_currency), the plugin picks it up automatically.
Taxes
Tax rates appear in the totals section grouped by rate name (e.g., "VAT 20%", "GST 5%"). The plugin uses $order->get_tax_totals() so this matches whatever WooCommerce displays elsewhere.
For stores with multiple tax rates per order, each rate gets its own row.
Inclusive vs exclusive tax
Both supported. The plugin reads wc_prices_include_tax() and renders subtotal/tax accordingly:
- Tax exclusive — subtotal shown, tax shown separately, total = subtotal + tax.
- Tax inclusive — total shown, tax shown as "of which X is tax".
Shipping
Shipping methods appear as their own row in totals. Free shipping renders as "Shipping: Free".
Order item meta
Custom item meta (e.g., from product addons, custom fields, or Subscriptions) is rendered in the items table column. Use the epdi_item_data filter to control which meta keys appear:
add_filter( 'epdi_item_data', function( $data, $item, $order ) {
$data['custom_field'] = $item->get_meta( '_my_custom_field' );
return $data;
}, 10, 3 );
WooCommerce extensions
WooCommerce Subscriptions
Compatible. The plugin's Subscriptions compatibility class hooks wcs_renewal_order_created to strip inherited PDF meta from renewal orders. Each renewal earns a fresh invoice number.
What works:
- Initial subscription order → Invoice / Receipt as expected.
- Renewal orders → fresh number, fresh PDF, attached to renewal email.
- Subscription switch orders → new invoice for the difference.
- Cancelled subscriptions → no documents generated for cancelled orders.
- Failed renewal payments → no documents until payment succeeds.
- The plugin doesn't add per-subscription summary PDFs (e.g., "all payments to date"). This isn't a common request — most accounting systems prefer one PDF per transaction.
WooCommerce Bookings
Compatible. Booking orders are regular orders from the plugin's perspective. The PDF includes booking details if they appear as item meta.
WooCommerce Memberships
Compatible. Membership orders are regular orders. The PDF generates as normal.
WooCommerce Marketplace / Vendors plugins
Mostly compatible but with a caveat: vendor plugins like Dokan, WC Vendors, or WCFM split orders into sub-orders or commission records. The plugin generates one PDF per WooCommerce order ID, so you'll get one parent PDF and one PDF per vendor sub-order if those are stored as separate WC_Order instances.
If your vendor plugin stores commissions as custom posts (not WC orders), the plugin won't generate PDFs for those — that's by design, since commission records aren't customer-facing documents.
WooCommerce Deposits
Compatible. The deposit and remaining balance show as separate line items or totals rows depending on the deposits plugin's data structure.
Action Scheduler
The plugin uses Action Scheduler (bundled with WooCommerce) for bulk operations above 50 orders. We never enqueue Action Scheduler ourselves — we use as_enqueue_async_action() and friends directly.
Monitor queued actions under Tools > Scheduled Actions.
Translation plugins
WPML
Compatible. The plugin hooks epdi_before_generate to call switch_to_locale() based on the order's language meta (wpml_language). After generation, restore_previous_locale() is called via epdi_after_generate.
What this means:
- A French customer's invoice renders in French.
- A German customer's receipt renders in German.
- Static plugin strings translate from the WPML language pack.
- Order item names render in the language they were saved in.
Polylang
Compatible. Same mechanism as WPML — the plugin reads the order's language meta and switches locale.
TranslatePress
Mostly compatible but TranslatePress's translation happens at the output buffer level and may not catch PDF content (PDFs aren't HTML pages). For PDF-specific translations, use the string translation hooks and translate strings directly via the easy-pdf-invoices-for-woocommerce text domain.
Caching plugins
The plugin doesn't add front-end pages, so caching plugins don't affect generation directly. Three caveats:
Object caching (Redis, Memcached)
The plugin's number generator uses database row-level locking (SELECT ... FOR UPDATE) so the lock survives even if the object cache returns stale values. Object caching is fully supported.
Page caching (WP Rocket, W3 Total Cache, etc.)
The download endpoint uses nocache_headers() and Cache-Control: no-cache, must-revalidate so caching plugins should bypass it. If your caching plugin still tries to cache PDF responses, exclude ?epdi_download from the cache rules.
Email caching
The plugin attaches PDFs at email send time. There's no email-level caching to interfere.
Performance plugins
The plugin doesn't add front-end JavaScript or CSS. The only frontend payload is the download endpoint response, which is the PDF binary.
The admin loads:
- 10–15KB of admin CSS, only on the order list, order edit, and settings pages.
- 10–15KB of admin JS, only where needed.
- 10KB of setup wizard JS, only when the wizard is open.
External services
QR Server API (optional, off by default)
The plugin uses the QR Server API to generate QR codes on packing slips when the merchant explicitly enables this in Branding settings.
- Provider: Foundata GmbH (Germany)
- Data sent: the order edit URL (no personal customer information).
- When: only when the QR setting is on AND a packing slip is being rendered.
- Caching: each QR code is cached locally for 12 hours, so repeat printing of the same order doesn't call the API.
- Privacy: goqr.me/de/rechtliches/datenschutz-qrserver.html
- Terms: goqr.me/de/rechtliches
No telemetry
The plugin does not:
- Send usage data to Themology or any other server.
- Phone home on activation, deactivation, or any other event.
- Load assets from any CDN.
- Include analytics, tracking pixels, or fingerprinting code.
- Call Google Fonts, jQuery CDN, or any other external resource.
Hosting environments
Shared hosting
Works on any shared host with PHP 8.1+, WordPress 6.4+, and WooCommerce 8.0+. The plugin's footprint (under 5MB on disk, under 32MB per PDF generation) fits within standard shared hosting limits.
If your shared host disables transactions (rare but possible), the number generator falls back to optimistic compare-and-set with bounded retries. See Numbering for details.
Managed WordPress hosting
Tested on:
- Kinsta, WP Engine, Pantheon, Pressable, Cloudways.
- All work without special configuration.
- Some hosts (e.g., WP Engine) require a writeable directory under
wp-content/uploads/— the plugin uses the standardwp-content/uploads/easy-pdf-invoices/path, which is allowed.
WordPress.com Business+ plans
Compatible. The plugin uses standard WordPress and WooCommerce APIs only.
WordPress multisite
Each site has its own settings, counters, and storage directory. The plugin works in single-site mode within a multisite network — not designed for network-level invoice management.
Headless WooCommerce
The plugin works regardless of whether the storefront is rendered by WordPress or by a headless framework. PDFs are generated server-side based on order data, which is the same in both setups.
The REST API gives headless storefronts programmatic access to invoice metadata and PDF binaries.
Server requirements
PHP
- Minimum: 8.1
- Tested: 8.1, 8.2, 8.3, 8.4
- All files use
declare(strict_types=1);
WordPress
- Minimum: 6.4
- Tested up to: 6.9 (current at time of release)
WooCommerce
- Minimum: 8.0 (HPOS stable release)
- Tested up to: 10.7
MySQL / MariaDB
- Minimum: MySQL 5.7 or MariaDB 10.4 (matches WordPress 6.4 requirements).
- The number generator uses
SELECT ... FOR UPDATEwhich requires InnoDB. Most WooCommerce installs use InnoDB by default.
PHP extensions
mbstring— required for DOMPDF font handling.gdorimagick— recommended for logo handling.zip— required for the bulk download ZIP feature. Falls back gracefully if missing (bulk action is hidden).curl— required for the optional QR Server API call. Falls back towp_remote_get()if cURL isn't available.
What doesn't apply
Email service plugins (SendGrid, Mailgun, Postmark, etc.)
The plugin attaches PDFs to WooCommerce emails via the woocommerce_email_attachments filter. WooCommerce then hands the email to whatever email provider plugin is active. The PDF rides along as a normal MIME attachment.
If your provider strips attachments above a certain size, switch to Settings > Invoices > Emails > Attachment method: Link to send a download link instead.
Backup plugins
PDFs are stored in wp-content/uploads/easy-pdf-invoices/. Standard backup plugins (UpdraftPlus, BlogVault, Jetpack Backup, etc.) include them in scheduled backups.
Order meta is stored in WooCommerce's order tables (HPOS) or the standard _postmeta table (legacy). Both are included in standard database backups.
Migration plugins
When migrating between sites, both the PDFs (filesystem) and order meta (database) need to come along. The plugin doesn't store any data outside of these standard locations, so any decent migration plugin handles it correctly.
The PDF storage path is relative — moving to a new domain doesn't break existing URLs since downloads are routed through the dynamic endpoint, not direct file URLs.
Reporting compatibility issues
If you find a third-party plugin that doesn't play nicely with Easy PDF Invoices, please open a support ticket with:
- Plugin name and version.
- Easy PDF Invoices version.
- WooCommerce, WordPress, and PHP versions.
- Steps to reproduce.
- Any errors from WooCommerce > Status > Logs (source:
easy-pdf-invoices).
Related
- Document Types — how the plugin handles order statuses.
- Settings Reference — every setting documented.
- Developer Guide — extensibility for advanced integrations.