WordPress powers over 43% of all websites. That's an enormous market for plugin developers — but it also means your code is distributed, inspected, and often improperly distributed. Without proper licensing, you're leaving revenue on the table.
This guide covers everything you need to know about licensing WordPress plugins: how license keys work in the WordPress ecosystem, common unauthorized distribution vectors, and the best strategies for protecting your plugin while keeping the user experience seamless.
Why WordPress Plugin Licensing Matters
Unlike SaaS applications where you control the server, WordPress plugins run on your customer's infrastructure. Once they download your plugin ZIP file, the code is theirs to read, modify, and redistribute. This creates unique challenges:
- Nulled plugins — Modified versions with license checks removed, distributed on unauthorized distribution sites
- Key sharing — One customer shares their license key across dozens of sites
- No update control — Without licensing, you can't gate feature updates or security patches
- Revenue leakage — Studies show 30-60% of premium WordPress plugin installations are unlicensed
How WordPress Plugin License Keys Work
A typical WordPress plugin licensing flow has five components:
- License key generation — Create unique, cryptographically signed keys tied to a purchase
- domain activation — Customer registers their domain against the license key
- Validation endpoint — Your server confirms the key is valid for that domain
- Update gating — Only activated sites receive plugin updates via the WordPress update API
- Feature gating — Premium features require an active, validated license
Domain-Bound Activation
The most effective WordPress licensing approach uses domain-bound activation. When a customer activates your plugin on example.com, that domain is recorded against their license key. If someone tries to use the same key on unauthorized-site.com, the validation fails.
// Example: Activating a license in your WordPress plugin
function activate_license() {
$license_key = get_option('my_plugin_license_key');
$domain = home_url();
$response = wp_remote_post('https://api.trafficorchestrator.com/api/v1/validate', [
'body' => json_encode([
'key' => $license_key,
'domain' => parse_url($domain, PHP_URL_HOST),
'product' => 'my-wordpress-plugin'
]),
'headers' => ['Content-Type' => 'application/json']
]);
$body = json_decode(wp_remote_retrieve_body($response), true);
if ($body['valid']) {
update_option('my_plugin_license_status', 'active');
return true;
}
return false;
}
Update Gating with the WordPress Update API
WordPress checks for plugin updates via the update_plugins transient. By hooking into this system, you can serve updates only to activated installations:
// Hook into WordPress update system
add_filter('pre_set_site_transient_update_plugins', 'check_for_updates');
add_filter('plugins_api', 'plugin_info', 10, 3);
function check_for_updates($transient) {
$license_status = get_option('my_plugin_license_status');
if ($license_status !== 'active') {
return $transient; // No updates for unlicensed installations
}
// Check your update server for new versions
$remote = wp_remote_get('https://api.trafficorchestrator.com/api/v1/updates/check', [
'headers' => [
'X-License-Key' => get_option('my_plugin_license_key'),
'X-Domain' => parse_url(home_url(), PHP_URL_HOST)
]
]);
// ... add update to transient if new version available
return $transient;
}
Common Distribution Control Strategies
1. Server-Side Feature Validation
Instead of just checking a boolean flag, have your premium features call your licensing server. This makes nulling significantly harder — an unauthorized user would need to rewrite your entire feature, not just bypass a conditional check.
2. Integrity Checking
Hash your plugin's critical files and compare against known-good checksums. If the license verification code has been modified, you can detect it:
function verify_plugin_integrity() {
$expected_hash = get_option('my_plugin_integrity_hash');
$actual_hash = md5_file(MY_PLUGIN_FILE);
if ($expected_hash && $expected_hash !== $actual_hash) {
// Plugin files have been modified
deactivate_plugins(MY_PLUGIN_FILE);
wp_die('Plugin integrity check failed. Please reinstall from your account.');
}
}
3. Periodic Re-Validation
Don't just validate once at activation. Schedule periodic checks (daily or weekly) using WordPress cron to verify the license is still valid. This catches expired licenses and revoked keys.
4. Obfuscation (Use Sparingly)
While security through obscurity isn't a strategy, light obfuscation of your license checking code raises the bar for casual unauthorized users. PHP obfuscators like ionCube or SourceGuardian can help, but treat this as a speed bump, not a wall.
Building Your License Key Admin Page
A great licensing UX is crucial for reducing support tickets. Your WordPress admin page should include:
- License key input field with clear status indicators (active, expired, invalid)
- One-click activation/deactivation buttons
- Domain information showing which domain is currently activated
- Remaining activations count (e.g., "2 of 5 sites activated")
- License expiry date with renewal link
- Support link for license issues
Pricing Models That Work
The most successful WordPress plugin licensing models include:
| Model | Best For | Example |
|---|---|---|
| Per-site annual | Most plugins | $49/year for 1 site, $99 for 5, $199 unlimited |
| Lifetime deals | Launch/growth phase | $149 one-time for unlimited sites |
| Freemium | Market penetration | Free core + $79/year pro |
| Tiered features | Complex plugins | Starter/Pro/Agency with increasing features |
Using Traffic Orchestrator for WordPress Licensing
Traffic Orchestrator makes WordPress plugin licensing straightforward with its domain-bound licensing model. Here's what you get out of the box:
- Cryptographic license keys — Ed25519 signed keys that can't be forged
- Domain-bound validation — Keys are tied to specific domains with activation limits
- Sub-10ms validation — Edge-based checks that won't slow down your customer's site
- PHP SDK — Native Composer package for easy integration
- Webhook events — Get notified on activation, deactivation, expiry, and renewal
- Stripe integration — Automatic license provisioning on purchase
Best Practices Checklist
- Always use domain-bound activation — it's the most effective distribution control measure
- Gate updates behind valid licenses — this is your strongest incentive for renewal
- Provide a generous activation limit (3-5 sites) — too restrictive and you'll get chargebacks
- Include a grace period after expiry — don't break customer sites immediately
- Log all activation events — you'll need this data for support and analytics
- Test your licensing on multisite installations — WordPress multisite has unique quirks
- Never store license keys in plaintext in the database — hash them
- Provide clear error messages — "Invalid license" is not helpful; explain WHY
Ready to License Your WordPress Plugin?
Traffic Orchestrator provides everything you need: cryptographic keys, domain-bound validation, update gating, and a PHP SDK. Start free with 5 licenses.
Start Free TodayShip licensing in your next release
5 licenses, 500 validations/month, full API access. Set up in under 5 minutes — no credit card required.