Black Friday: 30% OFF on all plans, applied automatically at checkout View plans
Log in Cart

Paid Memberships Pro Changelog

Every recorded version, newest first, with what changed in each one.

Latest 3.9 · Oct 27, 20269 versionsSince Jul 2026

2026 · 9 versions

  1. 3.9

    Latest
    7 new23 improvements10 security
    New
    • Merged the Subscription Delays Add On into core. The new First Recurring Payment setting on levels and custom pricing discount codes can delay the first recurring payment by a number of days or until a date set with a date pattern. #3630 (@dparker1005, @kimcoleman)
    • Merged the Set Expiration Dates Add On into core. Levels and custom pricing discount codes can expire memberships on a date set with a date pattern. #3630 (@dparker1005, @kimcoleman)
    • Added percentage and fixed amount discount code types alongside the existing per-level custom pricing. The discount is calculated from each level's current pricing and can apply to the initial payment, recurring payments, or both, while the billing cycle, trial, and expiration come from the level. #3727 (@dparker1005)
    • Added a migration tool for deprecated gateways, opened from the "Migrate Subscriptions Off This Gateway" button on the gateway's Payment Settings page. It recreates active subscriptions at Stripe (or sets the memberships to expire), can email members, cancels the old gateway subscriptions, and supports a dry run. A final step deletes the gateway's stored API credentials and stops loading the gateway; orders and subscriptions are kept. #3700 (@dparker1005)
    • Added WordPress Abilities API support (WordPress 6.9+) for querying membership levels, orders, subscriptions, and PMPro search results, and for viewing, changing, and cancelling a member's memberships. Abilities are available over the REST API and to MCP clients through an MCP adapter plugin. #3736, #3757 (@mircobabini, @dparker1005)
    • Added a `wp pmpro` WP-CLI command set for memberships, members, levels, orders, and subscriptions, and the `pmpro_cli_init` action for Add Ons to register their own commands. #3740, #3757 (@flintfromthebasement, @dparker1005)
    • Added `/pmpro/v1/memberships`, `/pmpro/v1/orders`, and `/pmpro/v1/subscriptions` REST API collection endpoints with filtering, sorting, and pagination. #3740, #3757 (@flintfromthebasement, @dparker1005)
    Improved
    • Added an "Awaiting Payment Method" filter and tag on the Subscriptions list, an admin notice, and a Membership Account page notice for subscriptions migrated to Stripe that have no payment method on file. The default Recurring Payment Reminder email now asks these members to add a payment method. #3700 (@dparker1005)
    • Added the "Deprecated Gateway Stripe Migration" and "Deprecated Gateway Checkout Required" email templates, shown on sites that still use a deprecated gateway. #3700 (@dparker1005)
    • The "Update Billing Info" links on the Membership Account and Billing pages no longer require the subscription to have an order. The Billing page link now only shows for subscriptions on the active gateway when that gateway supports payment method updates, matching the Membership Account page. #3700 (@dparker1005)
    • Added the `pmpro_deprecated_gateway_batch_size` filter to set how many subscriptions the deprecated gateway migration processes per batch. #3700 (@dparker1005)
    • Added a captcha to the login and lost password forms, including wp-login.php, when reCAPTCHA or Cloudflare Turnstile is enabled. The captcha is only shown after a failed login or other suspicious activity from the visitor's IP address in the last 15 minutes. #3765 (@dparker1005)
    • Replaced the separate reCAPTCHA and Cloudflare Turnstile settings with a single Captcha setting on the Security Settings page, so only one captcha runs at a time. Existing settings carry over, and sites that had both enabled now use reCAPTCHA. Added the `pmpro_captcha_services` filter for registering other captcha services. #3765 (@dparker1005)
    • Added the `pmpro_login_form_before_submit_button` action and the `pmpro_authenticate_login_checks`, `pmpro_login_forms_handler_message`, and `pmpro_login_forms_handler_msgt` filters to the login flow. #3765 (@dparker1005)
    • A failed payment at checkout or on the Update Billing page now requires a new reCAPTCHA or Cloudflare Turnstile check before the next attempt. Thanks to Freelance Studio for the report. #3885, #3887 (@dparker1005)
    • Membership Account page now shows when a membership's latest payment is past due and shows a card for memberships with a pending checkout that is waiting on payment. #3714 (@kimcoleman, @dparker1005)
    • Added the `pmpro_membership_account_after_pending_level_card_content` action for adding content to a pending membership card on the Membership Account page. #3714 (@kimcoleman, @dparker1005)
    • Added an optional Advanced Setting to automatically delete abandoned checkout users (Potential Spam Checkouts) after 30 days. Users with any membership history, users who can edit posts, and users who have written posts are never deleted. Added the `pmpro_abandoned_signup_deletion_days` filter to change the retention period. #3737, #3901 (@dparker1005)
    • Added Status, Usage and Level filters to the Discount Codes admin page. #3896 (@dparker1005)
    • Added a date filter (All Time, Last 7 Days, Last 30 Days, Last 12 Months, or a custom range) to the Email Log report. #3692 (@dwanjuki)
    • The Email Log now records the file names of email attachments and shows them in the log details and the personal data exporter. #3773 (@faisalahammad)
    • Added the `{{ billing_update_url }}` email template variable to the Payment Failure email and linked to the Billing page in its default body. #3892 (@dparker1005)
    • The Admin Activity Email now reports active members and active memberships as separate numbers when they differ. #3768 (@flintfromthebasement, @dparker1005)
    • Added Product/Offer JSON-LD structured data for membership levels on the levels page, the checkout page, and pages using the Single Membership Level block. It can be turned off with the Structured Data setting on the Advanced Settings page, and developers can customize it with the new `pmpro_structured_data_*` filters. #3735 (@flintfromthebasement, @dparker1005)
    • Added an optional Level Image setting on the edit level page, used as the product image in membership level structured data. #3735, #3906 (@flintfromthebasement, @dparker1005)
    • Added Elementor v4 (atomic elements) support to PMPro content restriction controls. Added the `pmpro_elementor_atomic_element_types` filter to change which atomic elements support restriction. #3709 (@dparker1005)
    • Added a new `pmpro_view_as` capability so the "View As" toolbar in the admin bar can be granted to roles that should not have `manage_options`. #3786 (@faisalahammad)
    • Added the `pmpro_memberslist_sortable_columns` and `pmpro_memberslist_sql_join` filters and made the First Name and Last Name columns sortable in the Members List. #3805, #3902 (@faisalahammad, @dparker1005)
    • Improved Members List performance for the default and single-level views by no longer grouping rows when each row is already one member and level. Added the `pmpro_members_list_group_rows` filter so custom code that adds joins through `pmpro_members_list_sql` can turn grouping back on. #3833 (@flintfromthebasement)
    • Added the `pmpro_is_page` function to safely check PMPro pages, with optional shortcode and block detection for custom pages. #3810 (@faisalahammad, @dparker1005)
    Security
    • Improved escaping and SQL query preparation throughout the plugin. #3827 (@dparker1005)
    • Added direct file access protection to plugin files. #3828 (@dparker1005)
    • Improved request input handling and redirect safety throughout the plugin. #3829 (@dparker1005)
    • The Authorize.net gateway now verifies TLS certificates when connecting to Authorize.net. #3916 (@dparker1005)
    • The 2Checkout gateway now verifies TLS certificates when sending API requests. #3917 (@dparker1005)
    • The `[pmpro_member]` shortcode is now also removed from newly added post meta saved by users who cannot edit users. #3921 (@dparker1005)
    • The REST API order endpoint now only includes order notes for users with the `pmpro_orders` capability. #3918 (@dparker1005)
    • Values in the members, orders, and logins report CSV exports that start with a spreadsheet formula character are now prefixed with a single quote so they are not run as formulas. #3922 (@dparker1005)
    • The admin redirect for missing members, orders, subscriptions, discount codes, and levels now only runs for users who can access the Memberships menu. #3920 (@dparker1005)
    • The Billing page now redirects to the Membership Account page when the requested subscription does not exist. #3919 (@dparker1005)
  2. 3.8.9

    4 improvements22 fixes1 security
    Improved
    • Added the `pmpro_account_profile_list_items` filter to customize the profile items on the Membership Account page. The Username and Email items now also have their own CSS classes. #3870 (@dparker1005)
    • Added edit and view page buttons to the Terms of Service setting. #3881 (@dparker1005)
    • Applying an empty discount code at checkout now shows an error message. #3866 (@dparker1005)
    • When an admin refund fails, the notice now includes the payment gateway's error message. #3883 (@dparker1005)
    Fixed
    • Fixed the membership required message showing twice on restricted content when Elementor and Yoast SEO are both active. #3879 (@dparker1005)
    • Restricted Elementor widgets are no longer rendered as empty styled containers for users without access. #3875 (@dparker1005)
    • Fixed the level confirmation message losing its paragraph formatting in checkout emails. #3861 (@dparker1005)
    • Fixed the default "More Information" heading not showing for the checkout_boxes field group, and the `pmpro_default_field_group_label` filter being ignored. #3859 (@dparker1005)
    • Fixed a deprecation notice when using the `pmpro_default_field_group_label` filter. The legacy `pmprorh_section_header` filter is now the one flagged as deprecated. #3888 (@dparker1005)
    • Textarea user field values now keep their line breaks when displayed. #3878 (@dparker1005)
    • Fixed `[pmpro_account]` shortcode attributes being ignored when the same page also has a `[pmpro_account]` shortcode or Membership Account block without attributes. #3877 (@dparker1005)
    • PMPro page settings are now cleared when the assigned page is trashed or deleted, and restored if the page is restored from the trash. #3872 (@dparker1005)
    • Page Settings no longer shows edit and view buttons for an assigned page that isn't published. #3886 (@dparker1005)
    • Renew links and the redirect for already-submitted orders now use the `pmpro_level` URL parameter instead of `level`. #3876 (@dparker1005)
    • Gateway cancellations now cancel memberships for members whose level is hidden by the `pmpro_has_membership_level` filter, such as unconfirmed Email Confirmation members. #3867 (@dparker1005)
    • Gateway cancellations for deleted users are no longer logged as errors. #3882 (@dparker1005)
    • Fixed fatal errors when checkout email or password fields were submitted as arrays. #3855 (@dwanjuki)
    • Recurring levels now save a billing cycle number of at least 1. #3865 (@dparker1005)
    • Deleting an order now also deletes its order meta. #3869 (@dparker1005)
    • Deleting an order now keeps all Orders list filters, sorting and the current page. #3868 (@dparker1005)
    • Paginating or sorting after deleting a discount code or order no longer repeats the delete request. #3863 (@dparker1005)
    • The personal data exporter now shows array user meta as readable text instead of serialized data. #3860 (@dparker1005)
    • Fixed a PHP warning in `pmpro_has_membership_access` when the post doesn't exist. #3862 (@dparker1005)
    • Failed AJAX and REST API logins no longer redirect to the login page. #3864 (@dparker1005)
    • The Logins report now tracks visits after a member logs in or out. #3871 (@dparker1005)
    • The membership section and Edit Member link are now hidden on Network Admin user profiles. #3880 (@dparker1005)
    Security
    • Fixed an issue where a failed Cloudflare Turnstile check allowed later checkout and billing update submissions in the same session to skip the security check. #3884 (@dparker1005, Freelance Studio)
  3. 3.8.8

    1 improvement7 fixes4 security
    Improved
    • Pending checkout uploads are now deleted when their order is deleted. #3847 (@dparker1005)
    Fixed
    • Fixed a fatal error when changing membership levels while WP Fusion Lite is active but not connected to a CRM. #3834 (@andrewlimaza)
    • Checkout now stops with an error when the chosen username could not be used to log in, instead of silently saving a different username. #3837 (@faisalahammad)
    • Fixed the file field Delete button showing to all users when `allow_delete` was set to `admins`. #3847 (@dparker1005)
    • Fixed user field file uploads being rejected when the file extension's case did not match the field's allowed file types. #3850 (@dparker1005)
    • Fixed a PHP warning and a missing file extension on temporary upload files for checkouts that are completed later, such as Stripe Checkout and PayPal Express. #3851 (@dparker1005)
    • Fixed export downloads failing when a plugin filters `random_password` to add special characters to generated passwords. #3849 (@dparker1005)
    • Stripe webhooks no longer try to update a subscription's application fee on sites using API keys, which logged failed requests in Stripe. #3852 (@flintfromthebasement)
    Security
    • Files uploaded through user fields are now stored in uniquely named folders, and are deleted when the user is deleted. #3847 (@dparker1005, @GrayOM)
    • Fixed restricted post excerpts showing in RSS feeds, embeds, and the Post Excerpt block when "Show Excerpts to Non-Members" is off. #3853 (@dparker1005, @Feldspar-AI-Agent)
    • The member edit screen's User Info panel now requires permission to edit the specific user being edited, and only accepts a password when creating a new user. #3835 (@dparker1005)
    • User fields can no longer save to the user meta key that stores roles and capabilities. #3848 (@dparker1005)
  4. 3.8.7

    3 improvements12 fixes5 security1 removed
    Improved
    • Added a Stripe connection test to the payment settings page that checks daily and on demand whether Stripe and the Paid Memberships Pro Connect server can be reached and whether Stripe accepts the saved keys, with an admin notice when a key is rejected. #3792 (@dparker1005)
    • Added additional PHP file extensions to the default extension blocklist for the `getfile` script. #3798 (@dparker1005, @kta1kri)
    • Members List username row actions now use the same markup as the other PMPro list tables. #3817 (@kimcoleman)
    Fixed
    • Connecting to Stripe now refuses to overwrite an existing connection with a different Stripe account. #3792 (@dparker1005)
    • The Stripe webhook notice no longer reports a missing webhook when Stripe is actually rejecting the saved credentials. #3792 (@dparker1005)
    • Refunding an order whose charge was already refunded in the Stripe dashboard now marks the order as refunded instead of failing. #3811 (@dparker1005)
    • Fixed Stripe webhook errors for `charge.failed` and `charge.refunded` events when another plugin loads an older version of the Stripe library. #3796 (@faisalahammad)
    • Guest comments no longer show the post author's PMPro avatar. #3822 (@flintfromthebasement)
    • Membership managers can now print order invoices. #3807 (@faisalahammad)
    • The Pay by Check gateway description now reflects that orders are marked as paid at checkout, and links to the Pay by Check Add On for manual payment approval. #3802 (@faisalahammad)
    • Fixed quotes in email template variable descriptions showing as HTML entities in the editor autocomplete. #3818 (@dparker1005)
    • The required asterisk is now shown only once on radio user fields. #3795 (@faisalahammad)
    • Fixed the styling of the Export to CSV button on admin list pages when it is rendered as a button. #3824 (@kimcoleman)
    • Expanded rows in the Orders, Members, Subscriptions, and Discount Codes list tables now take the full table width on mobile. #3816 (@faisalahammad, @kimcoleman)
    • The PMPro admin banner no longer overlaps the Screen Options and Help tabs on small screens, and list table row actions are tidied on mobile. #3815 (@kimcoleman)
    Security
    • Fixed a REST API authorization bypass where route capability checks were case-sensitive while WordPress routes are not. #3823 (@andrewlimaza, @kta1kri)
    • PayPal Express, Website Payments Pro, Payflow Pro, and PayPal Standard API requests now verify PayPal's SSL certificate. #3830 (@dparker1005, @kta1kri)
    • PayPal gateway error messages for invalid API responses no longer include the API request, which contained the merchant's API credentials. #3830 (@dparker1005, @kta1kri)
    • Fixed an issue where the Orders admin search could be used to modify the database query. #3825 (@dparker1005)
    • Added a missing capability check to the Setup Wizard save handler so it only runs for users with the `pmpro_wizard` capability. #3784 (@faisalahammad)
    Removed
    • Deprecated `PMPro_AddOns::http_request_args_for_addons`, which no longer changes request arguments. #3831 (@dparker1005)
  5. 3.8.6

    3 improvements5 fixes
    Improved
    • Changed the "Edit Membership" button on the Edit Member memberships panel to "Update Membership" to make it clear that it saves the level change. #3781 (@flintfromthebasement)
    • The password visibility toggle now shows only the eye icon in the log in widget and on narrow screens so the field label and the toggle no longer wrap into each other. #3769 (@kimcoleman)
    • Wisdom tracking data now reports whether the site is running on PMPro Hosting. #3770 (@dparker1005)
    Fixed
    • Stripe Connect sites now refresh the platform publishable key from Paid Memberships Pro instead of using the key saved during the initial connection forever, so onsite checkout keeps working after the platform key is rotated. #3791 (@flintfromthebasement)
    • Liquid tags that the visual email template editor wrapped in paragraph tags no longer produce empty or unbalanced paragraphs in sent emails. #3782 (@dparker1005)
    • The 3.8.4 upgrade script no longer fires order update hooks (e.g. Zapier) for every order whose Stripe transaction IDs were recovered. #3790 (@dparker1005)
    • Fixed the Stripe Connect environment lookup in `has_connect_credentials` so that Site Health checks the credentials for the active gateway environment, and avoided a PHP notice after a failed Stripe Connect disconnect response. #3777 (@flintfromthebasement)
    • The "Error:" prefix in Stripe Connect failure notices now renders in bold instead of as literal HTML. #3774 (@flintfromthebasement)
  6. 3.8.5

    1 improvement1 fix3 security
    Improved
    • Removed the notices on the Stripe payment settings recommending the deprecated Add PayPal Express Add On. #3751 (@flintfromthebasement)
    Fixed
    • Guarded the `pmpro_setMessage` calls in `PMPro_AddOns` so that activating Paid Memberships Pro while the Update Manager Add On is active no longer causes a fatal error. #3763 (@dparker1005)
    Security
    • Fixed an issue where the payment amount was not re-verified after Strong Customer Authentication (3D Secure) in the Stripe on-site checkout. #3767 (@proxydom)
    • Fixed an access check bypass in the `getfile` service that could allow protected files to be served through `admin-ajax.php` without a membership access check. #3762 (@dparker1005)
    • Added missing capability and nonce checks to several admin AJAX and service handlers. #3758 (@flintfromthebasement)
  7. 3.8.4

    1 improvement3 fixes
    Improved
    • Added new `--pmpro--btn--border-radius`, `--pmpro--btn--top-bottom-padding`, and `--pmpro--btn--left-right-padding` CSS variables so that button styles can be customized separately from other elements that share the base variables. #3747 (@RachelRVasquez)
    Fixed
    • Fixed an issue where Stripe Checkout orders paid with delayed notification payment methods such as SEPA Direct Debit could be completed without their subscription and payment transaction IDs, which prevented membership cancellations from being sent to Stripe. An upgrade script now recovers the missing IDs for previously affected orders. #3745 (@dparker1005)
    • Fixed an issue where a user field could be shown at checkout even though its field group was hidden from checkout if the field overrode the group's profile visibility setting. #3744 (@dparker1005)
    • Fixed an issue where duplicate recurring scheduled tasks, such as those inherited from a cloned or migrated database, would run simultaneously indefinitely. Duplicate chains are now cancelled automatically, keeping the earliest scheduled task. #3746 (@dalemugford)
  8. 3.8.3

    3 improvements5 fixes
    Improved
    • Site Health now detects the PMPro SMTP Add On as the site's email sending service when a connector is configured. #3729 (@dparker1005)
    • Added translator comments to localized strings containing placeholders so translators have context for each variable. #3730 (@jahidhasan018)
    • The discount code lookup in `PMPro_Discount_Code::save` now uses `$wpdb->prepare`. #3734 (@andrewlimaza)
    Fixed
    • Multi-value user fields (multiselect, select2, and grouped checkboxes) now display correctly when their values were imported from a CSV file as a comma-separated string. #3742 (@flintfromthebasement)
    • Fixed a fatal error that could occur when returning from an offsite gateway if the checkout data was missing from the order meta. #3741 (@dparker1005)
    • Set `new_version` on `no_update` entries so up-to-date Add Ons no longer trigger an undefined property warning in WP-CLI and other consumers of the plugin update transient. #3738 (@dalemugford)
    • The bulk user delete confirmation screen now counts membership history for every selected user instead of only the first. #3733 (@jahidhasan018)
    • The level group selection message is no longer shown on the Membership Levels page for groups that contain only one level. #3731 (@jahidhasan018)
  9. 3.8.2

    4 fixes2 security
    Fixed
    • Read-only user fields are no longer saved on form submission and are now escaped when displayed. This also fixes read-only checkbox and select field values being erased on profile update. #3726 (@dparker1005)
    • Fixed broken CSV exports when an exported value contained a quotation mark. #3716 (@dwanjuki)
    • Fixed checkout failures that could occur when the matching Stripe price had been archived in the Stripe dashboard. #3717 (@flintfromthebasement)
    • Fixed an issue where users with the `pmpro_reports` capability could not view email content in the Email Log popup. #3718 (@dwanjuki)
    Security
    • Restored sanitization of user field values on save, which had been inactive since v3.4. #3726 (@dparker1005)
    • The Authorize.net Silent Post handler now requires Authorize.net API credentials to be configured on the site. #3724 (@dparker1005)

Changelog published by the developer, in their original language.