How to enable debugging on your WordPress site.

Enable Debugging on Your WordPress SiteIs your site no longer working? Has your WordPress site been replaced with a blank white screen, the infamous White Screen of Death? Maybe you are experiencing styling issues, your footer is not loading correctly, or you are having a tough time checking out of your site. This is not unique to Paid Memberships Pro and can occur on any website, using any theme or any plugin(s). Knowing what is causing the problem can give you or a developer the relevant information needed to help fix these issues.

Whatever the reason, this article will explain how to enable debugging mode in WordPress to uncover any PHP errors or warning messages that are on your site.

Turning WP_DEBUG Mode on.

WP_DEBUG is a PHP constant (a permanent global variable) that can be used to trigger the “debug” mode throughout WordPress. It is assumed to be false by default and is usually set to true in the wp-config.php file on development copies of WordPress.”  WP DEBUG, WordPress Codex

  1. Before getting started you will need to be able to access your WordPress site files by means of an FTP Client or your website’s control panel.
  2. To turn WP_Debug mode on, navigate to your wp-config.php file (found in your WordPress install directory), edit the file using a text editor of your choice. Once the file is open, search for the following line of code define( 'WP_DEBUG', false ); and change the value from false to true. If you do not find the WP_DEBUG line of code in your wp-config.php file, you can simply add it toward the bottom of the file. It is usually placed below the table prefix, but certainly above the /* That's all, stop editing! Happy blogging. */ line.

With WP_DEBUG turned on, errors will be displayed right on your homepage, so your site may appear broken (or more broken). Copy the entire error message down to share with the support team or developer working on your site.

Fatal Error Example

To hide the errors again, change WP_DEBUG mode back to false. It is often acceptable to turn on WP_DEBUG, navigate to your site and copy the error, and finally navigate back to your wp-config.php file and turn off WP_DEBUG. When dealing with a live site, any visitors who were browsing your site would be interrupted by the error/message notification. It’s important to hide those errors again as quickly as possible or use the instructions below to send the errors to a log file that only you can see.

Turning off errors that would otherwise display on-screen.

By default, WP_DEBUG will display all errors and notification to your screen. This is not ideal in many cases as the notification/errors will replace the actual webpages of your site with the error messages. To stop errors and messages from displaying on your screen, you can add the following line of code to your wp-config.php file, just under the WP_DEBUG line: define( 'WP_DEBUG_DISPLAY', false )

With this constant set to false, errors are not displayed on screen but are still saved to your web server’s PHP error log. You can set a specific error log for WordPress errors using the steps below.

Making a Debug log file.

Along with WP_DEBUG, you can use WP_DEBUG_LOG , this will save all errors and notifications to a debug.log file that you can use as a reference of any errors/php notifications. You can also use this file to send to any developer or support engineer who is working on your site. In the event that there were no errors found, a debug.log file will not be created.

Simply add the following line of code to your wp-config.php file under the other WP_DEBUG constants: define( 'WP_DEBUG_LOG', true )

Accessing the Debug.log File

Once you have added the define( 'WP_DEBUG_DISPLAY', false ) line of code to your wp-config.php file , you will find the debug.log by navigating to your wp-content folder found in the WordPress install directory. You will need to access this part of your website by using a FTP client or through your websites control manager.

Important: Once done with your debug.log file, disable WP_DEBUG mode and delete the debug.log file from your site immediately. Not doing so may result in compromising the security of your site or exposing sensitive information to unwanted parties.


What it looks like all together.

Now that you have added all the lines of code to your wp-config.php file, you should have something similar to the below coding example:

WordPress Debugging – Summarized

  1. Login to your site via FTP or your host’s File Manager.
  2. Navigate to your WordPress install directory and enter it (usually public_html or www).
  3. Find the wp-config.php file and edit with a text editor of your choice. Some popular text editors to use are: Atom, Sublime 3 and PHPStorm
  4. Search the file for the following line of code: define( ‘WP_DEBUG’, false );
  5. Change this value from false to true. This will now output errors to your site by displaying them right on your homepage, so instead of your site you will see any underlying errors. To get your website back, change WP_DEBUG mode back to false.
  6. Directly below this you can enter two new lines of code to send errors to a log file:
    • define( ‘WP_DEBUG_DISPLAY’, false );
    • define( ‘WP_DEBUG_LOG’, true );
  7. Save your file and re-upload to the same directory – overwrite the file when prompted. (Do not close your FTP client just yet).
  8. Go back to your website using your browser and recreate the issue.
  9. Head back on over to your FTP client and navigate to wp-content and expand the folder, your debug.log file will be loaded into this directory if there are any PHP errors.
  10. Download the debug.log file. Feel free to send this log file onto your support engineer.
  11. For a more detailed guide on debugging in WordPress, have look at the WordPress codex.

This looks tough – I need help.

If you are uncomfortable editing your wp-config.php file or are otherwise having trouble following these instructions, reach out to your hosting company for help. You can ask them the following in a support ticket or through email:

Can you tell me how to find the PHP error log for my website at and send me a list of the last 20 errors that have occurred?

Exactly how to access error logs varies depending on your host and server setup. Any good host should be able to respond to request above.

If you would like our help fixing a PMPro-related error on your site, we have a team of Support Engineers that are equipped to help you with your debugging questions. Feel free to get in touch with our team over on our Members Support Forum.

Access to Member Support Forums requires a PMPro Plus Account or higher.

View Membership Options

Setting up a Developer Account to Test Your Payment Gateway

Using Paid Memberships Pro in your selected payment gateway’s “testing/sandbox” mode allows you to test membership checkout without processing real payments. Sandbox mode requires unique credentials that vary based on the active payment gateway.

This post covers how to set up your test or sandbox account so that you can run tests on a membership checkout.

Testing your Payment Gateway.

