Feature Gating

Feature gating lets you conditionally enable functionality in your plugin or theme based on the customer's licence tier. Define feature slugs per price tier in the admin, then check them at runtime with the client library's has_feature() method.

How features are stored

Features are stored as a JSON array in the features column of the wplf_product_prices table. The column type is longtext and holds a serialized JSON array of string slugs.

["core", "advanced-analytics", "priority-support", "white-label"]

In the admin UI, you enter features as plain text with one slug per line. LicenceForge converts the newline-separated list to a JSON array on save and back to newline-separated text when editing.

Features textarea in the price tier row showing one slug per line
The features textarea accepts one slug per line. Use lowercase slugs with hyphens.

Defining feature slugs

Feature slugs are arbitrary strings that you define. Use a consistent naming convention:

Slug Description Tiers
core Base plugin functionality Personal, Pro, Agency
advanced-analytics Extended reporting and analytics module Pro, Agency
priority-support Access to priority support channels Pro, Agency
white-label Remove branding and use custom logos Agency
premium-templates Access to premium template library Pro, Agency

Tip

Use hyphenated lowercase slugs (e.g. priority-support, not Priority Support). This keeps feature checks consistent and avoids case-sensitivity issues.

Checking features in your plugin

The client library provides two methods for feature-aware logic:

has_feature()

Returns true if the current licence tier includes the specified feature slug.

$license = WPLF_Client::instance( 'my-plugin' );

if ( $license->has_feature( 'advanced-analytics' ) ) {
    // Load the analytics module
    require_once __DIR__ . '/modules/analytics.php';
}

if ( $license->has_feature( 'white-label' ) ) {
    // Remove plugin branding
    add_filter( 'my_plugin_show_branding', '__return_false' );
}

get_features()

Returns an array of all feature slugs included in the current licence tier. Useful for bulk checks or debugging.

$license  = WPLF_Client::instance( 'my-plugin' );
$features = $license->get_features();
// ['core', 'advanced-analytics', 'priority-support']

get_tier_label()

Returns the human-readable tier label (e.g. "Pro", "Agency"). Useful for displaying the current plan in settings screens.

$license = WPLF_Client::instance( 'my-plugin' );
$tier    = $license->get_tier_label();
// "Pro"

How it works internally

  1. When the client library validates a licence (via /wplf/v1/license/validate), the API response includes the tier's feature array.
  2. The client caches the validation response locally (including the feature list).
  3. has_feature() reads from the cached status and checks whether the slug exists in the tier's feature array using in_array() with strict comparison.
  4. The result is filterable via the wplf_client_has_feature filter, allowing developers to override feature access programmatically.
// Override feature access regardless of tier
add_filter( 'wplf_client_has_feature', function ( $has, $feature_slug, $product_slug ) {
    // Grant white-label to all tiers during a promotional period
    if ( 'white-label' === $feature_slug && 'my-plugin' === $product_slug ) {
        return true;
    }
    return $has;
}, 10, 3 );

Static helper

If you need a quick one-liner without instantiating the client, use the static helper:

if ( WPLF_Client::has_feature( 'advanced-analytics' ) ) {
    // Feature is available
}

The static method resolves the correct client instance internally using the product slug or falls back to the first registered instance.

Warning

Feature checks depend on a valid, cached licence status. If the licence has never been validated (e.g. the site has no internet access and no cache exists), has_feature() returns false for all features. Ensure your plugin handles this gracefully.

Next steps