Membership site

I run a few sites (one with WooCommerce as a catalogue) made with BricksBuilder and the Crocoblock suite.

I have a request from a friend of mine to create a blog site with membership (paid and free) and a comments system. My question is: is it possible to achieve this with my current stack (payments should be done through WooCommerce because of the local gateway), or do I have to invest in some additional add-ons?

Any pointers, suggestions, or examples are much appreciated.

simplifed definition of membership site is = payment and roles

bricks conditions can handle the roles easily
rest is just show this section to visitors show this section to this roles only conditions setups on your design thats it.

check this it may help I am making a membership site too at the moment.
watch the both videos they are short anyway.

1 Like

I have created a few membership sites using Woocommerce and just a small snippet of code to create a custom function (then it checks to see if the user has purchased the course/product).

Is that what you are looking for?

Thanks for your time, @sinanisler

Your solution is “overkill” for me and, as I said, I’m forced to use a local payment processor which have a plugin only for WooCommerce. I’ve found a few videos on WPTuts that might do the trick.

Best regards,

Goran

Thanks @shingen

Something like this. I’m looking at JetFormBuilder and WooCommerce integration to solve payment. As for user roles I’ve found snippet that solved that issue.

Best regards

Goran

You don’t need JetFormBuilder 
 just Bricks and Woocommerce.

Also, you don’t need an additional code snippet for role changing, as this has it built in.

So there are two parts to it. 1. A custom function and 2. The membership code

  1. Custom Function: Add this to your functions file of your child theme or in a code snippets plugin.

    // Bricks Date Comparison
    add_filter(“bricks/code/echo_function_names”, function () {
    return [
    ‘user_has_bought_product’,
    ];
    });

  2. Membership Code: Add to a PHP file and then call it via your functions file or again, use a code snippets plugin.

    /**
    
    WooCommerce Course Access System for Bricks Builder
    
    Features:
    
    Creates WordPress accounts on completed purchases
    
    Checks course access permissions
    
    Integrates with Bricks Builder dynamic data
    
    Handles clean username generation
    
    Sends password setup emails
    */
    
    // Security check
    if (!defined(‘ABSPATH’)) {
    exit;
    }
    
    /**
    
    Check if user has purchased a specific product
    
    
    
    @param int $product_id The product ID to check
    
    @return bool True if purchased, false otherwise
    */
    function user_has_bought_product($product_id) {
    if (!is_user_logged_in()) return false;
    
    $user_id = get_current_user_id();
    
    // First check user meta for cached purchases
    $purchased_courses = get_user_meta($user_id, ‘purchased_courses’, false);
    if (in_array($product_id, $purchased_courses)) {
    return true;
    }
    
    // If not found in meta, check order history
    return check_orders_for_product($user_id, $product_id);
    }
    
    /**
    
    Check order history for specific product purchase
    
    
    
    @param int $user_id WordPress user ID
    
    @param int $product_id WooCommerce product ID
    
    @return bool True if found in orders
    */
    function check_orders_for_product($user_id, $product_id) {
    $orders = wc_get_orders([
    ‘customer_id’ => $user_id,
    ‘status’ => ‘completed’,
    ‘limit’ => -1,
    ‘return’ => ‘ids’,
    ]);
    
    foreach ($orders as $order_id) {
    $order = wc_get_order($order_id);
    foreach ($order->get_items() as $item) {
    if ($item->get_product_id() == $product_id) {
    // Cache this purchase in user meta
    add_user_meta($user_id, ‘purchased_courses’, $product_id);
    return true;
    }
    }
    }
    
    return false;
    }
    
    /**
    
    Register Bricks Builder dynamic data function
    */
    add_filter(‘bricks/custom/dynamic_data’, function($tags) {
    $tags[‘user_has_bought_product’] = [
    ‘label’ => ‘Check Product Purchase’,
    ‘callback’ => function($attributes) {
    if (empty($attributes[‘product_id’])) {
    error_log(‘Missing product_id parameter in user_has_bought_product’);
    return false;
    }
    return user_has_bought_product(intval($attributes[‘product_id’]));
    },
    ‘params’ => [
    ‘product_id’ => [
    ‘label’ => ‘Product ID’,
    ‘type’ => ‘number’,
    ‘required’ => true
    ]
    ]
    ];
    return $tags;
    });
    
    /**
    
    Create WordPress user when WooCommerce order is completed
    */
    add_action(‘woocommerce_order_status_completed’, ‘create_wp_user_on_order_completion’, 10, 2);
    
    function create_wp_user_on_order_completion($order_id, $order) {
    // Get the customer email from the order
    $customer_email = $order->get_billing_email();
    
    // Check if a user already exists with this email
    if (email_exists($customer_email)) {
        return; // User already exists, do nothing
    }
    
    // Get customer details from the order
    $first_name = $order->get_billing_first_name();
    $last_name = $order->get_billing_last_name();
    
    // Generate clean username (firstname.lastname)
    $username = generate_clean_username($first_name, $last_name, $customer_email);
    
    // Generate a random password (will be reset via email)
    $password = wp_generate_password();
    
    // Create the new user with default role
    $user_id = wp_create_user($username, $password, $customer_email);
    
    if (is_wp_error($user_id)) {
        error_log('Failed to create user for order ' . $order_id . ': ' . $user_id->get_error_message());
        return;
    }
    
    // Assign course student role
    $user = new WP_User($user_id);
    $user->set_role('customer'); // Change to your preferred role
    
    // Update user meta with names
    wp_update_user([
        'ID' => $user_id,
        'first_name' => $first_name,
        'last_name' => $last_name,
        'display_name' => $first_name . ' ' . $last_name
    ]);
    
    // Store billing information
    update_user_meta($user_id, 'billing_first_name', $first_name);
    update_user_meta($user_id, 'billing_last_name', $last_name);
    update_user_meta($user_id, 'billing_email', $customer_email);
    update_user_meta($user_id, 'billing_phone', $order->get_billing_phone());
    update_user_meta($user_id, 'billing_address_1', $order->get_billing_address_1());
    update_user_meta($user_id, 'billing_city', $order->get_billing_city());
    update_user_meta($user_id, 'billing_postcode', $order->get_billing_postcode());
    update_user_meta($user_id, 'billing_country', $order->get_billing_country());
    
    // Track purchased courses
    foreach ($order->get_items() as $item) {
        add_user_meta($user_id, 'purchased_courses', $item->get_product_id());
    }
    
    // Send password reset email
    send_password_reset_email($user_id);
    
    }
    
    /**
    
    Generate clean username (firstname.lastname)
    
    Handles duplicates by adding incrementing number
    */
    function generate_clean_username($first_name, $last_name, $email = ‘’) {
    // Sanitize names - remove accents, special chars, etc.
    $clean_first = sanitize_title($first_name);
    $clean_last = sanitize_title($last_name);
    
    // Remove any remaining special characters
    $clean_first = preg_replace(‘/[^a-z0-9]/’, ‘’, $clean_first);
    $clean_last = preg_replace(‘/[^a-z0-9]/’, ‘’, $clean_last);
    
    // If either name is empty after cleaning, use email prefix as fallback
    if (empty($clean_first) || empty($clean_last)) {
    return sanitize_user(current(explode(‘@’, $email)), true);
    }
    
    // Create base username
    $base_username = $clean_first . ‘.’ . $clean_last;
    $username = $base_username;
    $counter = 1;
    
    // Check if username exists and increment if needed
    while (username_exists($username)) {
    $username = $base_username . $counter;
    $counter++;
    }
    
    return $username;
    }
    
    /**
    
    Send password reset email to new user
    */
    function send_password_reset_email($user_id) {
    $user = get_userdata($user_id);
    if (!$user) return;
    
    $key = get_password_reset_key($user);
    if (is_wp_error($key)) return;
    
    $reset_url = network_site_url(“wp-login.php?action=rp&key=$key&login=” . rawurlencode($user->user_login), ‘login’);
    
    $subject = sprintf(__(‘Set your password for %s’), get_bloginfo(‘name’));
    
    $message = sprintf(__(‘Hello %s,’), $user->first_name) . “\r\n\r\n”;
    $message .= __(‘Your account has been created.’) . “\r\n\r\n”;
    $message .= __(‘To set your password, please click the following link:’) . “\r\n\r\n”;
    $message .= $reset_url . “\r\n\r\n”;
    $message .= __(‘This link will expire in 24 hours.’) . “\r\n\r\n”;
    $message .= __(“If you didn’t request this, please ignore this email.”) . “\r\n”;
    
    wp_mail($user->user_email, $subject, $message);
    }
    

