Import users from a CSV file into WordPress
|Author:||Thomas Sjolshagen (profile at wordpress.org)|
|WordPress version required:||4.4|
|WordPress version tested:||4.9.8|
|Added to WordPress repository:||03-01-2018|
|Total downloads:||1 415|
Click to start download
For an automatic installation through WordPress:
- Go to the ‘Add New’ plugins screen in your WordPress admin area
- Search for ‘Import Users from CSV’
- Click ‘Install Now’ and activate the plugin
- Upload your CSV file in the ‘Users’ menu, under ‘Import From CSV’
Or use a nifty tool by WordPress lead developer Mark Jaquith:
- Visit this link and follow the instructions.
For a manual installation via FTP:
- Upload the
pmpro-import-members-from-csvdirectory to the
- Activate the plugin through the ‘Plugins’ screen in your WordPress admin area
- Upload your CSV file in the ‘Members’ menu, under ‘Import Members’
To upload the plugin through WordPress, instead of FTP:
- Search for the plugin (“Paid Memberships Pro Import Members from CSV” on the ‘Add New’ plugins screen in your WordPress admin area and activate.
- Upload your CSV file in the ‘Memberships’ menu, under ‘Import Members’
How to use?
Click on the ‘Import Members’ link in the ‘Membership’ menu, then select your CSV file.
Next you have to decide whether you:
- want to deactivate previously existing member record(s) for the user – The CSV record has to specify the same membership as the user previously had so this is most useful when having to reimport/update data (default: enabled and recommended),
- update the existing user/member’s information (default: enabled and recommended)
- send a notification email to new users (default: disabled),
- want the password nag to be displayed when the user logs in (default: disabled),
- have included a hashed (encoded) password specified in the import file and (default: disabled)
- want to use the background import option (default: enabled and recommended)
- create a PMPro order record based on supplied payment info in the .csv file (default: disabled)
Then click the ‘Import’ button.
Each row in your CSV file should represent a user; each column identifies user data, user meta data or user membership data
If a column name matches a field in the user table, data from this column is imported in that field; if not, data is imported in a user meta field with the name of the column or into the PMPro custom membership tables.
Look at the examples/import.csv file in the plugin directory (also linked on the “Import Members” page) to have a better understanding of how the your CSV file should be organized and what the data fields need to contain as far as formatting/values go.
You can always try importing the examples/import.csv file and look at the result, assuming the values specified for the membership_id in the example file match your membership level configuration.
The .CSV file from the “Export to CSV” button on the “Members List” page won’t import?
The purpose of the resulting .CSV file from the “Export to CSV” is to generate reports that are meaningful to a human, not a file that can be imported easily. This is true for any of the available Import from .CSV plugins/add-ons for Paid Memberships Pro.
Basically there are a few key differences between the file resulting from the Export function and the file contents needed to import the same member.
As of version 2.5, this plugin includes data checks for some of the more common mistakes I’ve seen in the .CSV file(s).
You should also check out the import example file that is linked on the “Import Members” page (under the “Choose File” button).
My import fails, what is wrong?
This is almost always related to the data in the file being imported. As a result, I’ve added some data tests for some of the typical mistakes I’ve seen in the .CSV file(s) being imported. There is also a link to an example file on the “Import Members” page (under the “Choose File” button) that illustrates a functional import file. Things lik what the field names are and the format you’ll most likely need to use for the data in that column.
Check the wp-content/uploads/pmp_im_errors.log log file for details on the import operations (link should also be included in a wp-admin dashboard notice if there are errors/warnings). The log should contain suggestions on some of the more common mistakes in the data being imported.
Do I need to include all the columns from the sample file?
No. Only include the columns where you have data to import. I.e, if none of your members need to have their membership end date defined (i.e the membership you’re importing doesn’t have an expiration or it’s a recurring membership with a linked Payment Gateway subscription plan), just remove the column(s) you don’t need. That way, the plugin doesn’t try to import data that isn’t there.
If a column has no data, you should remove the column and it’s column header from the import file!
The plugin didn’t import any membership data!?!
This is a pretty common question and the reason is almost always because there is something unexpected in the
membership_ portion of the row being imported.
Most often it’s the date/time format for the membership_startdate and membership_enddate columns.
If you use MS Excel(tm) to prepare your .CSV file, you’re in for a treat…
In my experience, MS Excel(tm) is really good at changing the date format in a spreadsheet column to whatever it thinks works best (i.e. human readable).
However, human readable is often problematic for CSV imports, so you have to ensure the format follows the YYYY-MM-DD HH:ii:ss (where ii = 2 digit minute value). For startdate I’d recommend using
00:00:00 and for the enddate I’d suggest using
Just to be clear: The only date format for the membership_startdate, membership_enddate and the user_registered columns that this plugin will accept is the MySQL datetime format: YYYY-MM-DD HH:ii:ss.
Use anything else and your membership data will not be imported!
You can change the way Microsoft Excel(tm) handles date and time data in the Regional settings, but I’ve yet to figure out what the ideal settings are here. Truth be told, I’m using Apple Numbers and others have had great success using Google Sheets to process and export their .CSV files. Because there are alternatives to Microsoft Excel(tm) and they seem to work a lot better for this specific task, I’m not at all inclined to spend more time on fixing something that I view to be a rather significant “bug” in Excel(tm).
 = Being that it’s an intentional usability feature, I realize Microsoft is unlikely to be all that interested in fixing this “as designed” capability they’ve implemented.
Can this plugin be used to import order data for Paid Memberships Pro?
As of version 2.20, we have an option to create member orders along with the member record. That means you can now specify some of the order table fields to import custom values as needed for each user/member along with updating/adding their membership level information.
The supported order record columns are:
- billing_street (*)
- billing_city (*)
- billing_state (*)
- billing_zip (*)
- billing_country (*)
- billing_phone (*)
All of these columns/fields should be prefixed with ‘membership_’. I.e. ‘membership_paypal_token’ or ‘membership_tax’, etc. The exceptions are the ‘user_id’ and ‘membership_id’ columns/fields which should be left as ‘user_id’ and ‘membership_id’ respectively if you want to include them in the import operation(s).
The ‘status’ column has a limited number of valid values. By default, we recommend using either ‘success’ or ‘cancelled’
All timestamp values (‘timestamp’) must use the same format as the one used by the MySQL database’s ‘DATETIME’ format: YYYY-MM-DD HH:MM:SS
Although you can specify an account number (accountnumber) in the import file, doing that will not result in an ability to import and activate credit cards as part of the import operations.
You CANNOT use this tool to import and recreate subscription plans or transactions on the payment gateway for your Paid Memberships Pro users.
Including anything other than a masked Credit Card number for the “membership_accountnumber” column – Masked = Only the last 4 digits are real and the rest are repetitions of the ‘X’ character – would be a really bad idea!
Supported membership_gateway options
The Import Members from CSV plugin supports specifying different payment gateways for the user record(s) when importing order data (i.e. the “Attempt to create PMPro Order record” option has been selected). At present, the payment gateways that can be specified in the
membership_gateway column are:
During the import operation, the plugin will verify that the specified payment gateway integration is one of the supported payment gateway integrations for Paid Memberships Pro.
Specifying a Payment Gateway Integration that has not been configured for use during the PMPro checkout process would render the order record invalid.
NOTE: The limitations to how Paid Memberships Pro supports/handles multiple payment gateway integrations at the same time still apply.
Adding billing address information to the PMPro Order import
The normal way to import billing address data to the database for a member/user is to use the
pmpro_b[*] fields (pmpro_bfirstname, pmpro_blastname, pmpro_baddress1, pmpro_baddress2, pmpro_bcity, pmpro_bstate, pmpro_bzipcode, pmpro_bcountry and pmpro_bphone).
If the pmpro_b* field data is present in the row and the ‘Add order’ option is selected for the import file, the import will attempt to populate the order billing information using the pmpro_b* data.
How should the .csv file be defined?
This plugin assumes that the .csv file;
- Uses a comma (,) character to denote a new column in a row
- Uses a double-quote (“) character to wrap the contents of each of the columns
- Uses a backslash () character as the escape character
To have a 2 column .csv file, each row after the header row, the row should look something like this:
"my first column data","my second \"escaped\" column data".
The application you use to edit and export your .CSV file will need to be configured appropriately before you export the .csv file.
Why am I or my users not receiving New user notifications
There are a couple of possible reasons, as far as I can tell. The functionality in WordPress that generates the “new user notification” message is what they call “pluggable”. That means that it’s possible for a plugin (any plugin!) to override the behavior of the functionality. So the first thing I’d suggest investigating is whether you have a pluing active that intentionally changes/modifies/updates how the
wp_new_user_notification() function works/behaves.
Next, it’s (very) possible that your hosting environment doesn’t want you to be sending out a lot of email messages from their servers. As a result, the import operation could potentially trip their anti-spam measures and blocking you from sending any messages.
Third, the recipient email server may be using a SBL (Spam Black List) and have your web server IP listed as a typical source of Spam messages (it happens, a lot).
I’ve set the ‘membership_status’ column to ‘inactive’, but the user’s imported membership level is currently ‘active’?
This is due to what I’d term a bug in Paid Memberships Pro. This issue doesn’t currently have a fix.
Basically, the ‘inactive’ status will only apply to the order record (if it’s created, see above) and not to the user’s membership status.
NOTE: Assigning a membership level for a user will cause them to be given an active membership on the site when the import operation is complete, regardless of the value supplied for the ‘membership_status’ column.
How do I import an existing payment plan (recurring billing plan) for a user?
This only works if the plan already exists on the payment gateway itself.
There is no way to use this plugin to import a new member/user and have the system create a recurring billing plan for them.
Can I use this plugin to create new billing plans or trigger charges on the payment gateway for an imported user?
What are the constraints for WordPress Multisite import operations?
As documented by Paid Memberships Pro, the PMPro plugin cannot be Network Activated.
This import plugin will work from the site(s) where PMPro is active and have the same membership level IDs identified as are listed in the
membership_id column of the import file you’re using.
If your primary site has a configured and active Paid Memberships Pro installation, you could theoretically start the plugin from the Network Admin dashboard (which will send you to the primary site anyway).
The users being imported will only be linked to the site you import them to. Their membership data will only be visible on the PMPro site(s) that have the membership level ID(s) configured that match those in the import file.
What GDPR impacted data is stored by this plugin?
Obviously, there’s the user data that this plugin is designed to import. This plugin does not track, report, or allow download/deletion of any data it imports. There are (now or soon) other plugin options to handle those requirements from the GDPR legislation.
In an attempt to make the “Donation” button less intrusive, we attempt to track the computer (IP) address when somebody clicks the button. This plugin does not link the IP address to a user account, so it should be a little more challenging to identify the person who clicked the “Donate” button for any 3rd party who gets access to your database than simply looking at the options saved by this plugin.
The IP tracking information (the IP address) is stored in the WordPress options table (
wp_options) using the
e20r_import_has_donated option name. That option can safely be deleted in the database if you do not wish to have IPs tracked. Deleting the option from the database will obviously re-enable the Donation nag.
As long as this plugin remains installed and active on the server, the tracked IP address will automatically be removed from the option 2 months after the admin clicked the Donation button.
The option is removed when the plugin is deactivated in the “Plugins” admin panel.
Nag tracking can be disabled altogether with the
add_filter( 'e20r_import_donation_tracking_disabled', '__return_true' );'
- BUG FIX: Import data would be cleared if the “Import Users from CSV Integraion” add-on is installed and active.
- ENHANCEMENT: Add more tests & info about incorrect user_registered, membership_startdate and membership_enddate date formats
- ENHANCEMENT: Display a WordPress notice (error) message if a bad/incorrect date format is used in the import file
- ENHANCEMENT: Display proposed solution for date format issues
- ENHANCEMENT: Added check for valid – pre-defined – membership ID for the user/row
- ENHANCEMENT: When “Add order” is selected and there are
pmpro_bprefixed columns with data in the row, use it to try and populate the MemberOrder billing info (in the order record)
- ENHANCEMENT: New and updated Frequently Asked Questions (FAQs)
- ENHANCEMENT: Slightly less stringent behavior if the subscription_transaction_id and/or the payment_transaction_id data is missing
- ENHANCEMENT: Verify that the current line/column count matches the # of header columns
- BUG FIX: Invalid import.csv example file
- BUG FIX: Didn’t always track error status
- BUG FIX: Didn’t handle membership ID values of 0 properly
- BUG FIX: Didn’t set the payment gateway for an order when different from the default was specified
- BUG FIX: Occasional “Fatal Error” during import operation
- ENHANCEMENT: Dedicated data check method with filterable result (allow 3rd party data checks w/returned result: ‘pmpro_import_members_from_csv_data_check_status’ ). Triggered for each record/row being imported.
- ENHANCEMENT: Disallow problematic file names when selecting import .csv file (files that will be modified during data sanitation on transfer)
- ENHANCEMENT: Various additional tests of data and corresponding error messages when attempting to import order data
- ENHANCEMENT: Can add a PMPro Order record for the imported user, even without a linked payment gateway record. This assumes that either the membership_initial_payment or membership_billing_amount column is present in the import (.CSV) file. The add order operation can also use the default Membership level definition pricing if neither are present in import file).
- ENHANCEMENT: Support most of the table fields for the pmpro_membership_orders and pmpro_memberships_users table with a ‘membership_’ prefix as importable data (pmpro_membership_orders data expects the ‘Add order’ option to be enabled/checked).
- ENHANCEMENT: Extract column names dynamically from PMPro’s custom membership users/orders tables
- ENHANCEMENT: Updated screenshot(s)
- ENHANCEMENT: Updated and added to FAQ section
- BUG FIX: Not loading/updating record if user exists and the only user identifiable data is the email address
- BUG FIX: Consistent use of quote characters in .js file
- BUG FIX: Incorrect ID(s) for NONCE(s)
- BUG FIX: Hardened the error/warning message logger
- BUG FIX: Plugin links were missing
- BUG FIX: Missing semi-colon terminations in some instances
- ENHANCEMENT: Added Donation button (with logic to not always display it) and request for reviews (with .css file)
- ENHANCEMENT: Clicking the Donation button will attempt to dismiss the donation nag for 2 months by trying to track the user’s client IP address (can be error prone in certain environments).
- ENHANCEMENT: Remove nag tracking when plugin is being deactivated
- ENHANCEMENT: Add styling for Import Members from a CSV file page
- ENHANCEMENT: More info when we think the import file isn’t found/located
- ENHANCEMENT: Open the example import file in its own browser window/tab
- ENHANCEMENT: Add user_login check (validity/duplication)
- ENHANCEMENT: Optionally suppress the “Your password was changed” and “Your email address was changed” message to member when updating their record
- ENHANCEMENT: Remove import file & options when user clicks “Finish” for the import
- ENHANCEMENT: Faster turnaround when triggering background loading
- ENHANCEMENT: Updated .pot file
- BUG FIX: Didn’t skip user_login based search if user found by email address
- BUG FIX: Would look up user by username before using the (more likely to be unique) email address
- BUG FIX: Would attempt to update a user record when we shouldn’t
- BUG FIX: Didn’t list all tracked/saved errors when import fails
- ENHANCEMENT: Clear output buffer before sending AJAX response
- ENHANCEMENT/FIX: Limiting max # of records per import iteration to <= 60
- ENHANCEMENT: More descriptive language for some error messages
- ENHANCEMENT: More checks during Import page load if on WPMU site(s)
- ENHANCEMENT: Split out different membership ID related error messages
- BUG FIX: Didn’t handle ‘inactive’ status when no membership_enddate is supplied
- BUG FIX: Didn’t always generate a log entry for certain errors/issues
- ENHANCEMENT: Warn if user has an invalid (non-existing) membership ID
- ENHANCEMENT: Warn if the user has an enddate in the future but have had their membership_status set to ‘inactive’
- ENHANCEMENT: Use ‘admin_cancelled’ as new status for preexisting user_id/membership_id records where status is ‘active’
- ENHANCEMENT: Various updates to the FAQ section.
- ENHANCEMENT/FIX: Better warning messages & handling of WP Multisite configurations
- BUG FIX: Only set status if explicitly asked to
- BUG FIX: Incorrect handling of UTF BOM characters led to missing 1st column header
- BUG FIX: Didn’t return new member record to update status for in all cases
- BUG FIX: Didn’t set the supplied membership_status value correctly in all cases
- BUG FIX: Didn’t set format for DB record update
- BUG FIX: Didn’t send imported_member.html message (when activated) to imported member
BUG FIX: Didn’t send the email template based welcome message
BUG FIX: Typo in warning/error messages
BUG FIX: A little too silent when the imported file is mis-configured
BUG FIX: MS Excel causing trouble w/first column import values (Improved UTF BOM handling)
BUG FIX: validate_date() method triggered PHP Notices in certain situations
BUG FIX: Improved checking of email field in import file
BUG FIX: Would sometimes trigger PHP Warning due to incorrectly loaded empty line of text
ENHANCEMENT: Strip the UTF BOM character if necessary from first/header line in import file
ENHANCEMENT: Clean up unneeded user metadata
ENHANCEMENT: Improved error logging/handling for typical import file errors
ENHANCEMENT: Send Welcome Email template when adding user to membership level (“Welcome imported user” email located in emails/ directory)
ENHANCEMENT: Add warning if unable to apply new membership level for user
ENHANCEMENT: Added method to load custom imported_member.html email template for Active Theme/Active Child Theme directory
ENHANCEMENT: Add settings for Sending WordPress new user/updated user message
ENHANCEMENT: Add setting for sending Custom Welcome Message for new/updated members (imported members)
ENHANCEMENT: Run cleanup of imported_ usermeta attributes after import is complete
- BUG FIX: Attempting to fix issue with the New User Notice not always being sent
- ENHANCEMENT: Select target recipients of “New User Notice” (User, Admin or both)
- BUG FIX: Didn’t include the transaction IDs, affiliate ID or gateway settings in the import
- BUG FIX: Typo in readme.txt
- ENHANCEMENT: Now calculating # of records to import in background based on PHP setting for max_execution_time
- ENHANCEMENT: Differentiate between warnings and errors. Errors should terminate execution. Warnings should be logged, but not end import.
- ENHANCEMENT: Added (‘Recommended’) for Import settings we recommend you use
- ENHANCEMENT: Improved error/warning reporting by using SplFileObject() to manage import file (indicates the line in the .csv file with a problem)
- ENHANCEMENT: Added error message when the ID, user_login and user_email columns are missing
- ENHANCEMENT: Added file indexed warning message if user_login has to be generated from the record email address (using front of ‘@’ as the login name)
- ENHANCEMENT: Added file indexed warning message when an email address is either missing or unrecognizable
- ENHANCEMENT: Include warning and error messages in Import status window (when applicable)
- ENHANCEMENT: Updated links to the WordPress.org repository for information and support for the plugin
- ENHANCEMENT: Linted and refactored the source files
- ENHANCEMENT: Expanded the FAQ section, fixed a few typos and updated the Change log in readme.txt
- BUG FIX: Better handling/reporting of unexpected values in the membership_status column, incorrect email formats, incorrect or missing membership_id value(s), improper date formats for the membership_startdate, membership_enddate and membership_timestamp columns and unexpected membership configurations (based on values supplied in the import file)
- BUG FIX: Displaying error/warning/info messages in wp-admin was a little flaky
- BUG FIX: Would allow duplication of error messages in wp-admin area
- ENHANCEMENT: Added error checking and messages to warn about the most common PMPro related errors in the .csv file being imported.
- ENHANCEMENT: Added function to test dates for compliance with MySQL requirements
- BUG FIX: Typo in add_action( ‘pmp_im_pre_user_import’ …) caused default pre-import action to not be triggered
- ENHANCEMENT/FIX: Updated action names: ‘pmp_im_post_member_import’, ‘pmp_im_pre_members_import’
- BUG FIX: PHP Warning
- BUG FIX: The resume URL didn’t work as expected
- BUG FIX: Didn’t set the blog ID when updating membership info
- BUG FIX: Didn’t cancel previous membership records for the imported user ID / membership ID combination when deactivate_old_memberships was set to true (checked)
- ENHANCEMENT: Renamed import page function (documentation related)
- ENHANCEMENT: Added link to error log (if applicable) to the admin notices
- ENHANCEMENT: Add support for WP Multi Site configurations (adding/updating users to the specified WPMU site)
- ENHANCEMENT: Better error handling/notifications
- BUG FIX: Didn’t preserve settings between loads of JS
- BUG FIX: Didn’t always load the correct settings for the JS based import
- BUG FIX: Include error info
- BUG FIX: Didn’t include all required settings in AJAX operation
- BUG FIX: Didn’t set and clear busy icon for import status text
- ENHANCEMENT/FIX: Use PMPro variable array to set record info for each user
- ENHANCEMENT/FIX: Renamed methods to better describe where they’re being used/what they’re used for
- ENHANCEMENT: Action handler when clicking the “Finished” button at end of import ( redirect to admin_url() )
- ENHANCEMENT: Add set_busy() and clear_busy() for feedback during import
- ENHANCEMENT: Add “Finished” button (display when import is complete)
- ENHANCEMENT: Reorder options (more logical, I think)
- ENHANCEMENT: Use AJAX import as default behavior
- ENHANCEMENT: Add “Import Members” to “Memberships” drop-down menu in /wp-admin/
- ENHANCEMENT: Improved prompts/info for options on import page
- ENHANCEMENT: Load plugin actions in plugins_loaded action
- ENHANCEMENT: Fixing PHPDoc for new functions/updated functions
- ENHANCEMENT: Variable name update
- ENHANCEMENT: Clean up insert method for hashed passwords
- ENHANCEMENT: Log error message if there’s a problem with a header field
- ENHANCEMENT: Adding screenshot images
- Fixed bug: Sanitizing request variables
- Fixed bug: Notification nag not getting configured correctly
- Fixed bug: New user notification not getting configured correctly
- Fixed bug: Didn’t always handle pause/resume (at all)
- Fixed bug: Didn’t stop/pause the import when user clicked the “pause” link
- Enhancement: Added
is_iu_import_records_per_scanfilter to let user set # of records to import per step when using JS import
- Enhancement: Refactored and added local scope for variables & functions
- Enhancement: Use JSON and status returns from server
- Enhancement: Use filter to set timeout for AJAX operation
- Enhancement: Use proper WP AJAX functionality for variables and statuses
- Enhancement: Clean up translations and grammar.
- Enhancement: Use printf()/sprintf() to improve formatting & translation
- Enhancement: Clean up REQUEST variable use
- Enhancement: Allow setting password nag for both new and updated accounts
- Enhancement: Use wp_send_json*() functions for AJAX actions
- Enhancement: Allow import of pre-hashed passwords for user records
- Enhancement: More reliable option based tracking of imports (not transients)
- Forked from the Import Users from CSV plugin and integrated the “PMPro Import Users From CSV Integration” add-on functionality
- Fixed bug with Notification Nag
- Fixed bug with user notification
- Fixed bugs with static/non-static function calls