# Woocommerce

> This skill should be used when the user asks to "create a WooCommerce plugin", "build a WooCommerce extension", "develop a WooCommerce payment gateway", "add WooCommerce shipping method", "extend WooCommerce checkout", "customize WooCommerce admin", "use WooCommerce hooks", "WooCommerce REST API", "publish to WordPress.org", or needs guidance on WordPress/WooCommerce plugin development. Covers plugin architecture, hooks/filters, REST API, Blocks, HPOS compatibility, and marketplace publishing.

- Skill: `biggora/woocommerce` (Agent Skill, multi-file: 13 files)
- Install (CLI): `npx skillmds@latest add biggora/woocommerce`
- Raw SKILL.md: https://api.skillmd.com/api/skills/biggora/woocommerce/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: biggora (https://skillmd.com/u/biggora)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/biggora/woocommerce

---


# WooCommerce Plugin Development

## Overview

WooCommerce is an open-source e-commerce plugin for WordPress, powering over 36% of all online stores. It transforms a WordPress installation into a fully functional e-commerce platform with product management, cart, checkout, payment processing, shipping, and order management.

WooCommerce follows the WordPress extension model -- plugins extend core functionality through a hook-based architecture. WooCommerce adds its own extensive layer of hooks, filters, REST API endpoints, and abstract classes on top of WordPress's plugin system. Extensions can add payment gateways, shipping methods, product types, checkout fields, admin pages, reporting dashboards, and storefront modifications.

The platform has evolved significantly with the introduction of High-Performance Order Storage (HPOS), block-based checkout, and the WooCommerce Admin React-based interface. Modern WooCommerce plugin development must account for these architectural shifts while maintaining backward compatibility with classic implementations.

WooCommerce plugins are distributed through the WordPress.org plugin directory (free), the WooCommerce.com marketplace (premium), or independently through developer websites. All distribution channels require GPL-compatible licensing. The WordPress.org review process enforces security standards, coding quality, and adherence to plugin guidelines.

## Plugin Structure

Every WooCommerce plugin starts with a main PHP file containing the WordPress plugin header. WooCommerce-specific headers declare version compatibility:

```php
<?php
/**
 * Plugin Name: My WooCommerce Plugin
 * Plugin URI: https://example.com/my-woo-plugin
 * Description: A brief description of the plugin.
 * Version: 1.0.0
 * Author: Developer Name
 * Author URI: https://example.com
 * License: GPL-2.0-or-later
 * Text Domain: my-woo-plugin
 * Domain Path: /languages
 * Requires at least: 6.0
 * Requires PHP: 7.4
 * WC requires at least: 8.0
 * WC tested up to: 9.4
 * Woo: 12345:abc123def456
 */
```

The `WC requires at least` and `WC tested up to` headers tell WooCommerce which versions the plugin supports. The `Woo` header is required for plugins sold on WooCommerce.com marketplace.

### Activation and Dependency Checks

Before initializing, verify that WooCommerce is active. Hook into `plugins_loaded` to check for the `WooCommerce` class, and display an admin notice if WooCommerce is missing. Never call WooCommerce functions at the top level of the plugin file -- always wait for the `woocommerce_loaded` action.

### HPOS Feature Declaration

All new plugins must declare HPOS compatibility. Without this declaration, WooCommerce displays a compatibility warning in the admin:

```php
add_action('before_woocommerce_init', function () {
    if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
            'custom_order_tables', __FILE__, true
        );
    }
});
```

For full plugin structure details including autoloading, directory layout, and initialization patterns, see [references/architecture.md](references/architecture.md).

## Hook System

WooCommerce's hook system is the primary mechanism for extending functionality. It builds on WordPress's core `add_action()` and `add_filter()` API.

### Actions vs Filters

- **Actions** execute code at specific points in the WooCommerce lifecycle (order created, payment processed, email sent). They do not return values.
- **Filters** modify data as it passes through the system (change product price, alter checkout fields, modify email content). They receive a value and must return it (modified or not).

### Priority System

Hooks accept a priority parameter (default 10). Lower numbers execute first. Use priorities strategically:

- **1-9** -- Execute before most other plugins.
- **10** -- Default priority. Most plugins use this.
- **11-99** -- Execute after most plugins. Useful for overriding other plugin behavior.
- **100+** -- Execute last. Use for final modifications.

