Skip to content

plugpressco/plugpress-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PlugPress SDK

Drop-in SDK for WordPress plugins. Provides self-hosted updates (stable + beta channels), license activation, telemetry opt-in, deactivation feedback, and a React Hub (About + License pages) backed by a REST API.

composer require plugpressco/plugpress-sdk

Components

Config key Class What it does
PlugPress_Config Typed, sanitized config every component consumes
updater PlugPress_Updater Checks updates.plugpress.co for new versions (stable or beta channel)
updater PlugPress_Beta Per-site beta-channel switch (Beta Hub)
pro + updater PlugPress_License License key activation / validation (key never leaves PHP; APIs return a masked form)
optin PlugPress_Optin GDPR-compliant telemetry opt-in (WP Guideline 7)
feedback PlugPress_Feedback Deactivation reason modal on plugins.php
PlugPress_Activation Activation timestamp + optional first-run redirect
PlugPress_API REST API (plugpress/v1/{slug}/…) behind the Hub — API-first
about / menu_parent PlugPress_About React Hub admin pages (About + License)
PlugPress_Products Cross-sell catalogue with resolved install state
PlugPress_Notices Shared flash + persistent admin notices

Every component is individually toggleable — disable what your distribution channel restricts.


Beta Hub

Each product can opt a site into its beta channel from the Hub (or via POST /plugpress/v1/{slug}/beta). When on, update checks send channel=beta; the update server serves the manifest's beta block when its version is newer than stable — with the exact same license gate and signed download token. Turning beta off (or shipping a stable ≥ the beta) returns the site to stable automatically.

Manifest side (on the updates worker):

{
  "version": "1.2.0",
  "beta": { "version": "1.3.0-beta.1" }
}

Upload the zip as plugpress/<slug>/<slug>-1.3.0-beta.1.zip — same naming as stable.


REST API (API-first Hub)

Everything the Hub shows or changes goes through plugpress/v1 (cookie + nonce auth, capability required):

Route What
GET /{slug}/hub Full Hub payload: version, license (masked), beta, opt-in state, products
POST /{slug}/license { action: "activate"|"deactivate", key? }
POST /{slug}/beta { enabled: bool }
POST /{slug}/optin { decision: "allow"|"skip"|"later" }

Consumer plugins can link their own data into the Hub: filter plugpress_sdk_hub_payload (PHP) adds data to the payload; the plugpress.hubSections JS filter (via @wordpress/hooks) appends UI sections.

Building the Hub app

The built app (admin/build/) is committed — composer consumers never run npm. To change it:

npm install && npm run build   # use nvm node (see plugpress standard Δ6)

Distribution channel configs

1. PlugPress direct (full SDK)

Plugins sold at plugpress.co / outbees.co / inbees.co — SDK owns everything.

add_action( 'init', function () {
    if ( ! class_exists( 'PlugPress_SDK' ) ) return;

    PlugPress_SDK::init( [
        'slug'              => 'your-plugin',
        'name'              => 'Your Plugin',
        'file'              => __FILE__,
        'version'           => YOUR_PLUGIN_VERSION,
        'server'            => 'https://updates.plugpress.co',
        'telemetry_server'  => 'https://analytics.plugpress.co',
        'activate_redirect' => admin_url( 'admin.php?page=your-plugin#/onboarding/welcome' ),
        'pro'               => false,          // true for pro plugins
        // updater, optin, feedback all default to true
        'menu_parent'       => 'your-plugin',
        'accent'            => '#4F46E5',
        'about'             => [
            'tagline' => 'One-line description.',
            'links'   => [
                'Documentation' => 'https://yourplugin.co/docs',
                'Support'       => 'https://yourplugin.co/support',
            ],
        ],
    ] );
} );

1b. Pro via Freemius (updates + licensing owned by Freemius)

