Private WordPress plugins

Learn how to distribute your private WordPress plugins.

Installation instructions

You can use Anystack's WordPress Guard to automatically secure your plugin with a license key and enable automatic-updates. If you want to manually integrate the auto-updater, see the section below.

To get started you will need to download the latest release of the library. Make sure you download wp-guard.zip and not the source code! WordPress only has limited support for Composer (PHP package manager), for that reason you will have to download, update, and integrate the library manually.

Unzip the wp-guard.zip in the root of your plugin. Next, we can import the library and add the required code (verify the correct version namespace, e.g. V001).

1require 'wp-guard/src/WpGuard.php';
2 
3// To avoid conflicts with other WordPress plugins the namespace contains a version number (e.g V001)
4// Make sure you use the version that corresponds with the latest release.
5$guard = new Anystack\WpGuard\V001\WpGuard(
6 __FILE__,
7 [
8 'api_key' => 'your-api-key', // Ensure the API key only has the validation and activation scope
9 'product_id' => 'your-product-id',
10 'product_name' => 'Demo', // Product name to display
11 'license' => [
12 'require_email' => true, // Require email in addition to the license key
13 ],
14 'updater' => [
15 'enabled' => true, // Enable the automatic updater.
16 ],
17 // If you want to modify the activation page
18 // You can provide your own via the pages config.
19 // To see the original files, check the wp-guard/pages directory.
20 // 'pages' => [
21 // 'activate' => __DIR__.'./your-custom-activation-page.php',
22 // ],
23 ]
24);

If you want to disable certain functionality until the license has been validated you can use a callback:

1require 'wp-guard/src/WpGuard.php';
2 
3$guard = new Anystack\WpGuard\V001\WpGuard(...);
4 
5$guard->validCallback(function() {
6 add_action( 'admin_notices', 'daily_revenue' ); // This action will only be called if the license has been validated.
7});

The license is scheduled to be validated every hour. If the license is no longer valid the auto-updater will be disabled and any actions in the callback will no longer be called. Please be aware that this can be destructive given it will disable the functionality of your plugin. In case you don't want this, you can ignore calling the validCallback method.

Manual integration

Your customers can use WordPress's built-in updater to update the plugin when new versions are released. To enable this feature, you must register a custom plugin updater, we recommend using the Plugin Update Checker package found on GitHub.

The following code snippet can be used to register the custom updater:

1require 'plugin-update-checker/plugin-update-checker.php';
2 
3use YahnisElsts\PluginUpdateChecker\v5\PucFactory;
4 
5PucFactory::buildUpdateChecker(
6 'https://dist.anystack.sh/v1/php/wordpress-plugin/your-product-id/update-check.json', // Your product ID
7 __FILE__, // Full path to the main plugin file or functions.php
8 'demo' // Your unique plugin slug
9);

Note: If you're using the Composer autoloader, you don't need to explicitly require the library.

  • The second argument passed to buildUpdateChecker must be the absolute path to the main plugin file. If you followed the instructions above, you can just use the __FILE__ constant.
  • The third argument - i.e. the slug - is optional but recommended. In most cases, the slug should be the same as the name of your plugin directory. For example, if your plugin lives in /wp-content/plugins/my-plugin, set the slug to my-plugin. If the slug is omitted, the update checker will use the name of the main plugin file as the slug (e.g. my-cool-plugin.phpmy-cool-plugin). This can lead to conflicts if your plugin has a generic file name like plugin.php.

License verification

If your plugin distribution requires a valid license, you will need to append the contact email (only if license key is assigned to a contact), license key, and fingerprint (only if fingerprints are enforced via the license policy) to the update URL. You will need to request this information from your customer by providing a UI in your plugin settings page.

1require 'plugin-update-checker/plugin-update-checker.php';
2 
3use YahnisElsts\PluginUpdateChecker\v5\PucFactory;
4 
5$params = http_build_query([
6 'email' => get_option('my_plugin_license_email'), // Only required if license is associated with a contact
7 'key' => get_option('my_plugin_license_key'),
8 'fingerprint' => get_option('my_plugin_license_fingerprint'), // Only required if fingerprints are enforced via the license policy
9]);
10 
11PucFactory::buildUpdateChecker(
12 'https://dist.anystack.sh/v1/php/wordpress-plugin/your-product-id/update-check.json?' . $params, // Please note your product ID
13 __FILE__, // Full path to the main plugin file or functions.php
14 'demo' // Your unique plugin slug
15);

Providing additional information to the updater

You can distribute your WordPress plugin with additional data by creating a file called updater-info.json in the root of your repository. Below you can find some examples of what you can include in this file:

1{
2 "requires":"5.0",
3 "tested":"4.8",
4 "upgrade_notice":"Here's why you should upgrade...",
5 "author":"Anystack",
6 "author_homepage":"https://anystack.sh",
7 "sections":{
8 "description":"My plugin <strong>description</strong> here"
9 }
10};

The following keys are supported:

  • requires
    The minimum WordPress version required to run this plugin.
  • tested
    Inform your customers with which WordPress version you have tested your plugin.
  • upgrade_notice
    Display a notice why your customer should upgrade.
  • author
    Display your name.
  • author_homepage
    Link to your website.
  • sections
    Key-value object, the key will be displayed as a tab and the value will be the tab content. You can use basic html in the value.
  • sections.description
    The description will be displayed if a user clicks the 'view details' option.