Skip to content

Auto Updates

Enable automatic updates for your WordPress plugin using PackEdge.

Installation

bash
composer require packedge-sdk/license

Quick Setup

php
use PackEdge\License;

$license = License::init('pk_your_public_key', __FILE__);
$license->updater();

That's it. The SDK hooks into WordPress's update system automatically.

How It Works

  1. WordPress checks for updates periodically
  2. The SDK queries PackEdge's update-check endpoint for the product's stable release (the version you mark stable in the console; publishing a new version makes it stable automatically, and you can roll back to an earlier one)
  3. If a newer version exists, it appears in the WordPress updates screen — even for unlicensed sites, as a nudge to activate
  4. When the user clicks "Update", WordPress downloads the ZIP from PackEdge — but the download URL is only handed out to a valid, licensed, active site. Unlicensed or deactivated sites see the update but can't download it
  5. The SDK fixes folder names to match your plugin slug

Show the update, gate the download

The update notice is intentionally always shown; only the package (ZIP) URL is license-gated. So a site with no license, an expired/invalid license, or a deactivated activation still sees "update available" — clicking Update just fails until they activate a valid license.

When the stored license changes (activated, deactivated, disabled), the SDK clears WordPress's update_plugins transient so the Plugins/Updates screen re-checks entitlement immediately instead of waiting out the ~12h cache.

Complete Example

php
<?php
/**
 * Plugin Name: My Plugin
 * Version: 1.0.0
 */

require_once plugin_dir_path(__FILE__) . 'vendor/autoload.php';

use PackEdge\License;

$license = License::init('pk_your_public_key', __FILE__);

// Enable auto-updates. The update notice shows regardless of license state;
// the download is only served to a valid, licensed, active site.
$license->updater();

What the Updater Does

The Updater class hooks into three WordPress filters:

1. Update Check

pre_set_site_transient_update_plugins — Checks if a new version is available.

2. Plugin Info

plugins_api — Shows version details in the "View Details" popup.

3. Folder Fix

upgrader_source_selection — Renames the extracted folder to match your plugin slug.

Requirements

  • Valid license key saved in WordPress options
  • Release uploaded to PackEdge console
  • Plugin slug matches your product slug

Manual Integration

If you prefer not to use the SDK, hook into WordPress directly:

php
add_filter('pre_set_site_transient_update_plugins', function($transient) {
    // license_key is optional — without it the update still shows, the API just
    // omits the package so the download is gated.
    $license_key = get_option('my_plugin_license')['key'] ?? '';

    $response = wp_remote_get(add_query_arg(array_filter([
        'slug' => 'my-plugin',
        'license_key' => $license_key,
        'version' => MY_PLUGIN_VERSION,
        'site' => site_url(),
    ]), 'https://api.packedge.dev/public/v1/wp/update-check'), [
        'headers' => ['X-Public-Key' => 'pk_your_public_key'],
    ]);

    if (is_wp_error($response)) return $transient;

    $update = json_decode(wp_remote_retrieve_body($response));

    if (isset($update->version) && version_compare(MY_PLUGIN_VERSION, $update->version, '<')) {
        // Always surfaced as available; $update->package is empty for
        // unlicensed/deactivated sites, so WP shows it but the download fails.
        $transient->response['my-plugin/my-plugin.php'] = (object) [
            'slug' => $update->slug,
            'new_version' => $update->version,
            'package' => $update->package ?? '',
        ];
    }

    return $transient;
});

Troubleshooting

Updates not showing

The update notice does not require a license — if it's missing entirely:

  1. Verify a release is published and marked stable in the PackEdge console
  2. Check the installed version is older than the stable release version
  3. Confirm the plugin slug matches the product slug
  4. Clear WordPress update transients: delete_site_transient('update_plugins')

Update shows but "Update" fails / no download

This is the license gate working as intended — the package URL is only served to a valid, licensed, active site:

  1. Check the license is valid: $license->is_valid()
  2. Confirm the site's activation hasn't been deactivated in the console
  3. Confirm the license isn't expired

Wrong folder name after update

The SDK automatically fixes this, but if using manual integration, add:

php
add_filter('upgrader_source_selection', function($source, $remote_source, $upgrader, $hook_extra) {
    if (!isset($hook_extra['plugin']) || $hook_extra['plugin'] !== 'my-plugin/my-plugin.php') {
        return $source;
    }

    $correct_path = trailingslashit($remote_source) . 'my-plugin';

    if ($source !== $correct_path) {
        rename($source, $correct_path);
        return $correct_path;
    }

    return $source;
}, 10, 4);