### Critical WooCommerce Hooks

The most commonly used hooks fall into categories:

| Category | Key Hooks |
|----------|-----------|
| Product | `woocommerce_product_options_general_product_data`, `woocommerce_process_product_meta` |
| Cart | `woocommerce_add_to_cart`, `woocommerce_cart_calculate_fees`, `woocommerce_before_calculate_totals` |
| Checkout | `woocommerce_checkout_process`, `woocommerce_checkout_order_processed`, `woocommerce_checkout_create_order` |
| Order | `woocommerce_new_order`, `woocommerce_order_status_changed`, `woocommerce_payment_complete` |
| Admin | `woocommerce_admin_order_data_after_billing_address`, `woocommerce_product_data_tabs` |
| Email | `woocommerce_email_before_order_table`, `woocommerce_email_order_details` |

For a comprehensive categorized list with code examples, see [references/hooks-and-filters.md](references/hooks-and-filters.md).

## Development Setup

### Local WordPress Environments

Several tools provide local WordPress development environments:

- **LocalWP** (Local by Flywheel) -- GUI-based, one-click WordPress setup with SSL, mailbox, and live link sharing. Recommended for beginners.
- **wp-env** -- Official WordPress Docker-based environment. Define configuration in `.wp-env.json` and run `npx @wordpress/env start`. Ideal for CI/CD.
- **DDEV** -- Docker-based PHP development environment with WordPress recipes.
- **VVV** (Varying Vagrant Vagrants) -- Vagrant-based, heavier but highly configurable.

### WP-CLI

WP-CLI is the command-line interface for WordPress. Essential commands for WooCommerce development:

```bash
wp plugin activate my-woo-plugin
wp wc product list --user=admin
wp wc order create --customer_id=1 --user=admin
wp option get woocommerce_default_country
wp transient delete --all
```

### WooCommerce Beta Tester

Install the WooCommerce Beta Tester plugin to test against upcoming WooCommerce releases. This catches compatibility issues before they reach production stores. Enable beta updates in WooCommerce > Settings > Advanced > WooCommerce.com and select the desired release channel (beta, release candidate, or nightly).

### Debug Configuration

Enable WordPress debug mode in `wp-config.php`:

```php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
define('SCRIPT_DEBUG', true);
```

Use `wc_get_logger()` for structured logging within WooCommerce context. Log files appear under `wp-content/uploads/wc-logs/` and are viewable in WooCommerce > Status > Logs.

### Recommended Developer Tools

- **Query Monitor** -- WordPress debugging plugin that shows database queries, hooks fired, HTTP requests, and PHP errors. Invaluable for identifying performance bottlenecks and hook execution order.
- **WooCommerce Admin Test Helper** -- Reset WooCommerce admin features and onboarding states for testing.
- **Code Snippets** -- Test hook callbacks and filters without creating a full plugin.
- **Debug Bar** -- Inspect WordPress internals, including cache hits and conditional functions.

For testing strategies including PHPUnit setup, E2E tests, and mocking patterns, see [references/testing.md](references/testing.md).

## Key Integration Patterns

| Pattern | Base Class | Key Method(s) | Reference |
|---------|-----------|----------------|-----------|
| Payment Gateway | `WC_Payment_Gateway` | `process_payment()`, `init_form_fields()` | [payment-gateway.md](references/payment-gateway.md) |
| Shipping Method | `WC_Shipping_Method` | `calculate_shipping()`, `init_form_fields()` | [shipping-method.md](references/shipping-method.md) |
| Product Type | `WC_Product` | `get_type()`, custom data stores | [architecture.md](references/architecture.md) |
| Checkout Blocks | `IntegrationInterface` | `get_script_handles()`, `get_script_data()` | [storefront-and-blocks.md](references/storefront-and-blocks.md) |
| Admin Settings | `WC_Integration` | `init_form_fields()`, `process_admin_options()` | [admin-extension.md](references/admin-extension.md) |
| REST Endpoint | `WC_REST_Controller` | `register_routes()`, `get_items()` | [rest-api.md](references/rest-api.md) |