Technically, all you need to do to start accepting payments on your site is sign up for a payment gateway and paste the appropriate API information into the Memberships > Payment Settings page in the WordPress admin of your site.

However, taking some time out to test your payment gateway first will not only give you peace of mind that the gateway is properly set up and ready to start receiving payments but it also gives you a good idea of how the gateway works and whether or not this gateway will be right for you and your members.

Setup Example: Stripe

Setting up a Stripe testing account is really quite simple. All you need to do is navigate to the Stripe Registration page, fill in the appropriate fields and click on the “Create your Stripe Account”.

Once your account is set up , you will be redirected to your Stripe Dashboard and an email will be sent to you asking you to verify your email address. Your Stripe testing account is now set up and you are (almost) ready to start testing it out on your website.

Note – in order to start using this account to accept actual payments, you will need to “Activate your account” from within the Stripe Dashboard.

Adding the test API keys to your website.

To add the relevant Stripe API keys to your website, you will need to navigate to the “API” tab in your Stripe Dashboard and copy both the “Publishable” and “Secret” API key and paste them into your Paid Memberships Pro payment gateway settings. This can be found by navigating to your WordPress Dashboard > Memberships > Payment Settings.

Note: Remember to set the payment gateway in your payment settings to Stripe and your “Gateway Environment” to “Sandbox/Testing”.

Once you have added your API keys, save your settings.

Processing a test checkout.

It is now time to do a test checkout. Log out of your website completely and proceed to purchase a membership level just as one of your potential customers would. You should eventually be redirected to your checkout page.

Fill out the checkout form as a normal user would and when you get to the “Payment Information” section, you will need to input a Stripe Testing Card number in order to process the test payment. If you do not use a Stripe testing card, you will receive a “Your card number is incorrect” error message.

Back to the Stripe Dashboard.

Once you have successfully processed the membership checkout, you will be able to navigate back to your Stripe Dashboard and see the test data as if it was an actual user who checked out of your site. Feel free to browse through the different menu options to get an overall feel for how this payment gateway works. The more you explore the gateway’s capabilities and limitations, the better idea you will have of whether or not a payment gateway will work for you.

Time to go live.

When you have done enough testing and you are now ready change over to a live environment, make sure that you change your “Gateway Environment” to “Live/Production” and complete the fields with your gateway’s appropriate information.

If you have not yet activated your Stripe account, you will need to do this before you can get your “Live” API keys. Live payments cannot be processed if your integration is still using your test API keys. Once you paste in your live API keys, save your changes.

Some useful links to get you started.

On Time Zones and Off By One Day Errors

Some sites report “off by one day” errors when calculating end dates on new orders and memberships. What this looks like on the front end is setting someone’s end date to January 31, 2017 and then having it show up as January 30, 2017. Or expiration is set to happen at 12:00am, but it happens at 10:00pm instead.

This post covers some common reasons why this is happening and a collection of ways to set the various time stamp settings in your web stack.

What’s really going on?

In most cases, “off by one day” errors occur when your web server, database server, and/or WordPress install are disagreeing about which timezone to use for calculating dates.

Getting everyone to “agree” on the time zone varies depending on your setup, specifically if you are on shared hosting and have limited access to your server. In this case you may not be able to configure the time zone for one or more of the services listed below. That being said, making some or all of the suggested updates can help to resolve these time zone errors.

Settings In WordPress

To change the timezone in WordPress go to Settings –> General in the admin dashboard. You can also set the date format here, which is used by PMPro when displaying dates.

Settings In CentOS/Linux

Here is an article explaining how to change your timezone in CentOS. Use the correct timezone file (browse around the /usr/share/zoneinfo directory), but generally you should run these two commands when logged in as root. (Note: don’t copy the #)

# mv /etc/localtime /etc/localtime.bak
# ln -s /usr/share/zoneinfo/America/New_York /etc/localtime

Settings In Apache/PHP

Typically you need to add or edit a line in your php.ini document. Here is a list of timezones at

date.timezone = “America/New_York”

Settings In MySQL

Log into MySQL as root and run this query: (More information on time zones in MySQL.)

SET time_zone = ‘America/New_York’;


Making sure that all of these settings are in sync will usually fix any “off by one day” errors going forward. Some issues will be fixed immediately after changing these settings. Other issues will still happen since the timestamps in the database were set when time zones were out of sync. You’ll have to run queries in your database to update time/date fields after your time zones have been set correctly.

Some hosts or server setups will have different methods for changing the time zones as above. Searching the knowledge base of your host or opening a support ticket there may help. If you find a new solution related to above, feel free to comment and we’ll try to expand on the information here to cover as many scenarios as we can.

If you are still having issues related to dates and time stamps, please post to our member forums and we can help you fix things for your specific setup.

Configuring WordPress to Always Use HTTPS/SSL

SSL encryption adds a layer of security to your website that makes it harder for malicious actors to collect personal information submitted through forms on your website.

This post will walk you through obtaining an SSL certificate (Let’s Encrypt or Other Providers), installing it on your web server (Let’s Encrypt or Other Providers), setting up your WordPress site to use HTTPS URLs, and fixing any “mixed content” type errors that come up when a page served over HTTPS links to non-HTTPS content.

Yes, you should use an SSL.

Setting your site up with an SSL certificate to serve pages over HTTPS doesn’t make you 100% secure against all of the kinds of attacks that can befall a website, but it should be done on nearly every site using Paid Memberships Pro.

The use of an SSL certificate is required by the PCI Security Standards Council on any site accepting credit cards [more] and is required by most gateways even if the checkout is completed “offsite”.

Starting this year, search engines like Google will begin to penalize the search rankings of sites without SSL certificates and web browsers like Chrome will start to show more severe warnings on pages with password or credit card fields if an SSL certificate is not active.

Step 0. Backup Everything

Before you get started, perform a full backup of your website. The steps outlined in this tutorial touch on your WordPress files, database, and even your server configuration. So be sure to back up your website at all levels: files, database, and server configuration.

More About Site Backups

Step 1. Get an SSL Certificate

Quick Note: When we refer to “SSL Certificates” in this post, we mean specifically a “third-party” SSL certificate. These are certificates that are validated by a trusted third party. You can also use what are called “self-signed” SSL certificates or “shared” SSL certificates, but only a third-party SSL certificate will avoid all browser warnings and fulfill all SSL-related gateway/PCI requirements.

The easiest way to get an SSL Certificate purchased and installed is to ask your web host to do it for you.

The details and cost of this are different for each host, but they will know exactly how to get your site served over HTTPS with a proper SSL certificate. Again, ignore “shared” or “self-signed” SSL options and make sure that you obtain a full trusted third-party SSL certificate.

If you manage your own server or otherwise want to do it yourself, you have a couple of options.

1a. Generate a Let’s Encrypt SSL Certificate

In 2016, a new (and free) way to obtain “third party” SSL certificates was introduced called Let’s Encrypt. From the Let’s Encrypt about page:

Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit. It is a service provided by the Internet Security Research Group (ISRG).

We give people the digital certificates they need in order to enable HTTPS (SSL/TLS) for websites, for free, in the most user-friendly way we can. We do this because we want to create a more secure and privacy-respecting Web.

Many web hosts are starting to offer Let’s Encrypt SSL certificates for free or at a reduced cost. If your host supports Let’s Encrypt, ask if they will set up the certificate for you. If your host won’t set it up, but you have SSH access to your web server (typical of dedicated or VPS-level hosting plans), you can generate the certificate yourself and setup your web server to use it.

The easiest way to generate and manage Let’s Encrypt SSL certificates is through a command line tool called Certbot.

The Certbot homepage allows you to choose your web server software (e.g. Apache) and your server’s operating system (e.g. Ubuntu Linux) and will give you instructions for using Certbot to setup a Let’s Encrypt SSL. Here are some instructions for using Certbot with Apache on Ubuntu 16.10:

  1. Make sure that your web server is setup with SSL support. For Apache, the module is called mod_ssl. On recent versions of Ubuntu, you can enable this by typing the following into your command line: (restart Apache when finished)
    $ sudo a2enmod ssl

    If this doesn’t work, you’ll want to talk with your host or search their docs for “enabling mod_ssl for Apache”.

  2. Second, use apt-get to install Certbot:
    $ sudo apt-get install python-certbot-apache
  3. Third, generate the certificate. (In my experience, Certbot has often failed to configure Apache properly after generating the certificate. So I’ve only used it with the “certonly” option. If you are confident, you can try without that option and it try to automatically update your Apache configuration to use the new certificate.)
    $ certbot --apache certonly

    Your terminal should then look something like this:

    Don’t be alarmed by the border of random letters (I was the first time!). It’s just an ASCII representation of a bounding box. Cerbot tries to detect what domains are setup on your server. If you see your domain, use the arrows keys to highlight it and hit enter to check it, then follow the instructions. If you don’t see the domain you want a certificate for, you can specify the domain in the Certbot command:

    $ certbot --apache certonly --domains

    When Certbot is finished, it will generate a cert.pem and privkey.pem file, typically at the following locations:

    • /etc/letsencrypt/live/
    • /etc/letsencrypt/live/
  4. Fourth, you need to update your Apache configuration to use the new certificate. The exact steps for this will depend on your Apache setup, but you may have an /etc/httpd/conf.d/vhost-ssl.conf file that looks like this or similar code in another Apache config file: (Note the SSLCertificateFile and SSLCertificateKeyFile lines.)

    This is a fairly typical Apache setup. This configuration says to detect traffic coming in via port 443 for the host and redirects that traffic to the …/httpdocs/ folder. This is the same folder as for port 80/regular HTTP traffic. Sometimes your site may be setup to use a different directory for HTTPS traffic. If so, you can have that directory “sym linked” to the regular directory or update your settings per the above. With WordPress, it’s best to serve both HTTP and HTTPS traffic from the same directory.

Now restart Apache to have the new settings go live. It’s a good idea to have backups of your Apache configuration files in case something goes wrong. Then you can switch your files back to the backups and restart Apache to have your site fixed ASAP. Find the error in the Apache (or other web server) error logs and see what might be wrong.

Let’s Encrypt SSL certificates only last 90 days.

To simplify the renewal process, you will want to setup a cron job to renew the certificate regularly. The command to do that is:

$ certbot renew --quiet

You can test it like this:

$ certbot renew --dry-run

And the cron job line to run this daily at 4:17am might look like this:

17 4 * * * certbot renew --quiet --post-hook "systemctl reload httpd"

1b. Purchase an SSL Certificate

If you don’t have SSH access to your web server, but do have a way to install SSL certificates (e.g. through a control panel), then you can purchase an SSL certificate from a “certificate authority” for use on your site. You may also want to purchase from a certificate authority if you want a Wildcard SSL, SAN SSL or other advanced SSL.

You will sometimes need to generate a Certificate Signing Request (CSR). You will have to validate that you control the domain through a standard email address like, an update to the site’s homepage, or a special DNS update. Once purchased and validated, you will be given one or more certificate files to install the SSL certificate. How you exactly install that certificate again depends on your host and/or your control panel software. Most control panels have easy to follow instructions for how to do so.

Here are some place where you can purchase and download SSL certificates:

  • SSL For Free (Uses Let’s Encrypt. Free but must be manually renewed every 90 days.)
  • GoDaddy (Expensive, but lots of options. Affiliate link.)
  • RapidSSL
  • AlphaSSL (Sign up for a reseller account for discounts if you plan to purchase many certificates for clients/etc.


Step 2. Tell WordPress Your Site URL is HTTPS://…

Once you have your SSL certificate installed on your web server, you can test it by going to https:// followed by your website URL.

If you get an error message, then your Apache configuration is probably incorrect. Make sure that you have mod_ssl installed, a valid SSL certificate, and the Apache VHOST configuration setup properly. See the notes above and check with your host.

When you visit the https:// URL of your site, you may be redirected to the http:// version of that URL. There are many systems that will try to force a website to use a certain “scheme” (HTTP or HTTPS). For example, if the “Force SSL” option in Paid Memberships Pro is turned on it will actually redirect away from the HTTPS version of a page for non-checkout pages. Other plugins may do similar redirects. And WordPress itself will sometimes try to force a “canonical” redirect to make sure that each page on your website has exactly one URL (this is good for SEO).

If you are using the Force SSL redirect option of PMPro or other plugins like WooCommerce, disable those features as they may interfere with your global SSL settings. When your full site is served over SSL, you won’t need them.

To get everything in WordPress to load over HTTPS is actually fairly straight forward. You simply navigate to the Settings -> General page in your admin, and then change both the “WordPress Address URL” and “Site Address URL” to have an https:// in front instead of an http://.

Important Note: After making this change, many things will happen. Many things may break. For starters, you will be logged out. This is because the cookie created when you login is usually specific to the HTTP or HTTPS “version” of your page. After WordPress is updated to use the HTTPS URL, you will have to login again to generate a new authentication cookie.

Many other things can break once your site is updated to server over HTTPS. Step 3 goes over the most common ones we’ve run into.

Step 3. Fix Everything That Broke

Here we’ll try to document some of the most common things that can break on a site that is being served over HTTPS.

Users can still access the http:// version of the site.

If your site is setup to serve all pages over HTTPS, you will need to redirect http:// URLs to https://. There are a few ways to do this, but we recommend adding a rule through your web server.

If you are using Apache, you can add this snippet to redirect any http traffic to the https version of the URL. Make sure to place this under your Rewrite Engine On and Rewrite Base lines:

If you are using the NGINX web server, here is the configuration you can use to redirect all HTTP traffic to HTTPS across all hosts. See Bjørn Johansen’s blog post on this topic for more details.

Pages timeout with “too many redirects” errors.

If you get a too many redirects error, what’s happening is some code somewhere is telling the browser to redirect to the HTTP version of the page. Then some other code is telling the browser to redirect to the HTTPS version of the page. What you need to do is figure out what code is trying to redirect to the HTTP version and then disable that.

  • Bad Plugin Settings

    We’ve already mentioned that you should disable the “Force SSL” option on the payment settings page of PMPro if your site is fully served over HTTPS, and PMPro should detect this anyway. Other ecommerce plugins or login/redirect plugins may have similar features that need to be disabled.

  • Bad PHP Server Values

    Another common issue is that some hosts or proxies (like Cloudflare or Sucuri CloudProxy) can sometimes make your traffic appear to be coming over HTTP instead of HTTPS. It’s pretty subtle, but basically WordPress has a function is_ssl() that checks if the PHP value $_SERVER[‘HTTPS’] is set to “on”. When using a proxy, this value might be set to “off” or not set at all.

    Here is some code you can add to your wp-config.php temporarily to test the $_SERVER values to see if they are setup correctly. Add this code to wp-condig.php and then navigate to https://

    The output should be something like this:

    Note the HTTPS value. If you are loading an HTTPS URL, but this value is set to “off”, “false”, or blank. Look for another value indicating the scheme being used. Many proxies will set the HTTP_X_FORWARDED_PROTO value and you add this code to your wp-config.php to copy that value into the HTTPS

  • Bad Plugin Code

    If you can’t even get into the admin to change this feature, you can disable plugins one by one by renaming the folders on the server to plugin-name-o or something similar. This will hide it from WP and that plugin won’t be loaded. If disabling a plugin fixes the issue, then you know that plugin is (at least partly) to blame for the redirect. You can read more about how to disable all plugins when locked out of the admin at WPBeginner here.

    What to do next depends on the plugin at fault. Whether it’s PMPro, one of our addons, or any other plugin, we will help you in our member forums to fix the issue. Note that sometimes these issues aren’t as straight forward as just programming things correctly the first time. Issues can arise due to conflicts between plugins, themes, or specific server settings. Be understanding with us and any plugin or theme developer you reach out to for help.

  • Bad Web Server Redirect Rules

    Consult section 3a above for some examples on how to redirect all traffic to the HTTPS URLs. If this redirect code is not correct or there is similar but conflicting code in your configuration, then infinite redirect loops can occur. Disable the redirect rules to see if that fixes things. Then try to figure out the correct rules for what you need.

Mixed Content Errors

When you load a web page over HTTPS, your web browser will block any content linked through an HTTP (non-secure) URL. WordPress and any properly coded plugins or themes will use “relative URLs” or otherwise attempt to detect whether a site is using SSL before outputting a URL and so will avoid this issue. However, if a URL is “hard coded” with a starting http:// in your blog posts, or a stylesheet, or a JavaScript file, or somewhere else… then these URLs will get blocked when a page is loaded over HTTPS.

You can notice mixed content errors because:

  • Your page may look funny as certain stylesheets, JavaScript scripts, images, or other files aren’t being loaded.
  • The green/gold/etc padlock in the upper left corner (or lower right corner) of your browser may appear red or yellow instead of green or as an ! instead of a padlock.
  • The Chrome/Safari/Firefox/Firebug debug bar “Console” will show errors.

In Chrome, you can view mixed content (and other errors) in the debug tools console by holding Ctrl + Shift + J on PCs or Cmd + Option + J on Macs. Other browsers have similar features. It will look like this:

Note the “Mixed Content” error at the bottom. The error message will tell you what resource/URL is being blocked. You can use context clues in the resource URL to figure out where that bad URL is coming from. If the file is located within your theme, then the problem is probably in your theme. If the file is located within a plugin folder, then the problem is probably in that plugin. If the file is in the uploaded folder, it might be hard coded into the post content. Another common situation is when theme settings, e.g. a header image, are saved into options. Some theme’s and plugins that save options like this save the full URL. You can usually clear out and reset these options to get a new HTTPS URL saved.

There are some plugins that can be used to fix most of these mixed content issues. On the PMPro payment settings page, you can check the “Extra HTTPS URL Filter” setting and PMPro will attempt to correct any non-HTTPS URLs being used on the site. You can also try the Really Simple SSL plugin or the WP Force SSL plugin, which have more complicated methods of fixing mixed content errors.

If you still see errors even after activating one of the above plugins, then you’ll have to fix the issues “manually”. Again, you can reach out to us in our member forums or reach out to the applicable plugin or theme developer to try to get a mixed-content issue fixed. Sometimes, it’s as easy as changing a URL. Sometimes a resource may be loaded from another server that doesn’t serve files over HTTPS at all. In these cases, you’ll need to stop using that service or find a work around.


I hope this document helps some of you out there newly taksed with moving a site to full on HTTPS. I tried to share as much detail as possible without getting bogged down too much in the technical details. If you have any questions about this or run into other issues while making the move to HTTPS that you think we could address here, let us know in the comments.

If you need help transitioning to HTTPS, we will help our PMPro customers as much as possible in our member forums. Note that sometimes your host and/or SSL provider will need to be involved, so be ready for that. At the very least, we will need to get access information from you and find the time to carefully access your site to debug and fix anything we can.

Debug IPN and Webhook Activity for Integrated Gateways

This post shows you how to enable debugging for when your PMPro-powered site communicates with the payment gateway (via webhook, IPN, or silent post).

This is helpful not only when you are experiencing issues, but if you want to have a more detailed view of all the information your gateway transmits about orders and subscriptions.

Choose the Appropriate Debug Statement for your Gateway

The debug lines are listed below for each gateway we integrate with. To enable, just add the appropriate lines to your site’s wp-config.php file. An email will be sent to the site’s admin email as set under Settings > General.

If you have a lot of activity on your membership site, it may be smart to set up a rule in your email account to automatically archive or move these emails to a separate folder.

For PayPal [more info]

define('PMPRO_IPN_DEBUG', true);

For Stripe




For Braintree


For 2Checkout

define('PMPRO_INS_DEBUG', true);

If you are using our Add PayPal Express Add On, you can define both the onsite gateway debug as well as the PayPal debug.

Sending Debug Information to Other Emails

You can set specific email addresses to receive the debug information by changing the lines above as follows:

define('PMPRO_IPN_DEBUG', ',');

Logging Debug Information (instead of emailing)

You can also set the debug to save to a log file if you’d prefer NOT to receive an email for each piece of activity on your IPN/webhook/silent post URL. Change the line for your gateway as follows:

define('PMPRO_IPN_DEBUG', 'log');

Update on TLS 1.2 Requirements for Gateways

Earlier this year, we shared information on upcoming requirements for using PayPal APIs.

In this post, I’ll update the status of those changes for PayPal and for other gateways and introduce a plugin we’ve developed to help site owners navigate through the required changes.

What’s happening?

All payment gateways, including PayPal, Stripe, Braintree, and (and really any service that uses an API) are updating their API servers to only accept requests made using the new TLS 1.2 protocol for encryption.

What do I need to do?

Ask your web host or server admin to make sure your server supports TLS 1.2. Specifically your web server should:

  • Run OpenSSL 1.0.1 or higher, or another cryptographic library that supports TLS 1.2
  • Run PHP version 5.5.19 or higher.
  • Run cURL version 7.34.0 or higher.

What if I can’t upgrade my server?

The optimal fix for this issue is to upgrade your server software, and you must be running OpenSSL 1.0.1+ or the latest version of an alternative cryptographic library. The TLS 1.2 protocol is defined within the cryptographic library.

There are other reasons to upgrade PHP and cURL, including security reasons, but with respect to TLS 1.2, the versions recommended above mostly just tell the software to use the TLS 1.2 protocol. You may be able to get a lower version of PHP and cURL to use TLS 1.2 by adding the following code to your active theme’s functions.php or a custom plugin. Note that if the TLS 1.2 protocol becomes compromised in the future, you’ll need to adjust this code to force whatever new protocol takes its place.

That’s pretty complicated?

I’m trying to write this all out as clear as possible, but it is confusing. To help with things we’ve developed a plugin to help diagnose if TLS 1.2 is enabled on your site and what steps to take, including an option to force TLS 1.2 in cURL similar to the code gist above.

Get the TLS 1.2 Compatibility Test Plugin from the


When do I need to make these changes?

Ideally, you should make these changes as soon as possible to make sure your site is as secure as possible. Other than that, the main driver behind this change is the PCI Security Standards Council and they have set a deadline of June 30th, 2018, after which time you would risk losing PCI Compatibility status. This is an extension of the previous deadline of June 30th, 2016.

Your payment gateway will likely require the change sooner. PayPal was going to force TLS 1.2 today (June 17th, 2016), but has since extended their own deadline to June 30th 2017.

Other gateways were set to start requiring TLS 1.2 after June 30th, 2016 and may or may have extended that deadline because of the PCI SSC extension. You should check with your gateway to get the exact date… or just upgrade ASAP.

What might go wrong?

Whenever you upgrade your server, especially PHP, things might break. So it’s important to do these updates under the guidance of a trained sysop or with your host. Make any and all backups you can of your server, your files, and your database before starting the upgrade.

WordPress and most popular plugins, like Paid Memberships Pro, will work with newer versions of PHP. However some custom code of yours might rely on earlier PHP versions. I’m hesitant to say this, but generally you can upgrade PHP, then test things to see if anything broke, and then fix any code that is no longer working properly. Or you can consult with the developer who built the custom code and ask them if they expect any problems running the code under the newer version of PHP.

When upgrading PHP, you may also need to upgrade or reinstall some “PHP modules” that are used by your site. These might include the cURL library itself, the Multibyte String library, or others.

Some third party APIs outside the major gateways and name brand web companies may not have updates the web servers their APIs are running on to support TLS 1.2. If you upgrade your server to use TLS 1.2 and specifically if you use the gist above or our compatibility plugin to force TLS 1.2, API requests to these servers may fail. In these cases, you really should ask the entity managing the API to upgrade their servers to support the latest security protocols.

Why are these changes necessary?

When computers talk with each other and they want to keep the communication secret, encryption is used. In practice this means that visitors to the HTTPS version of your site use encryption so information like credit card numbers and billing addresses are kept secret when being entered into a form.

To make all of this work, standard “encryption protocols” are used so web browsers and web servers can communicate in a secure way. Previously, the SSL protocol was the standard, which is why you likely purchased something called an “SSL certificate” for your site. Third party SSL certificates authenticate that you are the true owner of your domain so browsers can confidently engage in SSL encrypted communication with the web server.

Encryption is also used when software like Paid Memberships Pro communicates with payment gateways like PayPal through its APIs. The same encryption protocols used when you visit a website in your browser are used when your web server makes a request to an API. Again, the SSL protocol was most popular for this.

However, several vulnerabilities have been found with SSL (most notably the Heartbleed and POODLE attacks) and a new protocol has been adopted called TLS (Transport Layer Security). This requires a number of updates to both browsers and web servers.

  • Upgrades to servers to use TLS 1.2 when connecting to outside APIs (the topic of this post)
  • Upgrades to API servers to use TLS 1.2 (what the gateways are doing)
  • Upgrades to web browsers to use TLS 1.2 when connecting over HTTPS
  • Upgrades to SSL/TLS certificates and web servers to use TLS 1.2 to serve sites over HTTPS

In Summary

Use the TLS 1.2 Compatibility Test plugin to diagnose if your site is already using TLS 1.2 and to get recommendations for how to upgrade your server to enable TLS 1.2.

While the PCI SSC and gateways have decided to extend the deadline for migrating to exclusive TLS 1.2 usage, you really should make this change as soon as possible to make sure your site is secure.

I’ve tried my best to make this post as clear as possible, but this is a technical issue. Let me know if there is something we can do to be more clear or helpful. If in doubt, forward this post to your host or web master to work through on your site.

Avoiding Undefined Function Errors In Hooks, Filters, Actions, and Custom Code

The dreaded “undefined function” error is a common PHP error that comes up when developing in PHP. We see it specifically come up when using custom code gists from this site.

This post will describe why this error comes up, how to debug it, and how to avoid this error when writing code of your own. You’ll learn how to test if a certain function or plugin is active before using that function or a feature of that plugin.

The error I’m talking about looks something like this:

Fatal error: Call to undefined function somefunctionname() in /var/www/vhosts/ on line 163

On live sites, errors like this might be hidden and/or logged to a file on the server, and so you will only see a blank “whitescreen of death”.

Why this error happens.

Put simply, PHP will throw this fatal error if you attempt to use a function that hasn’t been defined yet.

As an example, here is some PHP code that will cause an error like this if the PMPro Register Helper plugin is deactivated since the function pmprorh_add_registration_field() is defined by that plugin.

function my_pmprorh_init()
    $field = new PMProRH_Field(
        "company",              // input name, will also be used as meta key
        "text",                 // type of field
            "size"=>40,         // input size
            "class"=>"company", // custom class
            "profile"=>true,    // show in user profile
            "required"=>true    // make this field required
        "checkout_boxes", // location on checkout page
        $field            // PMProRH_Field object
add_action("init", "my_pmprorh_init");

Even if you have the Register Helper Add On activated, it will be temporarily deactivated during updates. The customization plugin above runs the pmpro_add_registration_field() function during init, and so your site will crash with a fatal error:undefined function when the Register Helper Add On gets deactivated during update.

How to fix or avoid undefined function errors.

The way to avoid undefined function errors is to make sure the function is defined before it gets used. The best way to do this is with the function_exists() PHP function.

Using function_exists()

At the very top of your function, add some code like this:

//rest of your function code

These two lines will stop the function from executing any code below if the pmprorh_add_registration_field is not available, and this is exactly what we do in our register helper example code.

If your function expects a return parameter, you’ll have to return the value expected

Some functions (e.g. callback methods for WP filters) expect a certain return value. Here is how you would do that if you were filtering on the the_content hook:

function my_the_content_filter($content) {
    //bail if PMPRo is not active
        return $content;  //return the original content
    //... the rest of your code to filter the_content ...
    return $content;

When using plugin functions in a theme file or template, use function_exists() right before the call

In the example above, we used the function_exists() call at the top of a function as a test to see if a plugin is activated before executing the rest of the function. Similarly, if you are using a plugin’s function in your theme’s files or templates, you should use a function_exists() test right before the call just in case that plugin is not activated.

For example, here is how we recommend using the pmpro_hasMembershipLevel() function in your theme code:

if(function_exists('pmpro_hasMembershipLevel') && pmpro_hasMembershipLevel()) {
    //this is a member, do something cool

Other ways to check if a plugin is loaded

Besides checking if a functions exists, you can also check if a class exists, a method exists for a certain class, or a constant is defined. Here are a couple other ways to test if PMPro is activated.


if(class_exists('MemberOrder')) {
    //do something with the MemberOrder class, e.g. $order = new MemberOrder();


if(method_exists('MemberOrder', 'getEmptyMemberOrder')) {
    //getEmptyMemberOrder method added in v1.8.6.8 is available


if(defined('PMPRO_VERSION')) {
    //PMPro has been loaded

We avoid using the TGM Plugin Activation library

There is a nifty library you can use to make plugins require other plugins called TGM Plugin Activation. We’ve used this in the past, but have removed it from some addons and avoid using it now because we found including the library caused more issues that it solved. If another plugin was using an older version of the TGM library, then there could be conflicts. If we simply test for a plugin by looking for a class, function, or constant definition, then there is no chance for a conflict there.

Make sure your check is always at the top of the function

When editing our gists or other code on this site, make sure that your edits go below any function/plugin tests. So…

function my_function() {
    //don't put any code up here
    //test for PMPro
    //put your edits below here

If you are writing a callback for a hook added by a certain plugin, you don’t have to test if that plugin is active

When you define a callback function via add_action() or add_filter() for a hook or filter added by a specific plugin, you don’t have to check that that plugin is active. The fact that the hook fires at all is proof that the plugin is active. So for instance, the PMPRO_VERSION check at the top of this callback is redundant and not needed.

function my_pmpmro_checkout_level($level) {
    //this check if redundant because the pmpro_checkout_level is only used by PMPro
        return $level;
    //... filters here ...
    return $level;
add_filter('pmpro_checkout_level', 'my_pmpro_checkout_level');

Let us know if you found this useful or if you have other questions around this or similar errors.

PayPal’s TLS 1.2 and HTTP/1.1 Upgrade and How it Could Impact Your Membership Site

PayPal has announced several security updates set to roll out in 2016 which will impact sites using PayPal gateways. This post covers the TLS 1.2 and HTTP/1.1 upgrade scheduled for June 17, 2016. If all actors involved (your host, WordPress, Paid Memberships Pro, and PayPal) update before June (we plan to), you should experience no disruption in your service. However, if you are using the PayPal sandbox environment now or otherwise want to make sure your host and website are ready, please review the content below.

We’ve outlined the steps to take now to ensure compatibility and avoid a disruption of service.

Note: The contents of this post are highly technical and should be reviewed by your web hosting company and an experienced web developer.

About the TLS 1.2 and HTTP/1.1 Upgrade

PayPal is upgrading the protocols used to secure all external connections made to their system. This includes every connection your site makes with PayPal (onsite or offsite Membership Checkout and via IPN). TLS 1.2 and HTTP/1.1 will become mandatory for communication with PayPal on June 17, 2016.

The latest versions of Paid Memberships Pro have already been updated to use HTTP 1.1 in its API calls to PayPal. However, your server still needs to be updated to use TLS 1.2 for SSL communication.

If your server does not support TLS 1.2 and HTTP/1.1, payments processed via PayPal gateways (PayPal Express, PayPal Standard, and PayPal Website Payments Pro) will fail. You may notice the following error message after clicking to checkout at PayPal:

methodName_ failed: SSL connect error

In addition to this PayPal security update, WordPress also needs to be updated to specify the SSLVERSION for cURL to support PayPal Express moving to TLS 1.2.

Verify Support for TLS 1.2 and HTTP/1.1 With Your Webhost

To avoid disruption in service, you must first verify if your web server supports these security protocols. Contact your web host and find out if your server supports TLS 1.2 and HTTP/1.1. If the answer is no, you will need to work with your web host to enable support. In general, the host only needs to “upgrade OpenSSL to the latest stable version”.

Specify the SSLVERSION for cURL in your WordPress Site

After verifying that your server supports TLS 1.2 and HTTP/1.1, you will also need to make an update to your WordPress site to set an SSLVERSION for cURL (a tool on your server that transfers data from or to a server, using one of the supported protocols). For your site to continue to be able to communicate with PayPal, you need to set your version of cURL to explicitly use the TLS 1.2 protocol. Setting this version prior to PayPal’s TLS 1.2 rollout should not impact current communications with PayPal.

Here’s a code gist for setting the SSLVERSION for cURL that we will continue to develop and improve over time. Copy this code into your active theme’s functions.php file or a custom plugin.

Note: This or some version of this code will be moved in Paid Memberships Pro core or WordPress core prior to the security update in June. The above code gist is only needed if you need to use PMPro with PayPal in sandbox mode in the meantime or if you want to be sure your site will be ready before the updates roll out in the coming months.

Test Checkout via the PayPal Sandbox

The PayPal Sandbox endpoints have already been configured with the latest security standards to which the Production endpoints will be moving.

You can set your Payment Gateway in Paid Memberships Pro to the PayPal Testing/Sandbox Mode to verify support prior to the security release on July 17. See this post on PayPal Sandbox with Paid Memberships Pro »

Important: How to Delete Redundant Cron Jobs

WordPress and Paid Memberships Pro use a system called WP Cron to schedule events like the scripts that PMPro uses to manage membership expirations and queue up “expiring soon” emails.

PMPro v1.8.7 introduced a bug that was scheduling extra cron events… actually 3 extra events with every page load. On active sites (like our own site here), this quickly led to thousands of cron jobs being added, which would fill up the database and slow the site down to the point of failure.

It’s an incredibly nasty bug, and we’re very sorry to have introduced it.

Below is more information on who the bug affects and a few ways to clean it up. If you feel that the bug is affecting your site, and would like further help fixing this, please reach out in our member forums (fastest reply) or our contact form and we’ll resolve this for your site.

Who is this bug affecting?

  • Sites that ran PMPro v1.8.7 or for any length of time.
  • Sites that are completely crashing.
  • Sites running significantly slower than expected even after updating to PMPro v1.8.7.2.

PMPro Contains a Cleanup Script

If your site is running and you are able to access the WordPress dashboard, upgrading to PMPro will run a script to clean up the redundant cron jobs. In our tests, this script always cleaned up the extra crons without halting as long as WordPress was loading in the first place. But please let us know if you experience any issues after upgrading to

You Can Also Run a Separate Cleanup Plugin

If you have access to your WordPress dashboard, but you’d rather not upgrade PMPro (although we think you should), you can run the plugin created by Thomas Sjolshagen specifically to clean up the extra PMPro Crons. Download the zip file here and then upload and activate the plugin. (Some people have reported that they have to activate the plugin twice.)


Fixing Via MySQL if You Cannot Access the WordPress Dashboard

If you cannot access your WordPress dashboard to upgrade PMPro or use the cleanup plugin, follow the instructions below to clean your cron jobs up. This is an advanced technique and should be done with care. If you use plugins that make large use of the WP Cron system (e.g. WooCommerce Subscriptions), you will definitely want to back up the database first or at least the “cron” row in the wp_options table. And you will want to take extra care before running the steps below.

  1. Back up your database and files through your host or a backup plugin [more info].
  2. Run the following SQL command to delete all scheduled cron jobs.
    DELETE FROM wp_options WHERE option_name = 'cron';

    Note that your DB prefix may be something other than wp_ so update the command with your proper options table name

  3. Alternatively, on one system we were fixing this on the DELETE command above didn’t work. The following update command did:
    UPDATE wp_options SET option_value = '' WHERE option_name = '';
  4. If your website is still slow or not loading at this point, you should restart the Apache/HTTPD/NGINX/etc and MySQL/MySQLD services through your control panel or SSH.
  5. Deactivate and reactivate Paid Memberships Pro and any other plugin that you might need to have crons rescheduled for.
  6. Install the WP Crontrol plugin and go to Tools -> Scheduled Events to see what crons are scheduled. If you see a ton of redundant events with the same name/hook, then you might need to adjust and/or the SQL query above.

Other Notes

If your site is running fine, you can try to view the crons using a plugin like WP Crontrol to see if you really have an issue. And you can try to deactivate and reactivate Paid Memberships Pro, which will try to clear out the PMPro-specific crons. However, if there are a very large number of these, the deactivation may take your site off line. At which point, you should follow the steps above to fix the issue.

We’re committed to helping people fix things as quickly and painlessly as possible. If you need further help, please reach out in our member forums (fastest reply) or our contact form and we’ll resolve this for your site.


Methods to Bulk Email Members by Membership Level

This post covers a few options to send email to your members list. There are many options for communicating with members via email. Your selection from the options below depends on the list size, email tracking needs and your preferences for automation vs. customization.

Topics Covered Include:

Email Users Plugin with PMPro Integration

This plugin makes it easy to kick off an email to your WordPress site users directly in the WordPress admin. You can segment users by a few criteria, including their “Membership Level”.

The plugin’s settings page (Settings > Email Users) allows you to configure some email defaults, design a “new post” notification email, as well as set up a custom email footer message.

To email a specific membership level or group of membership levels, navigate to Email Users > Send to Group(s). From here, you can set up your direct email and multi-select the membership levels you want to distribute the message to.


Members can manage their email preferences from the “Edit Profile” page. Options include subscribe/unsubscribe from direct messages, new page/post notifications and bulk/group messages. If you do not want your members to be able to mange these preferences or you want to update the default settings for a new member, navigate to Settings > Email Users > Default User Settings.

Download Email Users

MailPoet with Paid Memberships Pro Add On

MailPoet (formerly Wysija Newsletters) is a WordPress plugin that allows you to send newsletters, post notifications or autoresponders directly from your site’s WordPress admin. Read more about the add on here.

Members must “opt in” to a distribution list at signup. There is no option to send to a new segment based on “Membership Level” as this time.

MailPoet Paid Memberships Pro Add On

Download MailPoet Download the MailPoet PMPro Add On

The Pitfalls of Distributing Bulk Email from Your Web Server

There are a few limitations of sending bulk email directly from your WordPress site. First, the two options above have no built in “throttling” of email distribution. This means that your mail distribution can “time out” or “crash”, leaving you with no way of knowing who received the email, and who didn’t.

The second obvious pitfall is that mail sent directly by your WordPress site may be marked as “spam”, or even worse, totally rejected. InMotion hosting has a good article on email delivery with some steps you can take to help improve the delivery rates of your server-generated email.

The main approaches to improve server-generated mail delivery rates include:

If you run into trouble distributing bulk email to a large members list via your WordPress site, explore a transactional email service like wpMandrill. This will not only provide you with the ability to distribute to large lists, but also provides stats about your wp_mail (delivered, bounced, rejected, opened, clicked, country and more).

Using a Third Party Email Marketing Service

Paid Memberships Pro has integration for some of the top email marketing services, including MailChimp, Constant Contact, AWeber and more. Browse available integrations on the Free Add Ons page.

With each integration offered, you have the ability to associate “lists” with “membership levels”. This means that your email marketing program can maintain a unique subscriber list for each of your membership levels.

We use MailChimp for email marketing, and we’ve configured it so that new posts in the “newsletter” category are automatically distributed every Tuesday and Thursday at 1pm ET. This is set up using MailChimp’s RSS-to-Email feature. PMPro Plus members can watch our MailChimp webinar for instructions on how to set up an RSS-driven campaign.

Each email marketing program we integrate with has the ability to bulk email an individual campaign to one or more of your member lists. This method offers the full tracking options provided by your email marketing service, as well as the higher delivery rates of the bulk sender.

Explore Our Email Marketing Add Ons