---
title: Enable Automatic Updates for Plugins Hosted by Developers
date: 2009-11-12T22:21:28+00:00
modified: 2024-09-26T09:40:35+00:00
permalink: https://kaspars.net/blog/enable-automatic-updates-for-plugins-hosted-by-developers
post_type: post
author:
  name: Kaspars
  avatar: https://reverse.kaspars.net/gravatar/avatar/92bfcd3a8c3a21a033a6484d32c25a40b113ec6891f674336081513d5c98ef76?s=96&d=mm&r=g
post_tag:
  - How to
  - Plugin
category:
  - WordPress
---

# Enable Automatic Updates for Plugins Hosted by Developers

Currently WordPress doesn’t offer an easy way for plugins which are not hosted on wordpress.org to use its built-in automatic update feature.

Fortunately, I have found a quick and simple way to add this functionality to any plugin and allow plugin authors to take a complete control over when and how the updates are released.

 The solution consist of two parts:

1. filtering the contents of `get_transient('update_plugins')` under `wp_update_plugins()` in `<a href="http://svn.automattic.com/wordpress/trunk/wp-includes/update.php">/wp-includes/update.php</a>`, and
2. providing your own update API.

## Examples

### Updates Hosted on GitHub

See <https://github.com/kasparsd/git-update>

### Envato CodeCanyon Hosted Plugins

Note: this functionality is now provided by the [Envato Market Plugin](https://www.envato.com/lp/market-plugin/) by default!

See <https://github.com/kasparsd/envato-automatic-plugin-update>

### Custom Update Endpoint

Here is a working (and a very basic) example of an update API endpoint:

```
<?php 

// Set this to TRUE while editing and testing this file
$disable_update = false;

$allowed_clients = array(
	'111' => 'note for self',
	'222' => 'like the URL of the user'
);

// Strip away comments
$allowed_clients = array_keys($allowed_clients);

$versions['check'] = array(
	array(
		'version' => '0.5',
		'package' => 'http://api.example.com/plugin-0.5.zip'
	)
);

// Check if the request is valid
if (!isset($_POST['name']) || $disable_update || !is_array($versions[$_POST['name']]))
	return;

// Check if client can receive updates
if (!in_array($_POST['api-key'], $allowed_clients))
	return;
	
$latest_version = array_shift($versions[$_POST['name']]);

if (version_compare($_POST['version'], $latest_version['version'], '<'))
	print serialize($latest_version);

if ($disable_update && !isset($_POST))
	print_r($versions);
```

and a plugin using that endpoint:

```
<?php
/*
Plugin Name: Check Updates
Description: Plugins hosted outside wordpress.org should also enjoy the automatic updates.
Version: 0.1
Author: Kaspars Dambis
*/

add_filter('transient_update_plugins', 'check_for_update');

function check_for_update($checked_data) {
	global $wp_version;
	
	$api_url = 'http://api.example.com/';
	$plugin_base = plugin_basename(dirname(__FILE__));
	
	// Check for updates ONLY ONCE per hour
	if ($checked_data->last_checked) {
		if ((time() - $checked_data->last_checked) < 3600) {
			// uncomment this to avoid checking for updates on every page load
			// return $checked_data;
		}
	}
	
	// Start checking for an update
	$send_for_check = array(
		'body' => array(
			'name' => $plugin_base,
			'version' => $checked_data->checked[$plugin_base .'/'. $plugin_base .'.php'],
			'api-key' => '111'
		),
		'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo('url')
	);

	$raw_response = wp_remote_post($api_url, $send_for_check);
	
	if (!is_wp_error($raw_response) && ($raw_response['response']['code'] == 200))
		$response = unserialize($raw_response['body']);
	
	if (!empty($response['package'])) {
		$update_data = new stdClass;
		$update_data->slug = $plugin_base;
		$update_data->new_version = $response['version'];
		$update_data->url = 'http://konstruktors.com/blog/';
		$update_data->package = $response['package'];
		
		// Feed the update data into WP updater
		$checked_data->response[$plugin_base .'/'. $plugin_base .'.php'] = $update_data;
	}
	
	return $checked_data;
}
```

These solutions enable developers to sell their plugins and still retain the convenience of automatic updates for their users.