Views: 1
Learn how to build a WordPress theme companion plugin with one-click demo import, premium features, and freemium monetization. Complete guide to creating a best-selling theme ecosystem like any professional WordPress theme.
Introduction
After successfully submitting Versana v1.0 to the WordPress.org theme directory in Episode 28, it’s time to plan our next major release. In this episode, we’re diving into the strategy behind building a WordPress theme companion plugin – the secret weapon that transforms a good theme into a best-selling theme ecosystem.
You’ll learn why successful themes like Blocksy, GeneratePress, and Kadence use a WordPress theme companion plugin architecture, and how to implement one for your own theme.
What We’ll Cover
- Why use a companion plugin vs. core theme features
- Architecture of a successful theme ecosystem
- Building a one-click demo import system
- Implementing premium features
- Creating a freemium monetization model
- Technical implementation with code examples
- Revenue projections and business strategy
- Launch roadmap and timeline
Prerequisites
- Completed Episodes 1-28 (Versana theme development)
- WordPress theme approved on WordPress.org
- Basic understanding of WordPress plugin development
- PHP 7.4+ knowledge
- Understanding of WordPress REST API
Part 1: Why Build a WordPress Theme Companion Plugin?
The Companion Plugin Strategy
A WordPress theme companion plugin is a separate plugin that extends your theme’s functionality without bloating the core theme. This architecture is used by the most successful WordPress themes in the market.
Examples of Successful Companion Plugins:
| Theme | Companion Plugin | Strategy |
|---|---|---|
| Blocksy | Blocksy Companion | Free demos + Pro features |
| Kadence | Kadence Blocks | Free blocks + Pro templates |
| GeneratePress | GP Premium | Core free + Premium plugin |
| Astra | Astra Pro | Starter sites + Pro features |
Why This Architecture Works
For Theme Developers:
✅ Core theme stays lightweight
→ Better WordPress.org reviews
→ Faster page loads
→ Easier maintenance
✅ Faster updates for features
→ No theme review wait (weeks → hours)
→ Iterate based on feedback
→ Fix bugs immediately
✅ Better monetization
→ Clear free vs. pro distinction
→ Easier to sell premium features
→ Recurring revenue model
✅ Modular architecture
→ Users enable only needed features
→ Better performance
→ Cleaner codebase
For Users:
✅ Better performance
→ Load only active features
→ No unused code bloat
→ Faster websites
✅ More flexibility
→ Optional features
→ Easy to disable
→ No theme breaking
✅ Clearer value
→ See what's free vs. pro
→ Easy upgrade path
→ Better support for premium
Architecture Comparison
❌ All-in-One Theme (Old Way):
Versana Theme (Bloated)
├── Blog layouts ✓
├── Sticky header ✓
├── Demo import ✓
├── WooCommerce ✓
├── Dark mode ✓
├── Breadcrumbs ✓
├── Table of contents ✓
├── Share buttons ✓
├── Author box ✓
├── Related posts ✓
└── Premium features ✓
Problems:
❌ Every user loads all features
❌ Slow WordPress.org reviews
❌ Hard to monetize
❌ Performance suffers
❌ Maintenance nightmare
✅ Companion Plugin Architecture (Modern Way):
┌─────────────────────────────────┐
│ VERSANA THEME (Core) │
│ • Blog layouts │
│ • Sticky header │
│ • Essential features only │
│ • Fast & minimal │
└─────────────────────────────────┘
↓
┌─────────────────────────────────┐
│ VERSANA COMPANION (Free) │
│ • Demo import (3 free) │
│ • Breadcrumbs │
│ • Reading time │
│ • Share buttons │
│ • Author box │
│ • Related posts │
└─────────────────────────────────┘
↓
┌─────────────────────────────────┐
│ VERSANA PRO (Premium) │
│ • 20+ premium demos │
│ • WooCommerce integration │
│ • Dark mode │
│ • Table of contents │
│ • Advanced features │
│ • Priority support │
└─────────────────────────────────┘
Benefits:
✅ Users load only what they need
✅ Core theme fast & approved
✅ Features update independently
✅ Clear upgrade path
✅ Easy to maintain
Part 2: Planning Your Theme Ecosystem
The Three-Tier System
When building a WordPress theme companion plugin, think in tiers:
Tier 1: Core Theme (Always Free)
/**
* Versana Theme v1.0
* WordPress.org approved
*
* Core features only:
*/
- Full Site Editing (FSE)
- Basic blog layouts (list, 2-col, 3-col)
- Sidebar positioning (left, right, none)
- Sticky header option
- Performance optimizations
- Analytics integration
- Mobile responsive
- Translation ready
- Accessibility compliant
// Total file size: ~500KB
// Performance: 95+ PageSpeed score
// WordPress.org: ✓ Approved
Tier 2: Companion Plugin (Free)
/**
* Versana Companion (Free Plugin)
*
* Value-add features:
*/
- One-click demo import system
- 3 free starter templates
- Breadcrumbs navigation
- Reading time calculator
- Social share buttons (basic)
- Author bio box
- Related posts (basic)
- 20+ additional block patterns
- Template parts library
// Why free?
// - Builds user base
// - Showcases capabilities
// - Creates upgrade path
// - Community features
Tier 3: Pro Plugin (Premium – $49/year)
/**
* Versana Pro (Premium Plugin)
*
* Professional features:
*/
- 20+ premium demo templates
- Advanced demo import
- WooCommerce full integration
- Dark mode system
- Table of contents (auto-generated)
- Mega menu builder
- Header/footer builder (visual)
- Advanced typography (Google Fonts, Adobe Fonts)
- Performance dashboard
- Premium block patterns (100+)
- Priority support (< 24hr response)
- Agency license option
// Pricing: $49/year (single site)
// $149/year (unlimited sites - agency)
Feature Selection Strategy
How to decide what goes where:
// Decision Tree for Feature Placement
function whereToAddFeature(feature) {
// Core Theme? (Must be true for ALL)
if (
feature.essential === true &&
feature.affectsPerformance === 'minimal' &&
feature.usedByMajority === true
) {
return 'CORE_THEME';
}
// Free Companion? (Must be true for MOST)
if (
feature.addsClearValue === true &&
feature.communityRequested === true &&
feature.canBuildTrust === true &&
feature.showcasesCapability === true
) {
return 'FREE_COMPANION';
}
// Pro Plugin? (Can be true for ANY)
if (
feature.advancedFunctionality === true ||
feature.requiresMaintenance === true ||
feature.nicheUseCase === true ||
feature.providesROI === true
) {
return 'PRO_PLUGIN';
}
return 'NOT_NEEDED'; // Be selective!
}
// Examples:
whereToAddFeature({
name: 'Blog layouts',
essential: true,
affectsPerformance: 'minimal',
usedByMajority: true
}); // → CORE_THEME
whereToAddFeature({
name: 'Demo import',
addsClearValue: true,
communityRequested: true,
canBuildTrust: true,
showcasesCapability: true
}); // → FREE_COMPANION
whereToAddFeature({
name: 'WooCommerce integration',
advancedFunctionality: true,
nicheUseCase: true,
providesROI: true
}); // → PRO_PLUGIN
Part 3: Building the Demo Import System
The Blocksy-Style Demo Library
The killer feature of any WordPress theme companion plugin is one-click demo import. Here’s how to build it:
Visual Demo Library Interface:
┌─────────────────────────────────────────────────────┐
│ Versana Demo Import Library │
│ │
│ Filter: [All] [Free] [Pro] Search: [______] │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │Business │ │ Blog │ │Portfolio│ FREE │
│ │ [img] │ │ [img] │ │ [img] │ │
│ │ Preview │ │ Preview │ │ Preview │ │
│ │ Import │ │ Import │ │ Import │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Shop │ │ Agency │ │Magazine │ PRO 🔒 │
│ │ [img] │ │ [img] │ │ [img] │ │
│ │ Preview │ │ Preview │ │ Preview │ │
│ │Upgrade │ │Upgrade │ │Upgrade │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────────┘
Database Structure
-- Demo Library Table
CREATE TABLE wp_versana_demos (
id INT AUTO_INCREMENT PRIMARY KEY,
demo_key VARCHAR(50) UNIQUE NOT NULL,
demo_name VARCHAR(100) NOT NULL,
demo_description TEXT,
demo_category VARCHAR(50),
is_pro BOOLEAN DEFAULT 0,
preview_url VARCHAR(255),
thumbnail_url VARCHAR(255),
content_url VARCHAR(255),
theme_json_url VARCHAR(255),
required_plugins TEXT,
demo_version VARCHAR(20),
downloads INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_category (demo_category),
INDEX idx_is_pro (is_pro)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Installation Tracking Table
CREATE TABLE wp_versana_demo_installs (
id INT AUTO_INCREMENT PRIMARY KEY,
demo_key VARCHAR(50),
user_id INT,
site_url VARCHAR(255),
installed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
status VARCHAR(20) DEFAULT 'completed',
INDEX idx_demo_key (demo_key),
INDEX idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Plugin File Structure
versana-companion/
├── versana-companion.php # Main plugin file
├── readme.txt # Plugin documentation
├── assets/
│ ├── css/
│ │ ├── admin.css # Admin UI styles
│ │ └── demo-import.css # Import interface
│ ├── js/
│ │ ├── demo-import.js # Import functionality
│ │ └── admin.js # Admin scripts
│ └── images/
│ └── demos/ # Demo thumbnails
│ ├── business.jpg
│ ├── blog.jpg
│ ├── portfolio.jpg
│ ├── shop.jpg
│ └── agency.jpg
├── includes/
│ ├── class-demo-importer.php # Core import class
│ ├── class-content-cleanup.php # Content cleanup
│ ├── class-theme-json-merger.php # theme.json handling
│ ├── class-demo-library.php # Demo catalog
│ ├── class-license-manager.php # Pro license handling
│ ├── admin/
│ │ ├── class-admin-page.php # Admin menu
│ │ └── views/
│ │ ├── demo-import.php # Import UI
│ │ └── settings.php # Settings page
│ ├── features/
│ │ ├── breadcrumbs/
│ │ │ ├── breadcrumbs.php
│ │ │ └── css/breadcrumbs.css
│ │ ├── reading-time/
│ │ │ ├── reading-time.php
│ │ │ └── css/reading-time.css
│ │ ├── share-buttons/
│ │ │ ├── share-buttons.php
│ │ │ ├── css/share-buttons.css
│ │ │ └── js/share-buttons.js
│ │ ├── author-box/
│ │ │ ├── author-box.php
│ │ │ └── css/author-box.css
│ │ └── related-posts/
│ │ ├── related-posts.php
│ │ └── css/related-posts.css
│ └── integrations/
│ ├── woocommerce/
│ │ ├── woocommerce.php
│ │ └── templates/
│ └── contact-form-7/
│ └── contact-form-7.php
├── demos/ # Demo content
│ ├── business/
│ │ ├── content.xml
│ │ ├── theme.json
│ │ ├── customizer.dat
│ │ └── widgets.wie
│ ├── blog/
│ │ ├── content.xml
│ │ ├── theme.json
│ │ └── customizer.dat
│ └── portfolio/
│ ├── content.xml
│ ├── theme.json
│ └── customizer.dat
└── templates/ # Template library
├── headers/
├── footers/
└── patterns/
Core Implementation: Main Plugin File
<?php
/**
* Plugin Name: Versana Companion
* Plugin URI: https://codoplex.com/plugins/versana-companion
* Description: Extends Versana theme with demo import, advanced features, and premium functionality
* Version: 1.0.0
* Author: CODOPLEX
* Author URI: https://codoplex.com
* License: GPL v2 or later
* Text Domain: versana-companion
* Domain Path: /languages
* Requires at least: 6.0
* Requires PHP: 7.4
* Requires Plugins: (none)
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Versana Companion Constants
*/
define( 'VERSANA_COMPANION_VERSION', '1.0.0' );
define( 'VERSANA_COMPANION_FILE', __FILE__ );
define( 'VERSANA_COMPANION_PATH', plugin_dir_path( __FILE__ ) );
define( 'VERSANA_COMPANION_URL', plugin_dir_url( __FILE__ ) );
define( 'VERSANA_COMPANION_BASENAME', plugin_basename( __FILE__ ) );
/**
* Main Versana Companion Class
*
* @class Versana_Companion
* @version 1.0.0
*/
final class Versana_Companion {
/**
* Singleton instance
*
* @var Versana_Companion
*/
private static $instance = null;
/**
* Get singleton instance
*
* @return Versana_Companion
*/
public static function instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
$this->init_hooks();
}
/**
* Initialize hooks
*/
private function init_hooks() {
add_action( 'plugins_loaded', array( $this, 'check_theme' ) );
add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
add_action( 'plugins_loaded', array( $this, 'init' ), 11 );
register_activation_hook( __FILE__, array( $this, 'activate' ) );
register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );
}
/**
* Check if Versana theme is active
*/
public function check_theme() {
$theme = wp_get_theme();
// Check if Versana or child of Versana
if ( 'Versana' !== $theme->name && 'Versana' !== $theme->parent_theme ) {
add_action( 'admin_notices', array( $this, 'theme_notice' ) );
return false;
}
return true;
}
/**
* Theme compatibility notice
*/
public function theme_notice() {
?>
<div class="notice notice-error is-dismissible">
<p>
<strong><?php esc_html_e( 'Versana Companion', 'versana-companion' ); ?></strong>
<?php esc_html_e( 'requires Versana theme to be active.', 'versana-companion' ); ?>
<a href="<?php echo esc_url( admin_url( 'themes.php' ) ); ?>">
<?php esc_html_e( 'Activate Versana Theme', 'versana-companion' ); ?>
</a>
</p>
</div>
<?php
}
/**
* Load plugin text domain
*/
public function load_textdomain() {
load_plugin_textdomain(
'versana-companion',
false,
dirname( VERSANA_COMPANION_BASENAME ) . '/languages'
);
}
/**
* Initialize plugin
*/
public function init() {
if ( ! $this->check_theme() ) {
return;
}
$this->includes();
$this->init_classes();
// Hook for other plugins/themes
do_action( 'versana_companion_loaded' );
}
/**
* Include required files
*/
private function includes() {
// Core classes
require_once VERSANA_COMPANION_PATH . 'includes/class-demo-importer.php';
require_once VERSANA_COMPANION_PATH . 'includes/class-content-cleanup.php';
require_once VERSANA_COMPANION_PATH . 'includes/class-theme-json-merger.php';
require_once VERSANA_COMPANION_PATH . 'includes/class-demo-library.php';
require_once VERSANA_COMPANION_PATH . 'includes/class-license-manager.php';
// Admin classes
if ( is_admin() ) {
require_once VERSANA_COMPANION_PATH . 'includes/admin/class-admin-page.php';
}
// Features (conditionally load based on settings)
$features = get_option( 'versana_companion_features', array(
'breadcrumbs' => true,
'reading_time' => true,
'share_buttons' => true,
'author_box' => true,
'related_posts' => true,
) );
if ( ! empty( $features['breadcrumbs'] ) ) {
require_once VERSANA_COMPANION_PATH . 'includes/features/breadcrumbs/breadcrumbs.php';
}
if ( ! empty( $features['reading_time'] ) ) {
require_once VERSANA_COMPANION_PATH . 'includes/features/reading-time/reading-time.php';
}
if ( ! empty( $features['share_buttons'] ) ) {
require_once VERSANA_COMPANION_PATH . 'includes/features/share-buttons/share-buttons.php';
}
if ( ! empty( $features['author_box'] ) ) {
require_once VERSANA_COMPANION_PATH . 'includes/features/author-box/author-box.php';
}
if ( ! empty( $features['related_posts'] ) ) {
require_once VERSANA_COMPANION_PATH . 'includes/features/related-posts/related-posts.php';
}
// Integrations
if ( class_exists( 'WooCommerce' ) ) {
require_once VERSANA_COMPANION_PATH . 'includes/integrations/woocommerce/woocommerce.php';
}
}
/**
* Initialize classes
*/
private function init_classes() {
// Initialize admin if in admin
if ( is_admin() ) {
Versana_Companion_Admin::init();
}
// Initialize demo importer
new Versana_Demo_Importer();
}
/**
* Activation hook
*/
public function activate() {
global $wpdb;
// Create database tables
$charset_collate = $wpdb->get_charset_collate();
// Demos table
$sql_demos = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}versana_demos (
id INT AUTO_INCREMENT PRIMARY KEY,
demo_key VARCHAR(50) UNIQUE NOT NULL,
demo_name VARCHAR(100) NOT NULL,
demo_description TEXT,
demo_category VARCHAR(50),
is_pro BOOLEAN DEFAULT 0,
preview_url VARCHAR(255),
thumbnail_url VARCHAR(255),
content_url VARCHAR(255),
theme_json_url VARCHAR(255),
required_plugins TEXT,
demo_version VARCHAR(20),
downloads INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_category (demo_category),
INDEX idx_is_pro (is_pro)
) $charset_collate;";
// Installs tracking table
$sql_installs = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}versana_demo_installs (
id INT AUTO_INCREMENT PRIMARY KEY,
demo_key VARCHAR(50),
user_id INT,
site_url VARCHAR(255),
installed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
status VARCHAR(20) DEFAULT 'completed',
INDEX idx_demo_key (demo_key),
INDEX idx_user_id (user_id)
) $charset_collate;";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql_demos );
dbDelta( $sql_installs );
// Set default options
add_option( 'versana_companion_version', VERSANA_COMPANION_VERSION );
add_option( 'versana_companion_features', array(
'breadcrumbs' => true,
'reading_time' => true,
'share_buttons' => true,
'author_box' => true,
'related_posts' => true,
) );
// Populate demos library
$this->populate_demo_library();
// Flush rewrite rules
flush_rewrite_rules();
}
/**
* Populate demo library on activation
*/
private function populate_demo_library() {
global $wpdb;
$demos = array(
array(
'demo_key' => 'business',
'demo_name' => 'Business',
'demo_description' => 'Professional business website with services and portfolio',
'demo_category' => 'business',
'is_pro' => 0,
'preview_url' => 'https://demos.codoplex.com/versana/business/',
'thumbnail_url' => VERSANA_COMPANION_URL . 'assets/images/demos/business.jpg',
'content_url' => VERSANA_COMPANION_URL . 'demos/business/content.xml',
'theme_json_url' => VERSANA_COMPANION_URL . 'demos/business/theme.json',
'required_plugins' => '',
'demo_version' => '1.0.0',
),
array(
'demo_key' => 'blog',
'demo_name' => 'Personal Blog',
'demo_description' => 'Clean and minimal blog layout perfect for writers',
'demo_category' => 'blog',
'is_pro' => 0,
'preview_url' => 'https://demos.codoplex.com/versana/blog/',
'thumbnail_url' => VERSANA_COMPANION_URL . 'assets/images/demos/blog.jpg',
'content_url' => VERSANA_COMPANION_URL . 'demos/blog/content.xml',
'theme_json_url' => VERSANA_COMPANION_URL . 'demos/blog/theme.json',
'required_plugins' => '',
'demo_version' => '1.0.0',
),
array(
'demo_key' => 'portfolio',
'demo_name' => 'Portfolio',
'demo_description' => 'Showcase your work with a beautiful portfolio layout',
'demo_category' => 'portfolio',
'is_pro' => 0,
'preview_url' => 'https://demos.codoplex.com/versana/portfolio/',
'thumbnail_url' => VERSANA_COMPANION_URL . 'assets/images/demos/portfolio.jpg',
'content_url' => VERSANA_COMPANION_URL . 'demos/portfolio/content.xml',
'theme_json_url' => VERSANA_COMPANION_URL . 'demos/portfolio/theme.json',
'required_plugins' => '',
'demo_version' => '1.0.0',
),
);
foreach ( $demos as $demo ) {
$wpdb->insert(
$wpdb->prefix . 'versana_demos',
$demo,
array( '%s', '%s', '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s' )
);
}
}
/**
* Deactivation hook
*/
public function deactivate() {
// Cleanup if needed
flush_rewrite_rules();
}
}
/**
* Initialize Versana Companion
*
* @return Versana_Companion
*/
function versana_companion() {
return Versana_Companion::instance();
}
// Initialize
versana_companion();
Demo Import Process Flow
User clicks "Import Demo" button
↓
Modal appears with options:
- "Remove existing content?" (checkbox)
- "Install required plugins?" (auto-checked)
↓
User clicks "Start Import"
↓
Progress bar shows steps:
↓
[Step 1: Cleanup] ████░░░░░░ 10%
Removes existing posts, pages, media (if selected)
↓
[Step 2: Plugins] ████████░░ 80%
Installs & activates required plugins
↓
[Step 3: Content] ████████░░ 30%
Imports posts, pages, media from XML
↓
[Step 4: Settings] ██████████ 40%
Applies theme.json settings
↓
[Step 5: Customizer] ████████ 50%
Imports customizer options
↓
[Step 6: Widgets] ██████████ 60%
Sets up widget areas
↓
[Step 7: Menus] ████████████ 70%
Creates and assigns navigation menus
↓
[Step 8: Pages] ████████████ 80%
Sets homepage and blog page
↓
[Step 9: Finalize] ██████████ 90%
Flush rewrite rules, regenerate thumbnails
↓
[Complete!] ████████████████ 100%
↓
Success message + redirect to homepage
Part 4: Implementing Premium Features
License Management System
<?php
/**
* License Manager Class
* Handles Pro license verification
*
* @package Versana_Companion
*/
class Versana_License_Manager {
/**
* API endpoint for license verification
*/
const API_URL = 'https://api.codoplex.com/v1/license';
/**
* License option key
*/
const LICENSE_KEY = 'versana_pro_license';
/**
* License status option key
*/
const LICENSE_STATUS_KEY = 'versana_pro_license_status';
/**
* Check if user has valid Pro license
*
* @return bool
*/
public static function has_valid_license() {
$license = get_option( self::LICENSE_KEY );
$status = get_option( self::LICENSE_STATUS_KEY );
if ( empty( $license ) ) {
return false;
}
// Check cached status first (valid for 24 hours)
if ( isset( $status['valid'] ) && isset( $status['expires'] ) ) {
if ( $status['expires'] > time() ) {
return $status['valid'];
}
}
// Verify with server
return self::verify_license( $license );
}
/**
* Verify license with server
*
* @param string $license License key
* @return bool
*/
public static function verify_license( $license ) {
$response = wp_remote_post( self::API_URL . '/verify', array(
'body' => array(
'license' => $license,
'site_url' => home_url(),
'version' => VERSANA_COMPANION_VERSION,
),
'timeout' => 10,
) );
if ( is_wp_error( $response ) ) {
return false;
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! isset( $body['valid'] ) ) {
return false;
}
// Cache result for 24 hours
update_option( self::LICENSE_STATUS_KEY, array(
'valid' => $body['valid'],
'expires' => time() + DAY_IN_SECONDS,
'plan' => $body['plan'] ?? 'free',
) );
return $body['valid'];
}
/**
* Activate license
*
* @param string $license License key
* @return array Result with success/error
*/
public static function activate_license( $license ) {
$response = wp_remote_post( self::API_URL . '/activate', array(
'body' => array(
'license' => $license,
'site_url' => home_url(),
'version' => VERSANA_COMPANION_VERSION,
),
'timeout' => 15,
) );
if ( is_wp_error( $response ) ) {
return array(
'success' => false,
'message' => $response->get_error_message(),
);
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( isset( $body['success'] ) && $body['success'] ) {
update_option( self::LICENSE_KEY, $license );
update_option( self::LICENSE_STATUS_KEY, array(
'valid' => true,
'expires' => time() + DAY_IN_SECONDS,
'plan' => $body['plan'] ?? 'pro',
) );
return array(
'success' => true,
'message' => __( 'License activated successfully!', 'versana-companion' ),
);
}
return array(
'success' => false,
'message' => $body['message'] ?? __( 'License activation failed.', 'versana-companion' ),
);
}
/**
* Deactivate license
*
* @return array Result
*/
public static function deactivate_license() {
$license = get_option( self::LICENSE_KEY );
if ( empty( $license ) ) {
return array(
'success' => false,
'message' => __( 'No license to deactivate.', 'versana-companion' ),
);
}
$response = wp_remote_post( self::API_URL . '/deactivate', array(
'body' => array(
'license' => $license,
'site_url' => home_url(),
),
'timeout' => 15,
) );
// Remove license regardless of API response
delete_option( self::LICENSE_KEY );
delete_option( self::LICENSE_STATUS_KEY );
return array(
'success' => true,
'message' => __( 'License deactivated successfully!', 'versana-companion' ),
);
}
/**
* Get license info
*
* @return array License information
*/
public static function get_license_info() {
$license = get_option( self::LICENSE_KEY );
$status = get_option( self::LICENSE_STATUS_KEY );
if ( empty( $license ) ) {
return array(
'has_license' => false,
'valid' => false,
'plan' => 'free',
);
}
return array(
'has_license' => true,
'valid' => $status['valid'] ?? false,
'plan' => $status['plan'] ?? 'free',
'license' => substr( $license, 0, 4 ) . '****' . substr( $license, -4 ),
);
}
}
Part 5: Monetization Strategy
Pricing Model
Tier 1: Free (Forever Free)
Versana Theme + Companion (Free)
├── Everything in core theme
├── 3 starter demo templates
├── One-click demo import
├── Breadcrumbs navigation
├── Reading time calculator
├── Social share buttons (basic)
├── Author bio box
├── Related posts (basic)
├── 20+ block patterns
└── Community support (forum)
Target: Build user base
Goal: 5,000+ installs Year 1
Tier 2: Pro ($49/year – Single Site)
Everything in Free +
├── 20+ premium demo templates
├── Industry-specific demos
├── WooCommerce full integration
├── Dark mode system
├── Table of contents (auto)
├── Mega menu builder
├── Header/footer builder
├── Advanced typography (1000+ fonts)
├── Premium block patterns (100+)
├── Performance dashboard
├── Priority support (< 24hr)
└── 1 year updates
Target: 2% conversion
Goal: 100 customers Year 1
Revenue: $4,900/year
Tier 3: Agency ($149/year – Unlimited Sites)
Everything in Pro +
├── Unlimited site installations
├── White-label options
├── Client management dashboard
├── Reseller license
├── Remove branding
├── Premium support (< 12hr)
├── Direct Slack channel
└── Lifetime updates
Target: Agency users
Goal: 10 customers Year 1
Revenue: $1,490/year
Revenue Projections
Conservative Scenario (Realistic):
Year 1:
- 5,000 free installs
- 2% conversion to Pro = 100 customers
- Pro: 100 × $49 = $4,900
- Agency: 10 × $149 = $1,490
- Total: $6,390 ARR
Year 2: (10x user base)
- 50,000 free installs
- 2% conversion = 1,000 Pro
- Pro: 1,000 × $49 = $49,000
- Agency: 50 × $149 = $7,450
- Total: $56,450 ARR
Year 3:
- 100,000 free installs
- 2% conversion = 2,000 Pro
- Pro: 2,000 × $49 = $98,000
- Agency: 100 × $149 = $14,900
- Total: $112,900 ARR
Optimistic Scenario (If Viral):
Year 1:
- 20,000 free installs
- 3% conversion = 600 Pro
- Total: $29,400 ARR
Year 2:
- 100,000 free installs
- 3% conversion = 3,000 Pro
- Total: $147,000 ARR
Year 3:
- 300,000 free installs
- 3% conversion = 9,000 Pro
- Total: $441,000 ARR
Why $49/Year Works
Market Research:
| Theme/Plugin | Price | Model |
|---|---|---|
| GeneratePress Premium | $59/year | Single site |
| Kadence Pro | $59/year | Single site |
| Blocksy Pro | $49/year | Single site |
| Astra Pro | $59/year | Single site |
Psychology:
- Under $50 = impulse buy territory
- Annual = recurring revenue
- Single site = accessible to bloggers
- Agency tier = targets different market
Value Proposition:
User invests: $49/year
User gets:
- 20+ premium demos (worth $500+ if built custom)
- WooCommerce integration (worth $200+)
- All pro features (worth $300+)
- Priority support (worth $100+)
- Regular updates (worth $100+)
Total value: $1,200+
Price: $49
ROI: 24x value
Part 6: Implementation Roadmap
Phase 1: Foundation (Months 1-2)
Month 1: Plugin Structure
Week 1-2: Set up plugin architecture
- Create plugin boilerplate
- Set up file structure
- Implement autoloading
- Add activation/deactivation hooks
Week 3-4: Core functionality
- Database tables
- Admin menu system
- Settings API integration
- Basic feature toggles
Month 2: Demo Import Core
Week 5-6: Import system
- Content import (WordPress Importer)
- theme.json merger
- Customizer import
- Widget import
Week 7-8: Demo creation
- Create Business demo
- Create Blog demo
- Create Portfolio demo
- Test import process
Phase 2: Features & Polish (Month 3)
Week 9-10: Basic Features
- Implement breadcrumbs
- Implement reading time
- Implement share buttons
- Implement author box
- Implement related posts
Week 11-12: Polish & Testing
- UI/UX refinement
- Bug fixes
- Performance testing
- Documentation
- Beta testing
Phase 3: Launch (Month 3, Week 13)
Week 13: Free Plugin Launch
Day 1-2: Final testing
Day 3: Submit to WordPress.org
Day 4-5: Create marketing materials
Day 6-7: Launch announcement
Phase 4: Pro Development (Months 4-5)
Month 4: Licensing & Premium Demos
Week 14-15: License system
- API server setup
- License verification
- Activation/deactivation
- Pro feature gates
Week 16-17: Premium demos
- Create 10 premium templates
- Industry-specific designs
- E-commerce layouts
- Agency portfolios
Month 5: Pro Features
Week 18-19: WooCommerce integration
- Product layouts
- Shop templates
- Cart styling
- Checkout optimization
Week 20-21: Advanced features
- Dark mode system
- Table of contents
- Mega menu builder
- Header/footer builder (basic)
Phase 5: Pro Launch (Month 6)
Week 22-24: Pro Launch Preparation
Week 22: Testing & refinement
Week 23: Documentation & tutorials
Week 24: Marketing & launch
Timeline Summary
┌─────────────────────────────────────────────────────┐
│ Versana v2.0 Timeline │
├─────────────────────────────────────────────────────┤
│ Month 1-2: Plugin development & demo import │
│ Month 3: Free plugin launch │
│ Month 4-5: Pro features development │
│ Month 6: Pro version launch │
├─────────────────────────────────────────────────────┤
│ Total Time: 6 months from start to Pro launch │
│ Revenue Start: Month 6 │
│ Break-even: Month 8-10 (based on projections) │
└─────────────────────────────────────────────────────┘
Part 7: Marketing Strategy
Pre-Launch (Months 1-2)
Build Anticipation:
- Blog posts about development progress
- Sneak peeks on social media
- Build email list (early access)
- Create demo site
- Engage in WordPress communities
Launch (Month 3)
Free Plugin Launch:
Day 1: WordPress.org submission
Day 2-3: Announcement on:
- Your blog
- Twitter/X
- Facebook
- LinkedIn
- Reddit (r/Wordpress, r/webdev)
- WordPress communities
Day 4-7: Outreach
- Submit to theme/plugin directories
- Contact WordPress bloggers
- Reach out to YouTubers
- Post in Facebook groups
Growth (Months 4-6)
Content Marketing:
- Tutorial videos on YouTube
- Blog posts (2-3/week)
- Case studies
- User testimonials
- Documentation site
- Free webinars
Pro Launch (Month 6)
Premium Launch:
- Special launch pricing (limited time)
- Email campaign to free users
- Demo all pro features
- Social media campaign
- Affiliate program launch
- Partner with influencers
Part 8: Success Metrics & KPIs
Month 3 (Free Launch) Goals
□ Plugin installs: 1,000+
□ Active installs: 500+
□ Demo imports: 200+
□ Rating: 4.5+ stars
□ Support response: < 24 hours
□ Bug reports: < 5 critical
□ Documentation: Complete
Month 6 (Pro Launch) Goals
□ Free installs: 5,000+
□ Pro customers: 100+
□ Revenue: $5,000+
□ Churn rate: < 5%
□ Support satisfaction: 90%+
□ Pro features: All launched
□ Premium demos: 10+
Year 1 Goals
□ Free installs: 50,000+
□ Pro customers: 1,000+
□ Annual revenue: $50,000+
□ Reviews: 50+ (4.5+ average)
□ YouTube subscribers: 1,000+
□ Email list: 5,000+
□ Affiliate partners: 20+
Conclusion
Building a WordPress theme companion plugin is the strategic path to transforming your theme from a simple WordPress.org listing into a sustainable, profitable theme ecosystem. By separating core functionality from premium features, you create a win-win situation: users get a fast, lightweight theme with optional enhancements, and you build a business with recurring revenue.
What We’ve Learned
- Architecture Matters – Companion plugin beats all-in-one theme
- Demo Import is King – One-click import drives conversions
- Free Builds Trust – Give real value upfront
- Pro Creates Revenue – Clear upgrade path at $49/year
- Execution is Everything – Follow the 6-month roadmap
Key Takeaways
For a successful WordPress theme companion plugin:
✅ Keep core theme minimal (performance)
✅ Build free companion first (user base)
✅ Focus on demo import (killer feature)
✅ Launch pro after validation (revenue)
✅ Price competitively ($49/year)
✅ Provide excellent support (retention)
✅ Update regularly (trust)
✅ Market consistently (growth)
Next Steps
Starting Next Episode (Episode 30):
- Create plugin boilerplate structure
- Set up database tables
- Build admin interface
- Implement demo library system
- Create first free demo template
- Test import process
- Launch beta version
Resources
WordPress Plugin Development:
- Plugin Handbook: https://developer.wordpress.org/plugins/
- Plugin Review Guidelines: https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/
- REST API: https://developer.wordpress.org/rest-api/
Inspiration:
- Blocksy Companion: https://wordpress.org/plugins/blocksy-companion/
- Kadence Blocks: https://wordpress.org/plugins/kadence-blocks/
- Starter Templates: https://wordpress.org/plugins/astra-sites/
Frequently Asked Questions
Q: Why not just add features to the core theme? A: Bloated themes perform poorly, get rejected by WordPress.org, and frustrate users who don’t need all features. Separation is key to success.
Q: How long does it take to build a companion plugin? A: With our roadmap, 3 months for free version, 6 months total for Pro. Can be faster with a team.
Q: What if users don’t upgrade to Pro? A: That’s expected! Even 2% conversion at scale is profitable. Focus on volume with free, quality with Pro.
Q: Do I need a license server? A: Yes, for Pro features. You can use Freemius, EDD Licensing, or build your own (we’ll cover this in Episode 31).
Q: Can I charge more than $49/year? A: You can, but $49 is the sweet spot for conversions. Start there, increase based on value added.
Q: How do I handle support for both free and Pro? A: WordPress.org forums for free, email/Slack for Pro. Different tiers, different response times.
Q: What if someone copies my demos? A: GPL means they can. Focus on execution, support, and regular updates. Your service is the moat, not the code.
Q: Should I offer lifetime licenses? A: No. Annual recurring revenue is more sustainable. Lifetime licenses cannibalize future revenue.
Next Episode: We’ll start building the Versana Companion plugin, beginning with the plugin structure, database setup, and admin interface.
Series: WordPress Block Theme Development – Building Versana
Episode: 29 of ongoing series (v2.0 development begins)



Leave a Reply