Ask your WordPress questions! Pay money and get answers fast! (more info)

How to install a plugin from a remote site from a plugin subpage?


I am the developer of and for my pro version I plan to integrate the subpage "Upgrade to pro" from which I want users to be able to install the pro version (=separate plugin). After clicking the install button on this subpage, a zip-file with the pro-package from my server should be fetched and installed like you can do with WordPress by default on plugins / add new / upload.

How to best approach this? I am looking for solutions/code which use Wordpress best practices and APIs. Thanks.

Answers (4)


John Cotton answers:

You need to use the Plugin_Upgrader class. You can pass your custom url to it and it will do most of the output (look at /wp-admin/update.php for an example).


Francisco Javier Carazo Gil answers:

Hi Robert,

Look at update.php in /wp-admin line 90 and nexts:

if ( ! current_user_can('install_plugins') )
wp_die( __( 'You do not have sufficient permissions to install plugins on this site.' ) );

include_once ABSPATH . 'wp-admin/includes/plugin-install.php'; //for plugins_api..

check_admin_referer('install-plugin_' . $plugin);
$api = plugins_api('plugin_information', array('slug' => $plugin, 'fields' => array('sections' => false) ) ); //Save on a bit of bandwidth.

if ( is_wp_error($api) )

$title = __('Plugin Install');
$parent_file = 'plugins.php';
$submenu_file = 'plugin-install.php';
require_once(ABSPATH . 'wp-admin/admin-header.php');

$title = sprintf( __('Installing Plugin: %s'), $api->name . ' ' . $api->version );
$nonce = 'install-plugin_' . $plugin;
$url = 'update.php?action=install-plugin&plugin=' . $plugin;
if ( isset($_GET['from']) )
$url .= '&from=' . urlencode(stripslashes($_GET['from']));

$type = 'web'; //Install plugin type, From Web or an Upload.

$upgrader = new Plugin_Upgrader( new Plugin_Installer_Skin( compact('title', 'url', 'nonce', 'plugin', 'api') ) );

include(ABSPATH . 'wp-admin/admin-footer.php');


phppoet answers:

use something like this


$status = install_plugin_install_status( $plugin, true );

$action = '';
switch ( $status['status'] ) {
case 'install':
if ( $status['url'] ) {
$action = '<a class="install-now" href="' . $status['url'] . '" title="' . esc_attr(sprintf(__('Install %s', 'your plugin name'), $name ) ) . '">' . __('Install Now', 'your plugin name') . '</a>';
else {
$action = '<span title="' . esc_attr__('This plugin is already installed and is up to date', 'your plugin name') . ' ">' . __( 'Installed' ) . '</span>';
case 'update_available':
if ( $status['url'] )
$action = '<a href="' . $status['url'] . '" title="' . esc_attr(sprintf(__('Update to version %s', 'your plugin name'), $status['version'])) . '" class="your plugin name-bold your plugin name-orange">' . sprintf(__('Update Now', 'your plugin name'), $status['version'] ) . '</a>';
case 'latest_installed':
case 'newer_installed':
$action = '<span title="' . esc_attr__('This plugin is already installed and is up to date', 'your plugin name') . ' ">' . __('Installed', 'your plugin name') . '</span>';

where ' . $status['url'] . ' will contain zip url of your plugin.

phppoet comments:

Another way would be to implement something like this into your current plugin which is a plugin update script. which retrives data from external .js file which keep information about latest version ,zip update url.

When users click on version details they popup appears where install now link exists . when users click on install now previous plugin is deactivated and new plugin is downloaded,installed and activated from scratch. You can modify it as per your need.


plovs answers:

The simplest way I can think of to supply custom plugins is using the code found here: [[LINK href=""]]automatic-theme-plugin-update[[/LINK]]

You could add the custom update-code to your plugin, but deactivated. User pays money, gets a key, enters key, presses update, update checks the key, if correct, switches update repo, from then on it will do update-lookups to your server.

From then on the plugin will look in your custom location for updates, for the end-user it looks like any other plugin update.