Each integration pattern follows the same lifecycle: extend the abstract class, implement required methods, register with WooCommerce via the appropriate hook. WooCommerce discovers registered extensions through specific filter hooks -- `woocommerce_payment_gateways` for gateways, `woocommerce_shipping_methods` for shipping, and `woocommerce_integrations` for settings integrations. The registration hook fires during WooCommerce initialization, so the plugin must be loaded before that point.

For headless and external integrations, WooCommerce provides two REST APIs. The WC REST API v3 handles administrative operations (managing products, orders, customers) with consumer key/secret authentication. The Store API serves the block-based cart and checkout with session-based authentication. See [references/rest-api.md](references/rest-api.md) for endpoint details, custom controller creation, and webhook configuration.

## HPOS Compatibility

High-Performance Order Storage (HPOS) replaces the WordPress `wp_posts` and `wp_postmeta` tables with dedicated WooCommerce order tables. This dramatically improves query performance for stores with large order volumes.

### Key Rules for HPOS Compatibility

1. **Never access `wp_posts` or `wp_postmeta` directly for order data.** Use the WooCommerce CRUD API (`$order->get_meta()`, `$order->update_meta_data()`).
2. **Never use `get_post_meta()` or `update_post_meta()` on order IDs.** These bypass HPOS entirely.
3. **Use `OrderUtil::get_order_type()` to determine if an ID is an order**, not `get_post_type()`.
4. **Query orders with `wc_get_orders()`**, not `WP_Query` or direct SQL.
5. **Declare HPOS support** in the plugin header via `FeaturesUtil::declare_compatibility()`.

```php
// Correct: HPOS-compatible order meta access
$order = wc_get_order($order_id);
$custom_value = $order->get_meta('_my_custom_field');
$order->update_meta_data('_my_custom_field', 'new_value');
$order->save();

// Wrong: Direct post meta (breaks HPOS)
$custom_value = get_post_meta($order_id, '_my_custom_field', true);
update_post_meta($order_id, '_my_custom_field', 'new_value');
```

## WooCommerce Blocks

WooCommerce Blocks provide a modern, block-based cart and checkout experience built with React. The block-based checkout is now the default for new WooCommerce installations.

### Extending Block Checkout

Register a checkout block integration by implementing `Automattic\WooCommerce\Blocks\Integrations\IntegrationInterface`:

```php
use Automattic\WooCommerce\Blocks\Integrations\IntegrationInterface;

class My_Blocks_Integration implements IntegrationInterface {
    public function get_name() { return 'my-plugin'; }
    public function initialize() { /* register scripts */ }
    public function get_script_handles() { return ['my-plugin-checkout-block']; }
    public function get_editor_script_handles() { return []; }
    public function get_script_data() { return ['ajaxUrl' => admin_url('admin-ajax.php')]; }
}
```

On the JavaScript side, use the `@woocommerce/blocks-checkout` package to register components in checkout slots:

```javascript
import { registerCheckoutBlock } from '@woocommerce/blocks-checkout';

registerCheckoutBlock({
    metadata: { name: 'my-plugin/custom-field', parent: ['woocommerce/checkout-fields-block'] },
    component: MyCustomFieldBlock,
});
```

### Store API

The WooCommerce Store API serves block-based cart and checkout. Extend it to expose custom data to checkout blocks. Use `ExtendSchema` to add data to cart/checkout API responses and `register_endpoint_data` to attach custom schemas.

For complete block integration patterns, see [references/storefront-and-blocks.md](references/storefront-and-blocks.md).

## Anti-Patterns

Avoid these common mistakes in WooCommerce plugin development:

### Direct Database Access for Orders

Never query `$wpdb->posts` or `$wpdb->postmeta` for order data. This breaks HPOS compatibility and bypasses WooCommerce's data layer, cache, and hooks.

### Bypassing WooCommerce CRUD API

Always use `$order->get_total()`, `$order->get_billing_email()`, `$product->get_price()` instead of accessing internal properties or post meta directly. The CRUD methods handle data stores, caching, and format conversions.

### Hardcoding URLs

Never hardcode site URLs, asset URLs, or API endpoints. Use `plugins_url()`, `admin_url()`, `wc_get_endpoint_url()`, and `rest_url()` to generate URLs dynamically.

### Ignoring Nonce Verification

