If you’re developing a WordPress plugin or theme, you can easily add our license key check system. You’ll need to do a few basic steps, and we’ve included some working code from our own theme to get you started. We also have a WP demo theme with all the necessary files if you would like to have a look (linked below).
NOTE: Want to add BatchKeys to a WordPress plugin instead? Follow these instructions.
What You’ll Need #
To check license keys you need to edit or add a few basic files to your WordPress theme:
- /inc/.env file – holds your secure data, like your API auth key
- /inc/license-handler.php – will handle license key checks
You’ll also need to add a small snippet in critical files such as your functions.php, header.php or footer.php
Download Example Theme #
If you would like to see a working example, we have created a working demo theme that includes all the necessary files. It’s ready for you to modify into your own theme.
Download: batchkeys-demo-theme.zip
REMEMBER TO UPDATE THE .ENV FILE WITH YOUR ACTUAL API AUTHORIZATION CODE! You can find your API auth code in your Dashboard.
/inc/.env File #
Using an .env file is a standard security practicing to provide a layer of obfuscation between your sensitive developer data and the end user.
BK_API_URL=https://batchkeys.com/api.php
BK_API_AUTH=PUT_YOUR_ACTUAL_API_AUTH_KEY_FROM_YOUR_BATCHKEYS_DASHBOARD_HERE
/inc/license-handler.php #
This file handles the entire process of license key checking for a WordPress theme, including providing an admin options page with an input form that calls our API. We recommended encoding this file.
This file is comprehensive and has some optional features. The code does the following:
- Defines a constant we can check for later as a security measure (and shut down the theme if it’s not found)
- Include the custom CSS file for the admin page (optional, from our demo theme)
- Add a notice to the top of all admin pages if no key has ever been activated (optional)
- Create an admin options page with a form for the user to input the key. Also controls some message handling (messages are optional)
- Shows the license key input field within the options page (optional, we’ve added it separately in case you would like to replace it once a license key has been validated)
- Load .env variables into environment
- Validates the license key and sets a transient on success
- Show error messages (optional)
- Display success notice if transient is set (optional)
We’ve included optional features in the demo, such as adding a custom css file, showing special notice messages, and dynamically loading the input field into the form. These features can be removed, changed, or combined as you wish.
<?php
// We recommend renaming this file to something vague and also encoding this file for added security
// See our documentations on encoding PHP and how to use the encoding tool we have created
// https://batchkeys.com/docs/encoding-and-decoding-php/
// Defines a constant for checking if the license-handler.php was included in the theme
define('LICENSE_HANDLER_LOADED', true);
// Enqueue the admin page CSS file
function batchkeys_admin_styles() {
wp_enqueue_style('batchkeys-admin-css', get_template_directory_uri() . '/admin-style.css');
}
add_action('admin_enqueue_scripts', 'batchkeys_admin_styles');
// Add a notice if no key has ever been submitted
add_action('admin_notices', function() {
$license_key = get_option('theme_license_key');
if (!$license_key) {
echo '<div class="notice notice-warning is-dismissible"><p>The BatchKeys Demo Theme requires a license key to fully function. Please <a href="' . esc_url(menu_page_url('batchkeys-demo-theme-settings', false)) . '">enter it now</a>.</p></div>';
} elseif ($message = get_transient('batchkeys_activation_success')) {
echo '<div class="updated notice is-dismissible"><p>' . esc_html($message) . '</p></div>';
delete_transient('batchkeys_activation_success');
}
});
// Create the admin options page
function setup_theme_admin_menus() {
add_menu_page('BatchKeys Theme Settings', 'BatchKeys Theme Settings', 'manage_options',
'batchkeys-demo-theme-settings', 'theme_settings_page');
}
add_action('admin_menu', 'setup_theme_admin_menus');
function theme_settings_page() {
$message = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['theme_license_key'])) {
$validated_key = validate_license_key($_POST['theme_license_key']);
if ($validated_key !== false) {
update_option('theme_license_key', $validated_key);
$message = get_transient('batchkeys_activation_success');
if ($message) {
delete_transient('batchkeys_activation_success');
}
} else {
$error = get_transient('batchkeys_theme_error');
if ($error) {
$message = $error['message'];
delete_transient('batchkeys_theme_error');
}
}
}
// Display the admin page's contents, and a demo message if the key was activated
?>
<div class="wrap">
<h1>BatchKeys Demo Theme Settings</h1>
<?php if ($message): ?>
<div class="<?php echo $validated_key === false ? 'notice notice-error' : 'updated notice'; ?> is-dismissible"><p><?php echo esc_html($message); ?></p></div>
<?php endif; ?>
<?php
// Check if license key is set and display demo message
$license_key = get_option('theme_license_key');
if ($license_key): ?>
<div class="updated notice is-dismissible" style="background-color: #d3f8d3; border-color: #45b546;"><p>License Key Is Activated!</p></div>
<?php endif; ?>
<form method="post" action="">
<?php
settings_fields("section");
do_settings_sections("theme-options");
?>
<input type="submit" name="submit" id="batchkeys-save-settings" class="button-primary" value="Save Changes">
</form>
</div>
<?php
}
// Show the license key input field within the options page
function display_theme_panel_fields() {
add_settings_section("section", "All Settings", null, "theme-options");
add_settings_field("theme_license_key", "License Key:", "display_license_element",
"theme-options", "section");
register_setting("section", "theme_license_key");
}
function display_license_element() {
?>
<input type="text" name="theme_license_key" id="theme_license_key" placeholder="Abc1234-Def5678-Ghi9012-Jkl3456-Mno7890" required value="<?php echo get_option('theme_license_key'); ?>" />
<?php
}
add_action("admin_init", "display_theme_panel_fields");
// Load .env variables into environment
function load_env_variables() {
$env_path = __DIR__ . '/.env';
$log_path = __DIR__ . '/error_log'; // error log location in case the .env file is not found
if (!file_exists($env_path)) {
// Log the error
error_log('Missing .env file at ' . $env_path, 3, $log_path);
return false;
}
$env_vars = file($env_path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($env_vars as $env_var) {
if (strpos(trim($env_var), '#') === 0) {
continue;
}
list($name, $value) = explode('=', $env_var, 2);
$name = trim($name);
$value = trim($value);
putenv("$name=$value");
$_ENV[$name] = $value;
$_SERVER[$name] = $value;
}
}
add_action("admin_init", "load_env_variables");
// Function that actually validates the license key and sets a transient on success
// Consider encoding this part of the code if you have not encoded this entire file
// NOTE: See https://batchkeys.com/docs/encoding-and-decoding-php for encoding tips and info on how to use our encoding tool
function validate_license_key($license_key) {
if (!preg_match('/^[A-Za-z0-9-]+$/', $license_key)) {
add_theme_error_message('invalid_key_format', 'Please enter a valid license key. Only alphanumeric characters and dashes are allowed.');
return false;
}
$api_url = getenv('BK_API_URL');
$api_auth_key = getenv('BK_API_AUTH');
if (!$api_url || !$api_auth_key) {
add_theme_error_message('api_config_error', 'API URL or Auth key not set in environment variables.');
return false;
}
$args = array(
'method' => 'GET',
'headers' => array(
'auth' => $api_auth_key,
'key' => $license_key,
'domain' => $_SERVER['HTTP_HOST']
)
);
$response = wp_remote_get($api_url, $args);
if (is_wp_error($response)) {
add_theme_error_message('api_request_error', 'Failed to check the license key. Please try again.');
return false;
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
if (isset($data['valid']) && $data['valid'] == 1) {
set_transient('batchkeys_activation_success', 'Your license key has been activated successfully.', 3600);
return $license_key; // Return the license key itself if valid
} else {
add_theme_error_message('license_validation_failed', 'Invalid license key. Please check your key and try again.');
return false;
}
}
// Show error messages
function add_theme_error_message($code, $message) {
set_transient('batchkeys_theme_error', ['code' => $code, 'message' => $message], 3600);
}
// Display success notice if transient is set
add_action('admin_notices', function() {
if ($message = get_transient('batchkeys_activation_success')) {
echo '<div class="updated notice is-dismissible"><p>' . esc_html($message) . '</p></div>';
delete_transient('batchkeys_activation_success');
}
$error = get_transient('batchkeys_theme_error');
if ($error) {
echo '<div class="notice notice-error is-dismissible"><p>' . esc_html($error['message']) . '</p></div>';
delete_transient('batchkeys_theme_error');
}
});
functions.php #
The below code will load the license-handler.php file and then perform a check for a constant that is defined inside that file. If the constant is not found it prevents the theme from loading and shows a notice message instead.
Again, please adjust how limited you need your premium them to be, like for example if you only want to limit certain features. Consider encoding this part of the function.php file.
NOTE: You do not want to put too much security code into the functions.php, as it’s typically the first place a user looks. Again, we also highly recommend encoding or otherwise obfuscating critical parts of your code, such as this part of the functions file.
<?php
/*
* Include the license checking scripts and various other critical functions
* In actual production code, you should name license-handler.php something vague and possibly encode it
* NOTE: See https://batchkeys.com/docs/encoding-and-decoding-php for encoding tips and info on how to use our encoding tool
* NOTE: Check /batchkeys-demo-theme/inc/error_log to ensure your .env location is properly assigned in license-handler.php
*/
require_once get_template_directory() . '/inc/license-handler.php';
// Check if the license handler was loaded
if (!defined('LICENSE_HANDLER_LOADED')) {
add_action('template_redirect', 'disable_theme_frontend');
}
function disable_theme_frontend() {
if (!is_admin()) { // Check to ensure that we're on the frontend
wp_die('This theme requires a valid license to function. Please contact the site administrator.');
}
}
Your Other Critical Files #
For this demo, we also use a tiny snippet of code inside your critical files such as header.php, footer.php etc, to completely lock the theme. You can do this however you wish, for example you could change this to allow the frontend to work and only lock certain features.
We recommend encoding this snippet and placing it throughout your code in several place.
// Example header.php section to prevent wp_head() from loading and display a message instead
// Download and install our demo theme to see this live
//
// You can apply this same code to all critical functions
// ...such as:
// wp_head()
// wp_footer()
// the_content()
// get_footer()
// etc. etc. etc.
<?php
if (defined('LICENSE_HANDLER_LOADED')) {
// Get the wp head
wp_head();
} else {
wp_die('This theme requires a valid license to function. Please contact the site administrator.');
}
?>
Wrapping Up #
There you have it, add those files and snippets to your WordPress theme and the user will be presented with a form to input their key before your theme unlocks.
You’ll notice we used some css classes in the code. We provide the css in the demo theme linked at the top of this page, or you can change them to whatever suits your design best.
To further secure your theme we recommend additional security practices such as encoding or otherwise obfuscate sensitive parts of your code, using a checksum to ensure the code hasn’t been tampered with, or other standard security features that we couldn’t include in the demo because we wanted you to be free to modify it however you wish.