Pro products sold through Freemius. One init call: the SDK boots the Freemius SDK (ship it in your plugin via composer require freemius/wordpress-sdk or a vendored freemius/ dir) and stands its own updater/license/opt-in/feedback down — Freemius owns all four. The Hub keeps the About page and shows a "Manage account" card linking to Freemius's account screen.

add_action( 'init', function () {
    if ( ! class_exists( 'PlugPress_SDK' ) ) return;

    PlugPress_SDK::init( [
        'slug'        => 'saddle-pro',
        'name'        => 'Saddle Pro',
        'file'        => __FILE__,
        'version'     => SADDLE_PRO_VERSION,
        'pro'         => true,
        'menu_parent' => 'saddle',
        'freemius'    => [
            'id'         => '12345',            // Freemius product id
            'public_key' => 'pk_...',
            // 'start' => __DIR__ . '/freemius/start.php',  // optional explicit path
            // 'init'  => [ 'has_addons' => true ],         // fs_dynamic_init overrides
        ],
        'about'       => [ 'tagline' => '', 'links' => [ /* … */ ] ],
    ] );
} );

2. DiviPeople self-hosted (Freemius lite — no updater/license)

Plugins sold at divipeople.com that use Freemius lite for opt-in/feedback but NOT for updates. SDK adds About page + analytics.

add_action( 'init', function () {
    if ( ! class_exists( 'PlugPress_SDK' ) ) return;

    PlugPress_SDK::init( [
        'slug'             => 'divi-blog-pro',
        'name'             => 'Divi Blog Pro',
        'file'             => __FILE__,
        'version'          => DBP_VERSION,
        'telemetry_server' => 'https://analytics.plugpress.co',
        'updater'          => false,   // Freemius handles updates + license
        'optin'            => true,
        'feedback'         => true,
        'menu_parent'      => 'divi-people',
        'accent'           => '#7747FF',
        'about'            => [
            'tagline' => 'Beautiful blog layouts for Divi.',
            'links'   => [
                'Documentation' => 'https://divipeople.com/docs/divi-blog-pro',
                'Support'       => 'https://divipeople.com/support',
            ],
        ],
    ] );
} );

3. Full Freemius SDK (Divi Torque Pro and similar)

Plugins that use the full Freemius SDK — Freemius already handles opt-in and feedback. SDK adds only the About page.

add_action( 'init', function () {
    if ( ! class_exists( 'PlugPress_SDK' ) ) return;

    PlugPress_SDK::init( [
        'slug'             => 'divitorque',
        'name'             => 'Divi Torque Pro',
        'file'             => __FILE__,
        'version'          => DTP_VERSION,
        'telemetry_server' => 'https://analytics.plugpress.co',
        'updater'          => false,   // Freemius
        'optin'            => false,   // Freemius has its own opt-in
        'feedback'         => false,   // Freemius has its own feedback
        'menu_parent'      => 'divitorque',
        'accent'           => '#7747FF',
        'about'            => [
            'tagline' => 'Powerful Divi modules to create exceptional websites.',
            'links'   => [
                'Documentation' => 'https://divitorque.com/docs',
                'Support'       => 'https://divitorque.com/support',
                'Changelog'     => 'https://divitorque.com/changelog',
            ],
        ],
    ] );
} );

4. ET Marketplace version

Elegant Themes marketplace restricts all external HTTP calls. SDK adds only the About page — zero external calls.

add_action( 'init', function () {
    if ( ! class_exists( 'PlugPress_SDK' ) ) return;

    PlugPress_SDK::init( [
        'slug'        => 'divi-blog-pro',
        'name'        => 'Divi Blog Pro',
        'file'        => __FILE__,
        'version'     => DBP_VERSION,
        'updater'     => false,   // ET handles
        'optin'       => false,   // no external calls on ET
        'feedback'    => false,   // no external calls on ET
        'menu_parent' => 'divi-people',
        'accent'      => '#7747FF',
        'about'       => [
            'tagline' => 'Beautiful blog layouts for Divi.',
            'links'   => [
                'Documentation' => 'https://divipeople.com/docs',
                'Support'       => 'https://divipeople.com/support',
            ],
        ],
    ] );
} );

