1. Home
  2. Documentation
  3. Selling with Freemius
  4. Version Deployment

Version Deployment

There are two main reasons why Freemius manages its own repository and deployment process:

  1. To be able to securely serve premium plugin/theme downloads and updates to customers who own a valid license.
  2. To simplify code management by allowing developers to maintain only one code base which contains all of their plugin/theme functionality. A free, WordPress.org compliant version is automatically generated for them, using a custom PHP Preprocessor.

Deploying to Freemius

  1. Login to your Freemius Dashboard and head over to the Deployment section.
  2. Zip your plugin’s or theme’s root folder and upload it by clicking the [ + Add New Version] button, located at the top.

Here’s what is going to happen:

  1. In case you forgot to clear your secret_key and sandbox related code, our PHP Processor will automatically remove it for you.
  2. The same processor will auto-generate two versions of your plugin:
  • A premium version: One that’s identical to your uploaded version, which includes all of the code (excluding the secret_key). Will be enabled for download ONLY for customers with a valid license (paid or trial).
  • A free version: The same code, stripped from all of your paid features (based on the logic added with { method }__premium_only()). This stripped down version is what your users will be able to download first.
    In case your original plugin is compatible with the official WordPress.org guidelines – the new, free version, will also be compatible, as all premium code was stripped.

The premium version will not be available for download or update for your customers untill you change the release status to Released. If you have a beta program, you can also flag the release as Beta release to make it only available for customers who are part of the beta program.

If you already developed free and premium versions that are fundamentally different, you can either merge the versions into a single code base or ignore the free version generated by Freemius. If you go with the 2nd option, make sure also to integrate the SDK into your free version and set the is_premium flag to false to indicate the SDK that it is running in the scope of the free version.

Deployment Automation

freemius-suite: a Python based Bash library for packaging, deployment, and releasing a new product version via Freemius.

Credits: Created & maintained by Daniele Scasciafratte from Codeat

gulp-freemius-deploy: a niffty Gulp NPM library for packaging and deploying a new product version via Freemius.

Credits: Createad & maintained by James Kemp from IconicWP

Free Version Auto Generation / Premium Logic Stripping / PHP Preprocessor

The deployment PHP Preprocessor will automatically strip out any premium code – based on the following rules:

Stripping Premium Only PHP Logic

All logic within the if statements containing usage of license related methods with the __premium_only suffix will automatically be stripped from the free version.

// This IF block will be auto removed from the Free version.
if ( my_fs()->is__premium_only() ) {
    // This IF will be executed only if the user in a trial mode or have a valid license.
    if ( my_fs()->can_use_premium_code() ) {
    // ... premium only logic ...
    }
}

// This "if" block will be auto removed from the Free version.
if ( my_fs()->is_plan__premium_only('starter') ) {
    // ... logic related to starter plan and higher plans ...
}

Stripping Premium Only CSS & JavaScript Logic

Simply wrap the code you’d like to exclude with the following meta comments:

(function($){
    /*! <fs_premium_only> */

    // ... my premium only code ...

    /*! </fs_premium_only> */
})(jQuery);

In the future, we’ll provide a richer JavaScript SDK which will handle license-related logic in a similar manner to how our PHP SDK does it.

Developing a Gutenberg or JavaScript driven plugin with webpack?

To preserve Freemius meta comments from being stripped by webpack’s uglifyjs, configure webpack.config.js as follows:

module.exports = {
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        uglifyOptions: {
          output: {
            comments: /\<\/?fs_premium_only\>/i,
          },
        },
        extractComments: true,
      }),
    ],
  },
};

Stripping Premium Only PHP Functions

To add a function which will only be available in your premium plugin version, simply add the __premium_only suffix to the function’s name. Make sure that all lines that call that method either directly, or by using hooks, are also wrapped in the premium only logic:

class My_Plugin {
    function init() {
        ...
        
        // This "if" block will be auto removed from the free version.
        if ( my_fs()->is__premium_only() ) {
            // Init premium version.
            $this->admin_init__premium_only();
        
            add_action( 'admin_init', array( &$this, 'admin_init_hook__premium_only' );
        }
        
        ...
    }

    // This method will be only included in the premium version.
    function admin_init__premium_only() {
        ...
    }
    
    // This method will be only included in the premium version.
    function admin_init_hook__premium_only() {
        ...
    }
}

Stripping Premium Only Files/Folders

There are two ways to exclude files from your free version:

  1. Add __premium_only just before the file extension. For example: functions__premium_only.php will only be included in the premium plugin/theme version. This works for all type of files, not only for PHP.
  2. For plugins, add @fs_premium_only (a special meta tag) to the plugin’s main PHP file header. Example:
    /**
    * Plugin Name: My Awesome Plugin
    * Plugin URI:  http://my-awesome-plugin.com
    * Description: Create and manage Awesomeness right in WordPress.
    * Version:     1.0.0
    * Author:      Awesomattic
    * Author URI:  http://my-awesome-plugin.com/me/
    * License:     GPLv2
    * Text Domain: myplugin
    * Domain Path: /langs
    *
    * @fs_premium_only /lib/functions.php, /premium-files/
    */
    
    if ( ! defined( 'ABSPATH' ) ) {
        exit;
    }
    
    // ... my code ...
    

    The file /lib/functions.php and the directory /premium-files/ will be removed from the free plugin version.

  3. For themes, add @fs_premium_only, a special meta tag, to the themes’s main style.css file header. Example:
    /**
    * Theme Name: My Awesome Theme
    * Theme URI:  http://my-awesome-theme.com
    * Description: Create and manage Awesomeness right in WordPress.
    * Version:     1.0.0
    * Author:      Awesomattic
    * Author URI:  http://my-awesome-theme.com/me/
    * License:     GPLv2
    * Text Domain: mytheme
    *
    * @fs_premium_only /premium-functions.php, /premium-files/
    */
    
    body { ... }
    span { ... }
    

Ignoring Folders Processing

If your product has a lot of code and/or many files, we created a special @fs_ignore meta tag to direct the PHP Preprocessor to ignore a given collection of folders which you know doesn’t include any files or folders that need processing. For example, if you have a vendors folder with 3rd party libraries that should remain untouched in both the free and paid versions, that folder would be a great candidate for the @fs_ignore tag.

For plugins, add @fs_ignore to the plugin’s main PHP file header, similar to the @fs_premium_only example above.

For themes, add @fs_ignore to the theme’s style.css stylesheet, also similar to the @fs_premium_only example above.

Handling Premium readme.txt

In case you have a premium-only product (without a free version), the WordPress SDK will fetch it from our API instead of WordPress.org. For freemium plugins and themes, just like you only need to maintain a single version of your product, we’ve built a special markdown-friendly syntax to control which pieces of your readme.txt will show up only on the free version, only on the premium version, or on both.

Premium-only readme.txt Content

If you wish to add some content which should only appear for the paid version, use the following syntax in your readme.txt:

[//]: # fs_premium_only_begin
Whatever goes in here will only appear in the premium readme
[//]: # fs_premium_only_end

Free-only readme.txt Content

For content to appear only inside the free version use the following syntax in your readme.txt:

[//]: # fs_free_only_begin
Whatever goes in here will be only in the free readme
[//]: # fs_free_only_end

Common readme.txt Content

Content that will not be wrapped with any of the above will simply appear on both the free and the premium readme.txt files.

Freemium readme.txt Example

If you deploy a freemium product with the following readme:

=== My Awesome Product ===
Requires at least: 3.0
Tested up to: 4.9
Stable tag: 3.1.0
License: GPLv2 or later

== Description ==

This is the best product ever!

== Installation ==

1. Upload the product to your blog.
2. Activate it.
[//]: # fs_premium_only_begin
3. Enter the license key you received after the purchase and activate it.
[//]: # fs_premium_only_end

== Change Log ==

[//]: # fs_premium_only_begin
= 1.0.0 =
* New: New premium feature!
[//]: # fs_premium_only_end
[//]: # fs_free_only_begin
= 1.0.0 =
* New: New free feature!
[//]: # fs_free_only_end

The free readme.txt will look like this:

=== My Awesome Product ===
Requires at least: 3.0
Tested up to: 4.9
Stable tag: 3.1.0
License: GPLv2 or later

== Description ==

This is the best product ever!

== Installation ==

1. Upload the product to your blog.
2. Activate it.

== Change Log ==

= 1.0.0 =
* New: New free feature!

And the premium readme.txt will look like this:

=== My Awesome Product ===
Requires at least: 3.0
Tested up to: 4.9
Stable tag: 3.1.0
License: GPLv2 or later

== Description ==

This is the best product ever!

== Installation ==

1. Upload the product to your blog.
2. Activate it.
3. Enter the license key you received after the purchase and activate it.

== Change Log ==

= 1.0.0 =
* New: New premium feature!