PHPwoocommerceintermediate
WooCommerce Related Products Customization
Customize WooCommerce related products display, algorithm, and layout
Faisal Yaqoob
December 23, 2025
#woocommerce#related-products#upsell#cross-sell#product-display
Code
php
1 // Change number of related products displayed 2 add_filter('woocommerce_output_related_products_args', 'custom_related_products_args'); 3 function custom_related_products_args($args) { 4 $args['posts_per_page'] = 8; // Display 8 products 5 $args['columns'] = 4; // Display in 4 columns 6
7 return $args; 8 }
WooCommerce Related Products Customization
Customize how WooCommerce displays related products including the number shown, sorting algorithm, and display layout.
// Change number of related products displayed
add_filter('woocommerce_output_related_products_args', 'custom_related_products_args');
function custom_related_products_args($args) {
$args['posts_per_page'] = 8; // Display 8 products
$args['columns'] = 4; // Display in 4 columns
return $args;
}
Change Related Products Algorithm
// Customize how related products are selected
add_filter('woocommerce_related_products', 'custom_related_products_algorithm', 10, 3);
function custom_related_products_algorithm($related_posts, $product_id, $args) {
$product = wc_get_product($product_id);
if (!$product) {
return $related_posts;
}
// Get products from same categories
$categories = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids'));
// Get products from same tags
$tags = wp_get_post_terms($product_id, 'product_tag', array('fields' => 'ids'));
$related_args = array(
'post_type' => 'product',
'posts_per_page' => $args['posts_per_page'],
'post__not_in' => array($product_id),
'orderby' => 'rand',
'tax_query' => array(
'relation' => 'OR',
)
);
// Prioritize same category
if (!empty($categories)) {
$related_args['tax_query'][] = array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $categories,
);
}
// Then same tags
if (!empty($tags)) {
$related_args['tax_query'][] = array(
'taxonomy' => 'product_tag',
'field' => 'id',
'terms' => $tags,
);
}
$related_query = new WP_Query($related_args);
$related_posts = wp_list_pluck($related_query->posts, 'ID');
return $related_posts;
}
Display Related Products by Price Range
// Show related products in similar price range
add_filter('woocommerce_related_products', 'related_products_by_price', 10, 3);
function related_products_by_price($related_posts, $product_id, $args) {
$product = wc_get_product($product_id);
if (!$product) {
return $related_posts;
}
$price = $product->get_price();
// Define price range (±20%)
$min_price = $price * 0.8;
$max_price = $price * 1.2;
$related_args = array(
'post_type' => 'product',
'posts_per_page' => $args['posts_per_page'],
'post__not_in' => array($product_id),
'orderby' => 'rand',
'meta_query' => array(
array(
'key' => '_price',
'value' => array($min_price, $max_price),
'compare' => 'BETWEEN',
'type' => 'NUMERIC'
)
)
);
$related_query = new WP_Query($related_args);
$related_posts = wp_list_pluck($related_query->posts, 'ID');
return $related_posts;
}
Show Products from Same Brand/Manufacturer
// Display related products from same brand (using custom attribute)
add_filter('woocommerce_related_products', 'related_products_same_brand', 10, 3);
function related_products_same_brand($related_posts, $product_id, $args) {
$product = wc_get_product($product_id);
if (!$product) {
return $related_posts;
}
// Get brand attribute
$brand = $product->get_attribute('brand');
if (empty($brand)) {
return $related_posts;
}
// Find products with same brand
$related_args = array(
'post_type' => 'product',
'posts_per_page' => $args['posts_per_page'],
'post__not_in' => array($product_id),
'orderby' => 'rand',
'tax_query' => array(
array(
'taxonomy' => 'pa_brand',
'field' => 'name',
'terms' => $brand,
)
)
);
$related_query = new WP_Query($related_args);
$related_posts = wp_list_pluck($related_query->posts, 'ID');
return $related_posts;
}
Custom Related Products Heading
// Change related products heading
add_filter('woocommerce_product_related_products_heading', 'custom_related_products_heading');
function custom_related_products_heading() {
return __('You May Also Like', 'woocommerce');
}
Remove Related Products Completely
// Remove related products section
remove_action('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
Move Related Products Position
// Move related products to a different position
remove_action('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
add_action('woocommerce_after_single_product', 'woocommerce_output_related_products', 10);
Show Related Products with Custom Template
// Custom related products display
remove_action('woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
add_action('woocommerce_after_single_product_summary', 'custom_related_products_display', 20);
function custom_related_products_display() {
global $product;
$related_ids = wc_get_related_products($product->get_id(), 6);
if (empty($related_ids)) {
return;
}
echo '<section class="related-products-custom">';
echo '<h2>' . __('Recommended Products', 'woocommerce') . '</h2>';
echo '<div class="products-grid">';
foreach ($related_ids as $related_id) {
$related_product = wc_get_product($related_id);
if (!$related_product) {
continue;
}
echo '<div class="product-item">';
echo '<a href="' . get_permalink($related_id) . '">';
echo $related_product->get_image('medium');
echo '<h3>' . $related_product->get_name() . '</h3>';
echo '<span class="price">' . $related_product->get_price_html() . '</span>';
echo '</a>';
echo '<a href="?add-to-cart=' . $related_id . '" class="button add-to-cart">' .
__('Add to Cart', 'woocommerce') . '</a>';
echo '</div>';
}
echo '</div>';
echo '</section>';
}
Manually Set Related Products
// Add custom field to manually select related products
add_action('woocommerce_product_options_related', 'add_custom_related_products_field');
function add_custom_related_products_field() {
global $post;
echo '<div class="options_group">';
?>
<p class="form-field">
<label for="custom_related_products"><?php _e('Custom Related Products', 'woocommerce'); ?></label>
<select class="wc-product-search" multiple="multiple" style="width: 50%;"
id="custom_related_products" name="custom_related_products[]"
data-placeholder="<?php esc_attr_e('Search for products', 'woocommerce'); ?>"
data-action="woocommerce_json_search_products_and_variations">
<?php
$product_ids = get_post_meta($post->ID, '_custom_related_products', true);
if (!empty($product_ids) && is_array($product_ids)) {
foreach ($product_ids as $product_id) {
$product = wc_get_product($product_id);
if ($product) {
echo '<option value="' . esc_attr($product_id) . '" selected="selected">' .
wp_kses_post($product->get_formatted_name()) . '</option>';
}
}
}
?>
</select>
</p>
<?php
echo '</div>';
}
// Save custom related products
add_action('woocommerce_process_product_meta', 'save_custom_related_products_field');
function save_custom_related_products_field($post_id) {
$custom_related = isset($_POST['custom_related_products']) ?
array_map('intval', $_POST['custom_related_products']) : array();
update_post_meta($post_id, '_custom_related_products', $custom_related);
}
// Use custom related products if set
add_filter('woocommerce_related_products', 'use_custom_related_products', 10, 3);
function use_custom_related_products($related_posts, $product_id, $args) {
$custom_related = get_post_meta($product_id, '_custom_related_products', true);
if (!empty($custom_related) && is_array($custom_related)) {
return array_slice($custom_related, 0, $args['posts_per_page']);
}
return $related_posts;
}
Display Recently Viewed Products
// Track recently viewed products
add_action('woocommerce_before_single_product', 'track_recently_viewed_products');
function track_recently_viewed_products() {
if (!is_singular('product')) {
return;
}
global $post;
if (empty($_COOKIE['woocommerce_recently_viewed'])) {
$viewed_products = array();
} else {
$viewed_products = wp_parse_id_list((array) explode('|', wp_unslash($_COOKIE['woocommerce_recently_viewed'])));
}
// Remove current product from array if it exists
$keys = array_flip($viewed_products);
if (isset($keys[$post->ID])) {
unset($viewed_products[$keys[$post->ID]]);
}
// Add current product to start of array
array_unshift($viewed_products, $post->ID);
// Limit to 15 products
$viewed_products = array_slice($viewed_products, 0, 15);
// Set cookie
wc_setcookie('woocommerce_recently_viewed', implode('|', $viewed_products));
}
// Display recently viewed products
function display_recently_viewed_products() {
if (empty($_COOKIE['woocommerce_recently_viewed'])) {
return;
}
$viewed_products = wp_parse_id_list((array) explode('|', wp_unslash($_COOKIE['woocommerce_recently_viewed'])));
if (empty($viewed_products)) {
return;
}
// Remove current product
if (is_singular('product')) {
global $post;
$viewed_products = array_diff($viewed_products, array($post->ID));
}
if (empty($viewed_products)) {
return;
}
echo '<section class="recently-viewed-products">';
echo '<h2>' . __('Recently Viewed Products', 'woocommerce') . '</h2>';
$args = array(
'post_type' => 'product',
'posts_per_page' => 6,
'post__in' => $viewed_products,
'orderby' => 'post__in',
);
$products = new WP_Query($args);
if ($products->have_posts()) {
echo '<div class="products-grid">';
while ($products->have_posts()) {
$products->the_post();
wc_get_template_part('content', 'product');
}
echo '</div>';
}
wp_reset_postdata();
echo '</section>';
}
Styling
/* Related products custom styling */
.related-products-custom {
margin: 50px 0;
padding: 30px 0;
border-top: 2px solid #e0e0e0;
}
.related-products-custom h2 {
font-size: 28px;
margin-bottom: 30px;
text-align: center;
}
.products-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 30px;
margin-bottom: 30px;
}
.product-item {
text-align: center;
border: 1px solid #e0e0e0;
padding: 20px;
border-radius: 8px;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.product-item:hover {
transform: translateY(-5px);
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
}
.product-item img {
width: 100%;
height: auto;
margin-bottom: 15px;
border-radius: 4px;
}
.product-item h3 {
font-size: 16px;
margin: 10px 0;
min-height: 40px;
}
.product-item .price {
display: block;
font-size: 18px;
font-weight: 600;
color: #0073aa;
margin: 10px 0;
}
.product-item .button {
width: 100%;
margin-top: 10px;
}
/* Recently viewed products */
.recently-viewed-products {
margin: 50px 0;
padding: 30px 0;
background: #f9f9f9;
}
/* Responsive */
@media (max-width: 768px) {
.products-grid {
grid-template-columns: repeat(2, 1fr);
gap: 15px;
}
}
@media (max-width: 480px) {
.products-grid {
grid-template-columns: 1fr;
}
}
Features
- Flexible Display: Control number of products and columns
- Custom Algorithm: Select related products by category, tags, price, or brand
- Manual Selection: Choose specific related products via admin interface
- Price-Based: Show products in similar price range
- Brand-Based: Display products from same manufacturer
- Custom Heading: Change "Related Products" text
- Custom Position: Move related products section
- Custom Template: Full control over HTML output
- Recently Viewed: Track and display recently viewed products
- Cookie-Based Tracking: Persistent across sessions
- Responsive Design: Mobile-friendly grid layout
- Performance: Optimized queries for speed
Dependencies
- WooCommerce
Related Snippets
WooCommerce Custom Product Tabs
Add custom tabs to WooCommerce product pages with dynamic content
PHPwoocommerceintermediate
phpPreview
// Add a new custom tab
add_filter('woocommerce_product_tabs', 'add_custom_product_tab');
function add_custom_product_tab($tabs) {
// Specifications tab
...#woocommerce#product-tabs#ui+1
12/23/2025
View
WooCommerce Product Badges and Labels
Add custom badges and labels to WooCommerce products (Sale, New, Featured, Custom)
PHPwoocommerceintermediate
phpPreview
// Display product badges on product listings and single product pages
add_action('woocommerce_before_shop_loop_item_title', 'display_product_badges', 10);
add_action('woocommerce_before_single_product_summary', 'display_product_badges', 10);
...#woocommerce#badges#labels+2
12/23/2025
View
WooCommerce Bulk Discounts and Quantity Pricing
Implement bulk discounts, quantity-based pricing, and tiered discounts in WooCommerce
PHPwoocommerceadvanced
phpPreview
// Apply bulk discount based on quantity
add_action('woocommerce_before_calculate_totals', 'apply_bulk_discount');
function apply_bulk_discount($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
...#woocommerce#pricing#discounts+2
12/23/2025
View