Recipe: Gate a sibling plugin behind entitlement

Goal

Bootstrap a sibling plugin only when:

  1. mam-main is installed and active
  2. mam-main is at the required version
  3. The customer is entitled to use this plugin

Background

mam-main exposes two filters for sibling-plugin gating:

  • mam_check_required_version — checks whether a plugin is at a sufficient version
  • mam_plugin_entitlement — checks the WPMAM entitlement record for a plugin slug

A well-behaved sibling plugin checks both before bootstrapping its hooks. A poorly-behaved one bootstraps unconditionally and produces fatal errors when mam-main isn’t loaded — or worse, runs on un-entitled customer sites.


Steps

1. Wrap your bootstrap in a plugins_loaded callback at priority 11

mam-main runs its register_*() chain on its own constructor (called early). By priority 11 on plugins_loaded, mam-main’s hooks are registered and its filters are answerable.

add_action( 'plugins_loaded', 'mam_my_plugin_bootstrap', 11 );

2. Check the required version

function mam_my_plugin_bootstrap() {

    $required_version = '1.9.1';
    if ( ! apply_filters( 'mam_check_required_version', false, 'mam-main', $required_version ) ) {
        // mam-main is too old or missing.
        add_action( 'admin_notices', 'mam_my_plugin_required_version_notice' );
        return;
    }

    // ... continue
}

The mam_check_required_version filter returns true if the named plugin is at or above the required version.

3. Check entitlement

function mam_my_plugin_bootstrap() {

    // ...required version check...

    $entitlement = apply_filters( 'mam_plugin_entitlement', false, 'mam-my-plugin' );

    if ( ! $entitlement ) {
        // No entitlement record — customer isn't licensed for this plugin.
        return;
    }

    if ( ! empty( $entitlement['blocked'] ) ) {
        // Entitlement was revoked — silently skip.
        return;
    }

    if ( ! empty( $entitlement['expired'] ) ) {
        // Past expiry — show admin notice but don't bootstrap.
        add_action( 'admin_notices', 'mam_my_plugin_expired_notice' );
        return;
    }

    // ... bootstrap functional code
}

4. Bootstrap your plugin

function mam_my_plugin_bootstrap() {
    // ...gate checks...

    // OK to bootstrap.
    new MAM_My_Plugin_Manager();
}

Common admin-notice patterns

function mam_my_plugin_required_version_notice() {
    echo '<div class="notice notice-warning"><p>';
    echo 'MAM My Plugin requires MAM Main version 1.9.1 or later.';
    echo '</p></div>';
}

function mam_my_plugin_expired_notice() {
    echo '<div class="notice notice-error"><p>';
    echo 'MAM My Plugin entitlement has expired. Contact support to renew.';
    echo '</p></div>';
}

Show notices only on admin pages where they’re useful — guard with is_admin() and screen checks if needed.


Caching the gate decision

The entitlement filter is cached on the mam_entitlement_manager side, so calling it once on bootstrap is fine. Don’t re-check on every request:

// Good — bootstrap-time check, cached for the session
function mam_my_plugin_bootstrap() {
    $entitlement = apply_filters( 'mam_plugin_entitlement', false, 'mam-my-plugin' );
    if ( ! $entitlement ) return;
    // ...
}

// Bad — checking on every request
add_filter( 'some_hook', function ( $value ) {
    $entitlement = apply_filters( 'mam_plugin_entitlement', false, 'mam-my-plugin' );  // ← redundant
    if ( ! $entitlement ) return $value;
    // ...
} );

What “entitled” means

The entitlement record is per-customer-site and per-plugin. A site might have:

  • Some plugins entitled, others not
  • A plugin entitled at one tier (basic) but not another (premium)
  • An entitlement that expires and renews via WPMAM
  • An entitlement that’s been blocked by support

Your plugin should respect the record’s flags (blocked, expired) and adapt accordingly.


Gotchas

  • Priority 11 on plugins_loaded. Not 10 — at priority 10, mam-main’s register_*() chain hasn’t necessarily completed.
  • Don’t bootstrap on file include. Wait for plugins_loaded so mam-main is loaded.
  • Entitlement can change at runtime. A plugin that bootstraps once per request and caches the gate decision in PHP memory will not pick up a same-request entitlement change. Acceptable for most cases; if your plugin needs to react to revocation, use a longer-running mechanism (cron + invalidation).
  • WPMAM unreachability can produce stale entitlement reads. The graceful-degradation hook (mam_account_code_verify_fallback-style) typically defaults to “still entitled” during planned outages — confirm behavior with WPMAM ops.
  • Don’t try to “auto-recover” from blocked entitlement. A blocked entitlement means contact support.

  • Extending mam-main: developer guide
  • Integration: Account code and enrollment server
  • Hook: mam_plugin_entitlement
  • Frozen public contracts reference

Metadata

Field Value
Article type Recipe (Developer)
Plugin slug mam-main
Applies to plugin version 2.1.11+
Category Extending MAM Suite
Audience PHP developer
Estimated time 15 minutes
Last verified 2026-05-02
Contents

    Need Support?

    Can’t find the answer you’re looking for? Don’t worry we’re here to help!