Automatic Updates For Private And Commercial Themes

Update 2017-06-20: This library has been deprecated. Please use PUC instead. It’s more current and it supports both themes and plugins.


This is a PHP library that lets you add automatic update notifications and single-click updates to any WordPress theme. It’s purpose is to be easy to integrate for developers and to provide a familiar experience to theme users. From the users’ point of view, update notifications generated by this library will look and function just like those displayed by WP itself.

Dashboard screenshot

An update notification for a theme not hosted on wordpress.org

Download

License

This library is licensed under the GPL and is distributed free of charge. If you find it useful, consider making a donation. Commercial licensing (e.g. for projects that can’t use an open-source license) is available upon request.

Quick-Start Guide

There are two things you will need to do:

  1. Create a publicly accessible “metadata file” that describes the latest version of your theme.
  2. Add the update checker to your theme and tell it where to find that file.

First, the metadata file. Open your favourite text editor and copy the following JSON code into a new file:

{
  "version" : "2.0",
  "details_url" : "http://example.com/example-theme/details.html",
  "download_url" : "http://examle.com/example-theme/example-theme.zip"
}

Replace the placeholder values with your own data. As you can probably guess, version is the version number of your theme. details_url specifies the page that the user will see if they click the “View version 1.2.3 details” link in an update notification. Set this field to your “What’s New In Version 1.2.3” page or the theme homepage (tip: if you notice that your page looks strange when viewed from the WP dashboard, see this comment).

Finally, download_url is the URL where the latest version of the theme can be downloaded. This field is optional. If you leave it out, the user will still get an update notification when a new version comes out, but there will be no “update automatically” link. They’ll have to download and install the update manually.

Upload the metadata file to your website. You can use any directory and file name you like; just remember that the file URL should be accessible from wherever someone might install your theme.

Next, lets add the update checker library to you theme. Copy the “theme-updates” directory from the client library to your theme. Then add the following to your functions.php:

//Initialize the update checker.
require 'theme-updates/theme-update-checker.php';
$example_update_checker = new ThemeUpdateChecker(
    'example-theme',
    'http://example.com/example-theme/info.json'
);

Again, replace the placeholders with your own settings. The first argument should be the name of your theme’s directory. For example, if your theme lives in /wp-content/themes/my-theme/, use “my-theme” here. The second argument should be the URL of the metadata file you just created.

Congratulations, your theme now supports automatic updates 🙂 The update checker will automatically query the metadata file every 12 hours, checking to see if a new version is available. If it finds one, it will display a standard theme update notification on the Dashboard. Your users will be able to install the new version with a single click.

The ThemeUpdateChecker class

Class constructor
The library is configured by passing a number of arguments to the ThemeUpdateChecker constructor. They are, in order :

  • $theme –  The theme directory name, sometimes called the “slug”.
  • $metadataUrl – The URL of the theme metadata file.
  • $enableAutomaticChecking – Enable/disable automatic update checking. If set to FALSE, you’ll need to explicitly call the checkForUpdates method to, err, check for updates. Defaults to TRUE.

checkForUpdates()
Manually trigger an update check. This is useful if you want to do update checks on your own schedule. checkForUpdates has no parameters and does not return anything. If you want to actually retrieve the latest update, use requestUpdate instead.

requestUpdate()
Retrieve update information from the configured metadata URL. Returns either an instance of ThemeUpdate, or NULL if there is no newer version available or if there’s an error.

deleteStoredData()
The update checker stores various update-related bookkeeping data in a DB option. Call this method to delete that data. This is can be useful is your theme provides some kind of “uninstall” feature.

addQueryArgFilter($callback)
Register a callback for filtering query arguments. Whenever the update checker needs to retrieve the metadata file, it will first run each filter callback and attach the query arguments that they return to the metadata URL. This lets you pass arbitrary data to the server hosting the metadata. For example, commercial themes could use it to implement some kind of authorization scheme where only paying users get automatic updates.

The callback function will be passed an associative array of query arguments and should return a modified array. By default, the update checker will append the following query arguments to the URL:

  • installed_version – the currently installed version of the theme.

This method takes one parameter – the callback function.

addHttpRequestArgFilter($callback)
Register a callback for filtering arguments passed to wp_remote_get. The callback function should take one argument – an associative array of arguments – and return a modified array or arguments. See the WP documentation for details about what arguments are available and how they work. This method takes one parameter – the callback function.

addResultFilter($callback)
Register a callback for filtering theme info retrieved from the metadata URL. The callback function should take two arguments. If a theme update was retrieved successfully, the first argument will be an instance of ThemeUpdate. Otherwise, it will be NULL. The second argument will be the corresponding return value of wp_remote_get (see WP docs for details). The callback function should return an instance of ThemeUpdate, or NULL. This method takes one parameter – the callback function.

Related posts :

