For thirty years, hardware dongles were the gold standard of software protection. A USB device plugged into a port, a challenge-response handshake, and the software unlocked. They worked — until they didn’t. Lost dongles meant locked-out customers. Shipping physical devices to a global customer base meant logistics overhead that had nothing to do with software. And in a world where software increasingly runs in browsers, on servers, and inside containers, there’s no USB port to plug into. Domain-bound licensing is the evolution: tie the license to a domain instead of a device, validate at the edge in under 10ms, and eliminate the entire hardware layer.
What Is Domain-Bound Licensing?
Domain-bound licensing ties a software license key to one or more specific internet domains. Instead of validating against a physical device or machine fingerprint, the software checks whether the domain it’s running on matches the license record. If the domain is authorized, the software activates. If not, it refuses to run or falls back to a limited mode.
This model is purpose-built for software that runs in web contexts:
- WordPress premium plugins — License keys bound to the customer’s WordPress site domain
- JavaScript libraries and UI components — License validation runs in the browser against
window.location.hostname - SaaS embeds and widgets — Third-party scripts that should only run on authorized customer domains
- White-label products — Each reseller’s domain gets its own license scope
- Web-based enterprise tools — Internal tools deployed to company domains with per-domain licensing
The license-to-domain binding is stored server-side. The license_domains record maps each license key to its authorized domains, and the validation API checks this mapping on every request.
Use Cases
WordPress and CMS Plugins
The WordPress plugin ecosystem has 60,000+ plugins, and every premium plugin needs a licensing mechanism. Domain-bound licensing is the natural fit: each customer’s WordPress site has a unique domain, and the license key validates against it. When a customer buys a “single-site license,” that means one domain. A “5-site license” means five domains. The model maps directly to how customers think about their purchases.
Shopify and E-Commerce Apps
Shopify apps run on merchant stores, each with a unique *.myshopify.com subdomain or custom domain. Domain-bound licensing lets app developers control distribution per store without relying on Shopify’s built-in billing for all licensing logic.
Web-Based Enterprise Tools
Enterprise software deployed to internal domains (tools.acme-corp.com) validates against the corporate domain. When the contract covers multiple subsidiaries, each subdomain or domain gets added to the license. No VPN-based access controls needed — the license itself enforces the boundary.
Agency White-Label Distribution
Agencies resell software under their clients’ brands. Each client gets a domain-bound license for their specific domain. The agency manages a pool of licenses, activating and transferring them as client relationships change.
Multi-Tenant SaaS Add-Ons
SaaS platforms that offer marketplace add-ons can use domain-bound licensing to ensure each tenant’s add-on only runs on their designated subdomain. A tenant on acme.platform.com can’t share their add-on license with other.platform.com.
How Domain-Bound Validation Works
The validation flow has four steps, and the entire round trip completes in under 10ms when the validation runs at the edge:
- Extract the domain — The client software reads the current hostname. In a browser, that’s
window.location.hostname. In PHP, it’s$_SERVER['HTTP_HOST']. In Node.js, it’s theHostheader from the incoming request. - Send the validation request — The software sends the license key and domain to the validation API:
POST /api/v1/licenses/validatewith{ key, domain }. - Server-side domain check — The API looks up the license key, retrieves its authorized domains from the
license_domainstable, and checks whether the submitted domain matches any of them. Wildcard and subdomain matching are applied automatically. - Response with entitlements — The API returns the validation result including the license status, plan tier, feature entitlements, and expiration date. The client software enables or restricts features based on this response.
Domain Matching Rules
Domain matching handles the messy reality of how domains work in production:
- Exact match —
example.commatchesexample.com - www normalization —
www.example.commatches a license forexample.com(and vice versa) - Subdomain matching —
app.example.commatches a license forexample.comwhen wildcard subdomain matching is enabled - Wildcard domains —
*.example.commatches any subdomain ofexample.com - Port stripping —
localhost:3000is normalized tolocalhostbefore matching
Hardware Dongles vs Domain-Bound Licensing
The comparison isn’t abstract — it’s a concrete set of trade-offs across cost, UX, deployment, and security:
| Dimension | Hardware Dongle | Domain-Bound License |
|---|---|---|
| Unit cost | $5–$50 per dongle (hardware + shipping) | $0 — license is a database record |
| Deployment time | Days to weeks (physical shipping) | Instant — API call creates the license |
| User friction | Plug in USB, install drivers, keep dongle safe | Enter license key once — domain auto-detected |
| Loss/damage risk | High — lost dongle = locked-out customer | None — license key can be re-sent via email |
| Revocation | Requires physical retrieval or remote disable firmware | Instant — single API call revokes the license |
| Multi-site scaling | One dongle per machine (buy more dongles) | Add domains to the license record (no hardware) |
| Remote teams | Ship dongles to each location | Works anywhere the domain resolves |
| Cloud/container support | None — no USB port in a container | Native — domain validation works in any runtime |
| Offline support | Full (dongle is physically present) | Supported via Ed25519 signed tokens (cached locally) |
| Piracy surface | Dongle cloning, driver emulation | Domain spoofing (mitigated by server-side validation) |
| Analytics | None (dongle doesn’t phone home) | Full — validation logs, usage metrics, activation history |
Dongles still have one advantage: they work in air-gapped environments with zero network connectivity. For those scenarios, offline license validation with Ed25519 cryptographic signatures provides a comparable level of assurance — the signed token is verified locally without any network request.
Implementation Guide
PHP (WordPress Plugin)
Domain-bound validation in a WordPress plugin using the PHP SDK:
// Install: composer require traffic-orchestrator/sdk
use TrafficOrchestratorClient;
use TrafficOrchestratorConfig;
$client = new Client(new Config([
'apiKey' => MY_PLUGIN_API_KEY,
'product' => 'my-wordpress-plugin',
]));
// Extract the WordPress site domain
$domain = wp_parse_url(home_url(), PHP_URL_HOST);
// Validate the license key against the domain
$result = $client->validate([
'key' => get_option('my_plugin_license_key'),
'domain' => $domain,
]);
if ($result['valid']) {
// License is active for this domain
// $result['plan'] — the license tier
// $result['features'] — feature entitlements array
// $result['expiresAt'] — expiration timestamp
my_plugin_enable_premium();
} else {
// License invalid for this domain
my_plugin_show_activation_prompt();
}
Node.js
Server-side domain validation in an Express or Next.js middleware:
// Install: npm install @traffic-orchestrator/client
import { TrafficOrchestrator } from '@traffic-orchestrator/client'
const to = new TrafficOrchestrator({ apiKey: process.env.TO_API_KEY })
// Express middleware for domain-bound license validation
const validateLicense = async (req, res, next) => {
const licenseKey = req.headers['x-license-key']
const domain = req.hostname // Express extracts Host header
const result = await to.validate({
key: licenseKey,
domain,
})
if (!result.valid) {
return res.status(403).json({
error: 'LICENSE_INVALID',
message: 'License is not valid for this domain',
})
}
// Attach license metadata to the request for downstream use
req.license = {
plan: result.plan,
features: result.features,
expiresAt: result.expiresAt,
}
next()
}
app.use('/api/premium/*', validateLicense)
Browser-Side Validation
For client-side JavaScript libraries and embeddable widgets:
// Validate on initialization
const validateDomainLicense = async (licenseKey) => {
const response = await fetch(
'https://api.trafficorchestrator.com/api/v1/licenses/validate',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
key: licenseKey,
domain: window.location.hostname,
}),
}
)
const result = await response.json()
return result.valid
}
// Usage in your library initialization
const init = async (config) => {
const licensed = await validateDomainLicense(config.licenseKey)
if (!licensed) {
console.warn('Invalid license for this domain')
return
}
// Initialize premium features
}
Advanced Patterns
Multi-Domain Licenses
Enterprise customers often need a single license key that works across multiple domains — production, staging, and internal tools. Multi-domain licenses store an array of authorized domains against a single key:
// Creating a multi-domain license via the API
const license = await to.licenses.create({
product: 'my-saas-widget',
plan: 'business',
domains: [
'app.customer.com',
'staging.customer.com',
'internal.customer.com',
],
maxDomains: 5, // Allow up to 5 domains on this key
})
The maxDomains field controls how many domains a customer can activate. This maps directly to pricing tiers: a single-site license allows 1 domain, a 5-site license allows 5, and an unlimited license removes the cap.
Staging and Development Exclusions
Developers need to test licensed software locally without consuming a domain activation slot. Common patterns for handling development environments:
- Localhost bypass —
localhost,127.0.0.1, and::1are automatically recognized as development environments and don’t count against domain limits - Staging domain patterns — Domains matching patterns like
*.staging.*,*.dev.*, or*.localcan be configured as non-counting activations - Environment variable override — A
TO_ENV=developmentflag skips validation entirely in local dev (never ship this to production)
Domain Transfer Flow
When a customer migrates their site to a new domain, the license needs to follow. The transfer flow is a deactivate-then-activate sequence:
- Deactivate the old domain:
POST /api/v1/licenses/deactivatewith{ key, domain: oldDomain } - Activate the new domain:
POST /api/v1/licenses/activatewith{ key, domain: newDomain } - The domain slot is freed immediately — no waiting period, no support ticket
For WordPress plugins, this can be automated by detecting when home_url() changes and triggering the transfer automatically.
Wildcard Matching
Wildcard domains (*.example.com) authorize all subdomains under a root domain. This is useful for multi-tenant platforms where each tenant gets a subdomain: tenant-a.platform.com, tenant-b.platform.com, and so on. A single wildcard license covers all of them.
Handling Edge Cases
Domain Migrations
When a customer rebrands and changes their domain (oldsite.com → newbrand.com), two approaches work:
- Manual transfer — Customer or admin deactivates the old domain and activates the new one through the portal
- Automatic detection — The software detects a domain mismatch on startup and initiates the transfer via API, notifying the customer
CDN and Proxy Domains
Software served through CDNs or reverse proxies may see the CDN’s domain (cdn.cloudflare.com) instead of the actual customer domain. Handle this by:
- Reading the
OriginorRefererheader to get the actual customer domain - Using the
X-Forwarded-Hostheader when behind a reverse proxy - Allowing customers to configure their domain in the software settings rather than auto-detecting it
Localhost and Development
Local development environments present localhost, 127.0.0.1, or *.local as the hostname. The validation API recognizes these patterns and allows validation without consuming a domain activation slot. This means developers can test their integration without needing a separate “dev license.”
Anti-Piracy Through Domain Binding
Domain-bound licensing provides a natural anti-piracy mechanism that hardware dongles cannot match in web-distributed software:
- Key sharing is neutralized — A license key activated on
store-a.comwon’t validate onstore-b.com. Sharing the key achieves nothing because the domain check fails. - Nulled distributions are detectable — Even if someone removes client-side validation code, server-side enforcement still blocks requests from unauthorized domains. The validation response never reaches the nulled copy.
- Usage visibility — Every validation request is logged with the requesting domain. Unusual patterns (same key from 50 different domains) trigger automated alerts.
- Instant revocation — If a license is being abused, a single API call revokes it immediately. No waiting for a dongle to be physically recovered.
The BSA Global Software Survey estimates unauthorized software distribution costs the industry $46 billion annually. Domain-bound licensing doesn’t eliminate piracy entirely — no system does — but it makes casual key sharing and redistribution economically pointless for web-deployed software.
When Dongles Still Make Sense
Domain-bound licensing replaces dongles for web-deployed software, but hardware dongles still serve specific niches:
- Air-gapped industrial systems — Manufacturing floors, medical devices, and military systems with zero internet connectivity
- Pre-USB-C legacy environments — Older workstations running specialized software that predates cloud licensing
- Physical possession as a requirement — Regulatory environments where a physical token is mandated by compliance frameworks
For air-gapped environments that can tolerate periodic online activation, Ed25519 signed license tokens bridge the gap — the initial activation requires connectivity, but subsequent validations are performed locally using the cryptographic signature embedded in the token.
Domain Licensing on Every Plan
Domain-bound licensing is available on every Traffic Orchestrator plan, including the free Builder tier. The free plan includes 5 licenses and 500 validations per month — enough to build and test a complete domain-bound integration before going to production.
| Plan | Licenses | Validations/month | Domain-Bound Validation |
|---|---|---|---|
| Builder (Free) | 5 | 500 | ✓ Included |
| Starter ($29/mo) | 100 | 50,000 | ✓ Included |
| Professional ($99/mo) | 1,000 | 1,000,000 | ✓ Included |
| Business ($299/mo) | 10,000 | 5,000,000 | ✓ Included |
| Enterprise (Custom) | 100,000 | 100,000,000 | ✓ Included |
Validation requests resolve at 300+ edge locations in under 10ms. The API supports domain matching, wildcard subdomains, multi-domain licenses, and instant revocation on all tiers.
Add Domain-Bound Licensing to Your Software
12 SDKs. 300+ edge locations. Sub-10ms validation. Domain-bound licensing is available on every plan, including the free Builder tier — no credit card required.
Create Free AccountShip licensing in your next release
5 licenses, 500 validations/month, full API access. Set up in under 5 minutes — no credit card required.