Now use Bricks conditions and call the custom function like this.

{echo:user_has_bought_product(1234)}

Change “1234” to the product ID. This way when that product is bought, it checks the ID to ensure the user has purchased that item.

Also, as you will see at the bottom of the code an account is created for them; they are assigned to the “customer” role; and an email is sent out to them.

Have a look and see if this is something that might work for you. It has worked great for me on many clients that use it as a student/course membership setup.

Cheers

2 Likes

I would still suggest role based membership setup.
managing roles easier and long term safe when you want to change some stuff.

you never know when that time comes and usualy when it does it is the worst possible moment
 :rofl:

here good plugin from woocommerce
a bit advanced but this solves so many edge cases its worth to invest license cost not that much.

I recommend just buy the plugin :wink:

I even wrote a snippet for this 2 years ago
but it is way too simple probably needs to be tested a bit

I’ll look at it. Not just my decision. Depends on the client’s budget. :wink:

1 Like

if 50$ is too much for the client RUN :joy:

Well, it’s a friend, a non-profit
 so every cent counts. I’m doing this pro bono. The subscription is intended to cover hosting and maintenance expenses.

1 Like

I also created a plugin for free that manages roles if needed. No need to pay money.

Also, just as an aside. If you want to do role based that too is easy and create. Take the code I suggested and just change the role from customer to something like “student”. If you want to be able to change that role, you can create that via the role snippet you have already and use the ASE free plugin, as it allows you to manage multiple roles.

1 Like