This code solves your simple paid membership site needs.
If you are selling one-time content and hiding some of the site sections with user role check. This code is for you.
I wrote this code for my upcoming WordPress Development Course site and this code is enough for my case.
I could probably make this work with a subscription membership payment method too but maybe another time 🙂
Features;
- Adding Custom Role “student” to WordPress:
- Adding a Special User Roles Section for Products:
- Custom User Role for Each Product:
- Giving Roles to Buyers When They Purchase The Role with the Product:
- Updating Roles When Users Log In (just incase if the role not assigned in first place. maybe payment failed manual confirmation needed…etc):
- Every time a user logs into the website, it checks what products they have bought in the past. If they bought something tagged for a special role, like “student”, and they don’t already have that role, the code will auto-assign it.
/** * Function to add a new user role named "Student" */ function add_student_user_role() { // Add a new user role with the name 'Student' // The 'read' capability is a minimal capability that can be assigned add_role('student', 'student', array('read' => true)); } // Hook the function to WordPress 'init' add_action('init', 'add_student_user_role'); // Add the custom tab add_filter('woocommerce_product_data_tabs', 'add_user_role_custom_tab'); function add_user_role_custom_tab($tabs) { $tabs['user_role_tab'] = array( 'label' => __('User Role', 'woocommerce'), 'target' => 'user_role_options', 'class' => array('show_if_simple', 'show_if_variable'), ); return $tabs; } // Create the tab content add_action('woocommerce_product_data_panels', 'user_role_options_product_tab_content'); function user_role_options_product_tab_content() { global $post; ?><div id='user_role_options' class='panel woocommerce_options_panel'><?php ?><div class='options_group'><?php // Dropdown for user roles $roles = wp_roles()->get_names(); woocommerce_wp_select(array( 'id' => 'custom_user_role', 'label' => __('Select User Role', 'woocommerce'), 'options' => array('' => __('Select a role', 'woocommerce')) + $roles )); ?></div> </div><?php } // Save the custom field add_action('woocommerce_process_product_meta', 'save_user_role_option_fields'); function save_user_role_option_fields($post_id) { $custom_user_role = isset($_POST['custom_user_role']) ? $_POST['custom_user_role'] : ''; update_post_meta($post_id, 'custom_user_role', sanitize_text_field($custom_user_role)); } add_action('woocommerce_order_status_completed', 'assign_custom_user_role_on_purchase_optimized'); function assign_custom_user_role_on_purchase_optimized($order_id) { $order = wc_get_order($order_id); $user = $order->get_user(); if (!$user) { // No user associated with the order return; } // Fetch all roles once instead of checking in every iteration $available_roles = array_keys(wp_roles()->get_names()); // Collect all product IDs from the order $product_ids = array_map(function ($item) { return $item->get_product_id(); }, $order->get_items()); // Remove duplicate product IDs to minimize redundant queries $unique_product_ids = array_unique($product_ids); // Loop through unique product IDs foreach ($unique_product_ids as $product_id) { $custom_role = get_post_meta($product_id, 'custom_user_role', true); if (!empty($custom_role) && in_array($custom_role, $available_roles)) { // Assign the custom role to the user $user->set_role($custom_role); // Break the loop as we've found a valid role and assigned it break; } } } // Hook Function to Login add_action('wp_login', 'assign_role_based_on_order_history'); function assign_role_based_on_order_history($user_login) { $user = get_user_by('login', $user_login); if (!$user) { return; } $user_id = $user->ID; // Fetch all roles once $available_roles = array_keys(wp_roles()->get_names()); // Get all completed orders for the user $orders = wc_get_orders(array( 'status' => 'completed', 'customer_id' => $user_id, )); foreach ($orders as $order) { foreach ($order->get_items() as $item) { $product_id = $item->get_product_id(); $custom_role = get_post_meta($product_id, 'custom_user_role', true); if (!empty($custom_role) && in_array($custom_role, $available_roles) && !$user->has_cap('custom_role')) { // Add the custom role to the user without removing existing roles $user->add_role($custom_role); // Consider breaking the loop if only one role should be assigned // break 2; // Uncomment to break out of both loops } } } }
Recommended Plugins with this code:
Blocks visibility Plugin: if you need to show or hide your some of your sections or posts depending on users status or roles you can use this free plugin.
User Role Editor Plugin: You can use this plugin if you want to add and sell other roles.