All form submissions and AJAX requests must verify WordPress nonces with `wp_verify_nonce()` or `check_ajax_referer()`. Skipping nonce verification opens the plugin to CSRF attacks.

### Loading Assets Everywhere

Enqueue scripts and styles only on pages where they are needed. Use `is_checkout()`, `is_cart()`, `is_product()`, and similar conditional functions to target specific pages.

### Ignoring Block Checkout

Plugins that only support classic checkout (shortcode-based) are increasingly incompatible with new installations. Support both classic and block checkout flows.

### Modifying Orders via Direct SQL

Never run `UPDATE` or `INSERT` queries against `wp_posts`, `wp_postmeta`, or the HPOS tables (`wp_wc_orders`, `wp_wc_orders_meta`) directly. Use `wc_get_order()` to retrieve orders and the CRUD methods to modify them. Direct SQL bypasses validation, caching, and hook triggers, leading to data inconsistency.

### Not Sanitizing or Escaping

All user input flowing into the database must pass through sanitization functions (`sanitize_text_field()`, `absint()`, `sanitize_email()`). All output rendered in HTML must be escaped (`esc_html()`, `esc_attr()`, `esc_url()`, `wp_kses_post()`). Skipping sanitization or escaping is the most common reason for plugin rejection on WordPress.org.

### Shipping and Tax Assumptions

Never assume a store uses a specific currency, tax mode, or shipping structure. Use WooCommerce helper functions (`get_woocommerce_currency()`, `wc_tax_enabled()`, `wc_prices_include_tax()`) to query the store configuration. Hardcoded assumptions break internationalization.

## Data Handling and CRUD

WooCommerce provides a CRUD (Create, Read, Update, Delete) abstraction for all core data types. Use these APIs instead of direct WordPress functions:

| Object | Retrieve | Query |
|--------|----------|-------|
| Product | `wc_get_product($id)` | `wc_get_products($args)` |
| Order | `wc_get_order($id)` | `wc_get_orders($args)` |
| Customer | `new WC_Customer($id)` | `get_users($args)` |
| Coupon | `new WC_Coupon($code)` | `wc_get_orders(['type' => 'shop_coupon'])` |

All CRUD objects share the same meta API:

```php
$object->get_meta('_key');              // Read
$object->update_meta_data('_key', $v);  // Write (in memory)
$object->save();                        // Persist to database
$object->delete_meta_data('_key');      // Remove
```

Always call `$object->save()` after modifying data. Meta changes are batched in memory until saved, which reduces database writes.

For detailed architecture including autoloading, custom tables, template overrides, and WP-CLI commands, see [references/architecture.md](references/architecture.md).

## Reference Files

- [Architecture](references/architecture.md) -- Plugin file structure, autoloading, headers, HPOS declaration, activation hooks, settings registration
- [Hooks and Filters](references/hooks-and-filters.md) -- Complete categorized hook reference with code examples and priority system
- [REST API](references/rest-api.md) -- WC REST API v3, authentication, custom endpoints, Store API, batch operations
- [Admin Extension](references/admin-extension.md) -- Settings tabs, product data panels, order meta boxes, WooCommerce Admin pages
- [Storefront and Blocks](references/storefront-and-blocks.md) -- Block checkout extensions, Store API, template overrides, product page customization
- [Checkout and Cart](references/checkout-and-cart.md) -- Checkout field customization, cart fees, validation, block checkout integration
- [Payment Gateway](references/payment-gateway.md) -- WC_Payment_Gateway extension, tokenization, refunds, 3D Secure, webhook handling
- [Shipping Method](references/shipping-method.md) -- WC_Shipping_Method extension, rate calculation, shipping zones, tracking integration
- [Testing](references/testing.md) -- PHPUnit setup, WC test helpers, E2E testing, WP-CLI testing, debug logging
- [Publishing](references/publishing.md) -- WordPress.org submission, readme.txt format, SVN workflow, WooCommerce.com marketplace

## Example Files

- [Basic Plugin](examples/basic-plugin/my-woo-plugin.php) -- Minimal complete WooCommerce plugin with HPOS support, dependency check, and settings page
- [Payment Gateway](examples/payment-gateway/class-wc-gateway-example.php) -- Payment gateway skeleton with form fields, payment processing, webhooks, and refund support

