MemberPressBridge
Benecaster\Bridge\Bridges\MemberPressBridge
The built-in bridge for MemberPress. This is both a functional bridge used in production and the canonical reference implementation to read when building a custom bridge. Its source illustrates how a real bridge translates between a membership plugin’s data model and the BridgeInterface contract.
Slug: memberpress
Detection: class_exists('MeprUser') — true when MemberPress is active.
Tier Resolution
get_user_tier( int $user_id, int $show_id ) works as follows:
- Calls
MeprUser::active_product_subscriptions('ids')to retrieve all MemberPress product IDs with an active subscription for the user. - Iterates the returned IDs in order (most-recently-activated first).
- For each product ID, looks up a matching row in
benecaster_tier_mapwhereplugin_slug = 'memberpress'andexternal_tier_idmatches the product ID. - Filters to rows where
show_idmatches the given$show_id. - Returns the
internal_tier_slugof the first matching row, ornullif none matches.
The first match wins. If a subscriber holds multiple MemberPress memberships that are both mapped to tiers for the same show (an unusual configuration), the most-recently-activated membership determines the tier.
Required setup: At least one row must exist in benecaster_tier_map with plugin_slug = 'memberpress' and external_tier_id matching a MemberPress product ID, pointing to an internal_tier_slug for the target show. Without a mapped row, get_user_tier() always returns null even for active subscribers. See Mapping Your Membership Tiers.
Tier Listing
get_all_tiers( int $show_id ) returns all published MemberPress membership products (post_type = 'memberpressproduct'), site-wide. The $show_id parameter is accepted but not used — MemberPress membership levels are not scoped to a show.
Each entry is array{id: int, name: string, price: float}, where id is the product’s post ID, name is the product title, and price is the product’s price. A price of 0.00 marks the tier as free — it will not count toward the Benecaster license tier limit. This list populates the tier mapping UI.
Tier Save Events
on_tier_saved() hooks into MemberPress’s membership product save pipeline via the WordPress post save hook filtered to memberpressproduct post type. The same hook fires for both new product creation and updates (including price changes). Specific hook name TBD — verify against MemberPress docs before implementation (candidate: save_post_memberpressproduct). Fires the callback with array{id: int, name: string, price: float}.
MemberPress Hooks
MemberPressBridge hooks into the following MemberPress actions to relay subscription events to Benecaster:
| MemberPress hook | Bridge event | Notes |
|---|---|---|
mepr-signup |
on_subscription_activated |
New initial subscription. Receives MeprTransaction. Source: 'new'. |
mepr-event-subscription-resumed |
on_subscription_activated |
Reactivated previously cancelled subscription. Receives MeprEvent resolving to MeprSubscription. Source: 'resubscribe'. |
mepr-event-subscription-stopped |
on_subscription_cancelled |
Subscription cancelled. Receives MeprEvent resolving to MeprSubscription. |
mepr-event-transaction-completed |
on_subscription_renewed |
All successful charges. Callback fires only when a parent subscription exists (sub->id > 0) to skip initial sign-up transactions already handled by mepr-signup. |
mepr-event-subscription-paused |
on_payment_failed |
Fires after grace period elapses without a successful retry. Receives MeprEvent resolving to MeprSubscription. |
Known Limitation: No Native Tier-Change Event
MemberPress does not fire a native event when a subscriber upgrades or downgrades between membership levels. As a result, on_subscription_changed() in MemberPressBridge is a documented no-op — it registers no hooks and the passed callback is never called.
Tier changes in MemberPress happen via a cancel + re-subscribe flow. MemberPress fires a cancellation event on the old membership and an activation event on the new one. This means Benecaster receives on_subscription_cancelled followed by on_subscription_activated in sequence. The net effect is correct — the subscriber ends up on the new tier — but the benecaster_subscription_tier_changed action is not fired in this flow.
Code that depends on benecaster_subscription_tier_changed will not see tier changes from MemberPress subscribers. Use benecaster_subscription_activated with $source = 'resubscribe' as the closest available signal. State-diffing on mepr-event-transaction-completed is a future enhancement.
This is documented behavior. When building a custom bridge for a plugin that also lacks a tier-change event, implement on_subscription_changed() as an empty method — the same pattern used here.
Setup Notes
Benecaster handles the bridge connection and tier mapping through its Settings UI. No custom code is needed to use MemberPressBridge — it is configured, connected, and tested entirely through the admin interface.
See MemberPress Setup for the complete setup walkthrough, including how to connect the bridge, map tiers, and test the connection.