Learn to build a secure Licensing infrastructure for your WordPress plugin. Implement remote verification, manage activation states, and prevent unauthorized use.
Previously in this course, we covered Internationalization (i18n) to ensure our plugin reaches a global audience. Now that your plugin is ready for the world, you need a way to protect your intellectual property and monetize your work.
Implementing robust Licensing for a WordPress plugin is as much about Security as it is about SaaS business logic. You aren't just checking a string; you are establishing a trust relationship between your server and your user's site.
At its core, a licensing system requires three distinct components:
wp_options table.When a user enters their key, your plugin must perform a secure POST request to your licensing server.
Sequence diagram: participant U as User Site; participant S as Licensing Server; U → S: POST /activate key, site_url; S → S: Validate key/limit; S → U: JSON Response status, expiry, token; U → U: Store encrypted response
We avoid querying the remote server on every page load. Instead, we store the license status in wp_options and use a transient to cache the remote validation result.
We will create a LicenseManager class. This class handles the logic of storing the key and verifying it against your remote API.
PHPnamespace KnowledgeBase\Licensing; class LicenseManager { private const OPTION_KEY = 'kb_license_data'; public function activate(string $key, string $site_url): array { $response = wp_remote_post('https:#6A9955">//api.your-saas.com/v1/activate', [ 'body' => [ 'key' => $key, 'url' => $site_url, ], 'timeout' => 15, ]); if (is_wp_error($response)) { return ['status' => 'error', 'message' => 'Connection failed.']; } $data = json_decode(wp_remote_retrieve_body($response), true); if ($data['success']) { update_option(self::OPTION_KEY, [ 'key' => $key, 'status' => 'active', 'expires' => $data['expires'] ]); return ['status' => 'success']; } return ['status' => 'invalid', 'message' => 'Invalid license key.']; } public function is_active(): bool { $data = get_option(self::OPTION_KEY); return isset($data['status']) && $data['status'] === 'active'; } }
To ensure this is secure, your activation flow must prevent "key sharing." When the activation request reaches your server, you should store the home_url() of the requester. If the same key is activated on ten different domains, your server should return an error.
Security Considerations:
wp_options table is compromised.src/Licensing/LicenseManager.php in your plugin.LicenseManager::activate() method.is_active() check before rendering premium features.We've built a foundation for a Licensing system that leverages wp_options for local state and a remote API for validation. By integrating this with your Advanced Admin Dashboards, you provide a professional experience for your users while keeping your SaaS infrastructure secure.
Up next: Automated Update API — we will learn how to hook your custom licensing status into the WordPress Update API to deliver one-click updates to your paying customers.
Master advanced Nonce Security in WordPress. Learn to rotate, bind, and audit tokens for high-security operations and prevent CSRF replay attacks.
Read moreMaster secure file handling in WordPress. Learn to validate file types, sanitize filenames, and implement secure storage paths to prevent RCE and traversal.
Licensing Infrastructure
Custom Hooks for React