5. Free plugins (WordPress.org)

WP.org handles updates — no updater or license needed. Opt-in and feedback are allowed.

add_action( 'init', function () {
    if ( ! class_exists( 'PlugPress_SDK' ) ) return;

    PlugPress_SDK::init( [
        'slug'             => 'your-free-plugin',
        'name'             => 'Your Free Plugin',
        'file'             => __FILE__,
        'version'          => YOUR_PLUGIN_VERSION,
        'telemetry_server' => 'https://analytics.plugpress.co',
        'updater'          => false,   // WP.org handles updates
        'pro'              => false,
        'menu_parent'      => 'your-free-plugin',
        'accent'           => '#4F46E5',
        'about'            => [
            'tagline' => 'One-line description.',
            'links'   => [
                'Documentation' => 'https://...',
                'Support'       => 'https://wordpress.org/support/plugin/your-free-plugin',
                'Rate us'       => 'https://wordpress.org/plugins/your-free-plugin/#reviews',
            ],
        ],
    ] );
} );

Toggle cheatsheet

Channel updater optin feedback
PlugPress direct true true true
DiviPeople (Freemius lite) false true true
Full Freemius SDK false false false
ET Marketplace false false false
WordPress.org free false true true

Full config reference

PlugPress_SDK::init( [
    // Required
    'slug'              => '',        // plugin text-domain slug
    'name'              => '',        // human-readable plugin name
    'file'              => __FILE__,  // path to main plugin file
    'version'           => '1.0.0',

    // Update server (only used when updater: true)
    'server'            => 'https://updates.plugpress.co',

    // Analytics endpoint (only used when optin: true, empty = disabled)
    'telemetry_server'  => 'https://analytics.plugpress.co',

    // Redirect to onboarding after first activation (only when optin: true)
    'activate_redirect' => '',

    // Pro license gate (only when updater: true)
    'pro'               => false,

    // Component toggles
    'updater'           => true,   // self-hosted update checker + license + beta channel
    'optin'             => true,   // telemetry opt-in notice + weekly ping
    'feedback'          => true,   // deactivation feedback modal
    'optin_inline'      => false,  // true when YOUR admin app renders the opt-in card
                                   // (via get_optin_js_data()) — suppresses the PHP
                                   // notice on your top-level screen

    // Admin UI
    'menu_parent'       => '',        // parent menu slug for About/License pages
    'accent'            => '#2395E7', // brand colour for buttons and highlights
    'textdomain'        => '',        // defaults to slug
    'capability'        => 'manage_options',

    // About page content
    'about'             => [
        'tagline' => '',
        'links'   => [],  // [ 'Label' => 'https://...' ]
    ],
] );

Installation

composer require plugpressco/plugpress-sdk

Load the autoloader before calling PlugPress_SDK::init():

if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
    require_once __DIR__ . '/vendor/autoload.php';
}

Shipping tip: end-user sites don't run composer install, so commit the built vendor/ into your plugin's release zip, or run composer install --no-dev -o in your build step. The classes are class_exists-guarded so multiple PlugPress plugins each carrying their own copy won't collide.


Releasing updates

cd plugpress-sdk/
git commit -m "fix: ..."
git tag v1.2.2
git push && git push --tags
# Packagist auto-updates via GitHub webhook

Update in each plugin:

composer update plugpressco/plugpress-sdk
git add composer.lock && git commit -m "chore: bump plugpress-sdk to v1.2.2"

Versioning note (shared-SDK collision)

Classes are class_exists-guarded, so when several active plugins each bundle the SDK, the first-loaded copy wins — plugins must tolerate running against a slightly older SDK than they shipped. Keep the public surface backward-compatible within a major version. (ThemeIsle's SDK solves this with version-negotiated loading — the newest bundled copy wins; worth adopting here if the SDK's surface starts moving fast.)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors