Collections in WooCommerce like Shopify?

Kishore Sahoo
4 min readOct 18, 2024

--

If you have purchased anything on a Shopify store, you might have seen products grouped as Collections. Something like /collections/winter-sales or /collections/editors-picks, or /collections/under999.

In WooCommerce, we have categories & tags. But there is a huge difference between Categories and Collections. Categories are a navigational tool within your store. A collection refers to a group of products that share a common attribute or are grouped together for easy navigation.

In WooComerce, we do not have Collections. Let’s learn how to build collections using custom taxonomy. First, we need to register a custom taxonomy called Collections.

// hook it to woocommerce_init
add_action( 'woocommerce_init', 'woocommerce_collections_init' );

function woocommerce_collections_init() {
$labels = [
'name' => esc_html__( 'Collections', 'wc-product-collections' ),
'singular_name' => esc_html__( 'Collection', 'wc-product-collections' ),
'menu_name' => esc_html__( 'Collections', 'wc-product-collections' ),
'all_items' => esc_html__( 'All Collections', 'wc-product-collections' ),
'edit_item' => esc_html__( 'Edit Collection', 'wc-product-collections' ),
'view_item' => esc_html__( 'View Collection', 'wc-product-collections' ),
'update_item' => esc_html__( 'Update Collection', 'wc-product-collections' ),
'add_new_item' => esc_html__( 'Add New Collection', 'wc-product-collections' ),
'new_item_name' => esc_html__( 'New Collection Name', 'wc-product-collections' ),
'parent_item' => esc_html__( 'Parent Collection', 'wc-product-collections' ),
'parent_item_colon' => esc_html__( 'Parent Collection:', 'wc-product-collections' ),
'search_items' => esc_html__( 'Search Collections', 'wc-product-collections' ),
'popular_items' => esc_html__( 'Popular Collections', 'wc-product-collections' ),
'back_to_items' => esc_html__( '← Go to Collections', 'wc-product-collections' ),
'separate_items_with_commas' => esc_html__( 'Separate collections with commas', 'wc-product-collections' ),
'add_or_remove_items' => esc_html__( 'Add or remove collections', 'wc-product-collections' ),
'choose_from_most_used' => esc_html__( 'Choose from the most used collections', 'wc-product-collections' ),
'not_found' => esc_html__( 'No collections found', 'wc-product-collections' )
];

$args = [
'hierarchical' => true,
'labels' => $labels,
'show_ui' => true,
'query_var' => true,
'public' => true,
'publicly_queryable' => true,
'show_in_menu' => true,
'show_in_rest' => true,
'show_admin_column' => true,
'rewrite' => [
'slug' => apply_filters( 'wc_product_taxonomy_slug', 'collections' ),
'hierarchical' => true,
'with_front' => apply_filters( 'wc_product_taxonomy_with_front', true )
]
];

// register a taxonomy
register_taxonomy( 'collections', [ 'product' ], $args );
}

Now we need to add a field to this WooComerce taxonomy.

add_action( 'collections_add_form_fields', 'add_term_fields' );
add_action( 'collections_edit_form_fields', 'edit_form_fields', 10, 2 );

function add_term_fields( $taxonomy ) {
?>
<div class="form-field">
<label for="price_range">Price Range</label>
<input type="number" name="price_range" id="price_range" />
<p>Put a price like Under 900</p>
</div>
<?php
}

function edit_form_fields( $term, $taxonomy ) {

// get meta data value
$price_range = get_term_meta( $term->term_id, 'price_range', true );

?><tr class="form-field">
<th><label for="price_range">Price Range</label></th>
<td>
<input name="price_range" id="price_range" type="number" value="<?php echo esc_attr( $price_range ) ?>" />
<p>Put a price like Under 900</p>
</td>
</tr>
<?php
}


// save fields
add_action( 'created_collections', 'wc_product_save_term_fields' );
add_action( 'edited_collections', 'wc_product_save_term_fields' );
function wc_product_save_term_fields( $term_id ) {

update_term_meta(
$term_id,
'price_range',
sanitize_text_field( $_POST[ 'price_range' ] )
);

}

Now, we need a function which will take a price range and return the IDs.

function get_ids_on_price_range($value='100') {
$IDs = array();
$query = array(
'post_status' => 'publish',
'post_type' => 'product',
'posts_per_page' => 99999999,
'meta_query' => array(
array(
'key' => '_price',
'value' => array(0, $value),
'compare' => 'BETWEEN',
'type' => 'NUMERIC'
)
)
);

$wpquery = new WP_Query($query); // return 10 products within the price range 50 - 100
foreach ($wpquery->posts as $key => $value) {
$IDs[] = $value->ID;
}
return $IDs;
}

Now, we need to run the process when the product is created or saved. We have hardcoded the term_id here, but this code can be improved. We can run a cronjob instead of save_post_product hook.


function wpdocs_product_meta( $post_id ) {
// Check the logged in user has permission to edit this post
if ( ! current_user_can( 'manage_options' ) ) {
return $post_id;
}

$term_id = 30; // term id: change it

// get meta data value
$price_range = get_term_meta( $term_id, 'price_range', true );

$IDs = get_ids_on_price_range($price_range);

//print_r($IDs);

foreach ($IDs as $key => $value) {
// code...
wp_set_post_terms( $value, $term_id, 'collections' );
}
//die;
}
add_action( 'save_post_product', 'wpdocs_product_meta' );

Here is the complete code: https://gist.github.com/kish2011/2d99f088d4bdc952e067587f706d47d2

If you are looking for a complete solution for automated Collections creation like Shopify, then email me at kishore @ upnrunn.com

Thanks for reading the article. Also, you can buy things from me on Gumroad.

--

--

No responses yet