---
title: "How to Restrict Page Access Based on Purchased Products in WooCommerce"
description: "Learn how to restrict page access on your WooCommerce store based on users' purchase history. This step-by-step guide walks you through adding custom…"
url: "https://sajdoko.com/blog/how-to-restrict-page-access-based-on-purchased-products-in-woocommerce/"
language: "en"
content_signal: "ai-train=no, search=yes, ai-input=yes"
---
# How to Restrict Page Access Based on Purchased Products in WooCommerce

 12 September 2024·8 minutes read·[WooCommerce](https://sajdoko.com/blog/category/wordpress/woocommerce/)     

If you’re running a WooCommerce store, you may want to restrict access to certain pages based on the products a user has purchased. For example, you might offer exclusive content or services to customers who have bought specific products. This tutorial will guide you through the process of restricting access to pages based on a user’s purchase history using WooCommerce and some custom code.

 

## Step-by-Step Guide

 

### 1. Overview of the Code

 

The code below does two main things:

 

- Checks if a user is logged in and has bought the required product. If not, they are redirected to the login page or the product page.
- Adds a link to the user’s WooCommerce account dashboard showing which pages they can access based on their purchases.

 

### 2. Restricting Page Access Based on Product Purchases

 

First, we need to restrict access to specific pages depending on whether the user has purchased a product. If they haven’t, they will be redirected to either the login page (if not logged in) or the product page (if they haven’t bought the product).

 

```
/**
 * Check if user is logged in and bought the product. If not, redirect to login page.
 */
function sajdoko_to_login_if_not_customer() {
    global $post;

    // Get the current user ID and user object
    $user_id = get_current_user_id();
    $current_user = wp_get_current_user();
    $customer_email = $current_user->user_email;

    // Mapping of restricted pages to their corresponding product IDs
    $relation_page_product = [1439 => 1211, 1431 => 1210, 1441 => 1214, 1440 => 1212]; //page => product

    // Check if the current page is one of the restricted pages
    if (isset($relation_page_product[$post->ID])) {
        // If user is logged in, check if they have bought the product
        if (is_user_logged_in()) {
            // If user has not bought the product, redirect to the product page
            if (!wc_customer_bought_product_paid($customer_email, $user_id, $relation_page_product[$post->ID])) {
                wp_redirect(esc_url(get_permalink($relation_page_product[$post->ID])));
                exit;
            }
        } else {
            // If user is not logged in, redirect to the login page
            wp_redirect(esc_url(wp_login_url()), 307);
            exit;
        }
    }
}
add_action('wp', 'sajdoko_to_login_if_not_customer');
```

 

This function works as follows:

 

1. It checks whether the user is logged in.
2. If logged in, it verifies if the user has purchased the required product for the page they are trying to access.
3. If they haven’t bought the product, they are redirected to the product page.
4. If not logged in, the user is redirected to the login page.

 

### 3. Showing Accessible Pages on the User’s Dashboard

 

Next, we’ll show users links to pages they can access based on the products they’ve bought. This is done by adding a list of accessible pages to the user’s WooCommerce dashboard.

 

```
function sajdoko_show_link_page_to_dashboard() {
    // Get the current user ID and user object
    $user_id = get_current_user_id();
    $current_user = wp_get_current_user();
    $customer_email = $current_user->user_email;

    // Mapping of product IDs to their corresponding page IDs
    $relation_product_page = [1211 => 1439, 1210 => 1431, 1214 => 1441, 1212 => 1440]; //product => page

    // Get the list of products bought by the user
    $bought_products = sajdoko_get_bought_products();

    // If the user has bought products, display them
    if (!empty($bought_products)) {
        echo '<h3>' . sprintf(__('Paketat aktive: %s', 'woocommerce'), count($bought_products)) . '</h3>';
        echo '<ul>';
        foreach ($bought_products as $product_id) {
            // Check if the user has bought and paid for the product
            if (wc_customer_bought_product_paid($customer_email, $user_id, $product_id)) {
                $page_id = $relation_product_page[$product_id] ?? null;
                if ($page_id) {
                    $link = esc_url(get_permalink($page_id));
                    echo "<li><a href="$link">" . get_the_title($page_id) . "</a></li>";
                }
            }
        }
        echo '</ul>';
    }
}
add_action('woocommerce_account_dashboard', 'sajdoko_show_link_page_to_dashboard', 10);
```

 

This function:

 

- Retrieves the list of products the user has bought.
- Maps each product to a corresponding page.
- Displays links to these pages on the user’s WooCommerce dashboard.

 

### 4. Helper Functions

 

The two helper functions below handle checking if the user has purchased and paid for a product and retrieving the list of purchased products.

 

#### Checking If a Product Is Bought and Paid

 

```
/**
 * Check if the product is bought and paid.
 */
function wc_customer_bought_product_paid($customer_email, $user_id, $product_id) {
    global $wpdb;

    // Apply filters to check if the product is bought
    $result = apply_filters('woocommerce_pre_customer_bought_product', null, $customer_email, $user_id, $product_id);

    if (null !== $result) {
        return $result;
    }

    // Generate a transient name for caching
    $transient_name = 'wc_cbp_' . md5($customer_email . $user_id . WC_Cache_Helper::get_transient_version('orders'));

    // Check if the result is cached
    if (false === ($result = get_transient($transient_name))) {
        $customer_data = array_filter(array_unique([$user_id, $customer_email]));

        // Sanitize and filter customer data
        $customer_data = array_map('esc_sql', $customer_data);
        $statuses = array_map('esc_sql', wc_get_is_paid_statuses());

        // If no customer data is available, return false
        if (empty($customer_data)) {
            return false;
        }

        // Query the database to check if the product is bought and paid
        $result = $wpdb->get_col("
            SELECT im.meta_value FROM {$wpdb->posts} AS p
            INNER JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_items AS i ON p.ID = i.order_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS im ON i.order_item_id = im.order_item_id
            WHERE p.post_status IN ('wc-" . implode("','wc-", $statuses) . "')
            AND pm.meta_key IN ('_billing_email', '_customer_user')
            AND im.meta_key IN ('_product_id', '_variation_id')
            AND im.meta_value != 0
            AND pm.meta_value IN ('" . implode("','", $customer_data) . "')
        ");
        $result = array_map('absint', $result);

        // Cache the result
        set_transient($transient_name, $result, DAY_IN_SECONDS * 30);
    }
    return in_array(absint($product_id), $result);
}
```

 

#### Getting the List of Bought Products

 

```
function sajdoko_get_bought_products() {
    // Get the current user object
    $current_user = wp_get_current_user();

    // Check if the user is valid
    if (0 == $current_user->ID) {
        return [];
    }

    // Create arguments array for querying orders
    $args = [
        'numberposts' => -1,
        'meta_key' => '_customer_user',
        'meta_value' => $current_user->ID,
        'post_type' => wc_get_order_types(),
        'post_status' => array_keys(wc_get_is_paid_statuses()),
    ];

    // Get the list of customer orders
    $customer_orders = get_posts($args);

    // If no orders are found, return
    if (!$customer_orders) {
        return [];
    }

    // Loop through the orders and collect product IDs
    $product_ids = [];
    foreach ($customer_orders as $customer_order) {
        $order = wc_get_order($customer_order->ID);
        foreach ($order->get_items() as $item) {
            $product_ids[] = $item->get_product_id();
        }
    }

    return $product_ids;
}
```

 

## How to Implement This Code on Your Existing Website

 

To implement this functionality on your WooCommerce site, follow the steps below:

 

### 1. Add the Code to Your Theme’s Functions.php File

 

The easiest way to add this custom code is by placing it inside your theme’s `functions.php` file. Here’s how:

 

1. Log into your WordPress dashboard.
2. Navigate to **Appearance** > **Theme File Editor**.
3. In the file list on the right, find and click on `functions.php` under your active theme.
4. Paste the provided code at the end of the file.
5. Click **Update File** to save your changes.

 

**Note:** Make sure to back up your site before making any modifications to your theme files.

 

### 2. Use a Custom Plugin

 

If you prefer to keep your theme files untouched, creating a small custom plugin for this functionality is a more modular solution. Here’s how you can do it:

 

1. In your WordPress dashboard, go to **Plugins** > **Add New** and click on **Create a Plugin** (or use a plugin like *Code Snippets*).
2. Create a new plugin file by navigating to `wp-content/plugins/` on your server using an FTP client or file manager.
3. Create a folder for your custom plugin (e.g., `sajdoko-restrict-access`) and add a `.php` file within it.
4. Paste the code into this file, starting with a plugin header like: ``` /* Plugin Name: Sajdoko Restrict Access by Product Purchase Description: Restricts access to pages based on WooCommerce product purchases. Version: 1.0 Author: Your Name */ ```
5. Once you’ve saved the file, navigate back to the WordPress dashboard and activate your new plugin under the **Plugins** section.

 

### 3. Test the Functionality

 

After implementing the code, test it by logging into your website with a user account that has and hasn’t purchased the required products. Try accessing restricted pages and verify that users are properly redirected based on their purchase status. Also, check the user’s WooCommerce account dashboard to ensure the correct links appear for purchased products.

 

Make sure to clear your site’s cache if you’re using a caching plugin to see the changes immediately.

  

- [Code](https://sajdoko.com/blog/category/wordpress/code/)
- [WooCommerce](https://sajdoko.com/blog/category/wordpress/woocommerce/)
- [WordPress](https://sajdoko.com/blog/category/wordpress/)
- [woocommerce](https://sajdoko.com/blog/tag/woocommerce/)

   

## Have a project in mind?

 

Write to us and we come back with a concrete estimate within one working day.

  [Contact us →](https://sajdoko.com/contact/)     

## Leave a comment [Cancel](https://sajdoko.com/blog/how-to-restrict-page-access-based-on-purchased-products-in-woocommerce/?format=markdown#respond)

      

## Recent Posts

- [Fleet management software: what do you need beyond GPS?](https://sajdoko.com/blog/fleet-management-software-requirements-beyond-gps/)
- [Custom CRM Development vs Generic SaaS: The ROI Framework for Growing Enterprises](https://sajdoko.com/blog/custom-crm-development-vs-generic-saas/)
- [Web and Software Development Costs in Albania: The International Buyer’s Strategic Guide](https://sajdoko.com/blog/website-costs-in-albania-international-perspective/)
- [Scaling WooCommerce Performance: Eliminating High-Traffic Checkout Bottlenecks](https://sajdoko.com/blog/scaling-woocommerce-performance-checkout-bottlenecks/)
- [The Hidden Cost of Cheap or “Free” Websites: Why €100 Web Design Costs €3,000 Later](https://sajdoko.com/blog/the-hidden-cost-of-cheap-or-free-websites/)

## Recent Comments

1. Alvaro on [Optimizing and Extending the Livewire Product Filter – Part 4](https://sajdoko.com/blog/optimizing-and-extending-the-livewire-product-filter/#comment-4)
2. [sajdoko](https://sajdoko.com) on [How to Set Up WordPress on localhost Using XAMPP: A Step-by-Step Guide](https://sajdoko.com/blog/how-to-install-wordpress-on-localhost-using-xampp-step-by-step-guide/#comment-3)
3. Roshni on [How to Set Up WordPress on localhost Using XAMPP: A Step-by-Step Guide](https://sajdoko.com/blog/how-to-install-wordpress-on-localhost-using-xampp-step-by-step-guide/#comment-2)