306 Responses to “Automatic Updates For Private And Commercial Themes”

  1. Hans says:

    Hi Janis,
    thanks for your very good job! I have created a german tutorial, based one your scripts:
    https://www.web266.de/tutorials/wordpress/theme/themes-selbst-hosten/

    Best regards

  2. Wiz says:

    Hey Janis,

    Many thanks for still responding to support requests after so long! This class is amazing for plugins. Now I am trying to get it to work on my theme as well. The example theme when uploaded to my server works fine, however my theme will not show the available update.

    A few questions to try and troubleshoot:
    – Does the updater work over https or do the URLs in the info file have to be http?
    – Can the theme name have uppercase characters? My theme name is like “CompanyName” and so I wasn’t sure if that was the issue. the url would be like https://companyname.com/wordpress/themes/CompanyName.zip

    I have verified the info file is written correctly.
    I have the zip file with theme in the right directory.
    I have the code in the functions file and have ensured it is firing properly.

    Any other tips/tricks you can think of to help me troubleshoot the issue? I appreciate any help you can give!

  3. Wiz says:

    As a follow-up, if I look at the WPDB, unlike the example theme, it’s only showing the following:

    O:8:”stdClass”:3:{s:9:”lastCheck”;i:1476394883;s:14:”checkedVersion”;s:4:”1.25″;s:6:”update”;N;}

    Whereas, the example theme writes both the details and updates URL to the DB:

    O:8:”stdClass”:3:{s:9:”lastCheck”;i:1476392827;s:14:”checkedVersion”;s:3:”1.0″;s:6:”update”;s:187:”{“version”:”2.0″,”details_url”:”http:\/\/w-shadow.com\/files\/example-theme-updates\/details.html”,”download_url”:”http:\/\/w-shadow.com\/files\/example-theme-updates\/example-theme.zip”}”;}

    Not sure if this could help narrow down the issue. Thanks again for any help!

  4. Jānis Elsts says:

    – Does the updater work over https or do the URLs in the info file have to be http?

    In general, HTTPS should work fine, but it depends on your server. Some servers have very outdated SSL libraries or certificate stores. This can cause requests sent to HTTPS URLs to fail because the WordPress HTTP API can’t verify SSL certificates.

    You can use the Core Control plugin to log requests sent by the update checker and see if they’re successful:
    https://wordpress.org/plugins/core-control/

    – Can the theme name have uppercase characters?

    I don’t know about themes specifically, but there was a WordPress bug a while ago that could break the inline update feature for plugins that have uppercase characters in the directory name. It didn’t prevent updates from showing up, but it interfered with your ability to install them.

    It’s probably safer to use a lowercase directory name. The actual theme name (i.e. the “Theme Name:” header) can still have uppercase characters, of course.

    As a follow-up, if I look at the WPDB, unlike the example theme, it’s only showing the following: […]

    That suggests that the update checker either wasn’t able to retrieve the info file or it couldn’t parse the data. Try using Core Control (see above) to check for HTTP errors. Also, run your info file through a JSON validator:
    http://jsonlint.com/

  5. Mike Taylor says:

    Works great, thank you so much!

  6. MIKUScallion says:

    Works great, thank you so much!

    But, I can’t use it at wordpress Version 4.6.1.

    The plugin updater is ok, but theme updater not.

  7. Jānis Elsts says:

    What specifically is the problem with WP 4.6.1? Have you tried the example theme?

  8. Thomas says:

    The same for me. With WP 4.6.1 there’s no notice in the theme overview that my theme has an update.

    It only shows the update under Dashboard – Updates in the theme section.

    Thanks for your help!

  9. Jānis Elsts says:

    How about the example theme? Does the notice show up when this theme is active?

  10. Thomas says:

    No matter whether the sample theme or my theme – no notice for self hosted themes.

  11. Thomas says:

    Sorry, it was my fault. I had the wrong name in the slug parameter in the functions.php for the themes.

    Now it works fine!

  12. Ha Nguyen says:

    Thank you for this TUT !

  13. Taon says:

    hey bro how to add update button in page themes.php
    thank bro !

  14. Jānis Elsts says:

    Could you be a bit more specific? Usually WordPress will automatically display an “update now” link on the “Themes” page when an update is available. Do you want to add another link/button, or do you have some kind of a problem with the update checker where the link doesn’t show up? (If so, double-check your configuration.)

  15. Taon says:

    Oh my bad. I’m confused between theme name and theme folder name.

  16. […] Automatic Updates For Private And Commercial Themes | W-Shadow.com […]

  17. asmita says:

    I am having a problem since few days. After I update a theme, it appends an alphanumeric code (themename-45H9 something like this) after the theme name due to which the theme’s broken. Please do help.

  18. Jānis Elsts says:

    This problem is usually caused by incorrect directory structure. Make sure that the ZIP file contains only a single directory with the same name as your theme folder, and that all theme files are inside that directory. If there are multiple files at the root of the ZIP archive, WordPress will always mess up the folder name.

    If you’re using a Mac, you need to be especially careful about this because the built-in ZIP utility displays the contents of ZIP files in a misleading way. It makes it look like the files are in a directory when they’re not. I would recommend using a third-party archiver in this case.

  19. asmita says:

    Hi, I checked the ZIP file, it contains only a single directory with the same name as of the theme folder, but the issue still persists. Is there any other thing to look into?

  20. Jānis Elsts says:

    Are you 100% sure? As I mentioned, some software can display ZIP file contents in a misleading way. What ZIP archiver are you using?

    I can’t think of any plausible alternatives, at least not off the top of my head. In theory, some kind of a conflict with another custom updater could cause this kind of a problem, but that seems very unlikely and I’ve never seen happen in practice. Also, a file permission issue or a PHP error could prevent the directory from being (re-)named correctly, but both of those would usually either interrupt the update installation process completely or they would at least show up in the PHP error log.

Leave a Reply