Categories, tags and attributes
Products are grouped in three ways: categories (Mugs, Plates), tags (gift, new) and attributes (Color: white). All of these are WordPress taxonomies, and a single value — the Mugs category, the color white — is called a term.
Taxonomies
| What | Taxonomy | Where in the admin panel |
|---|---|---|
| Categories | product_cat | Products → Categories |
| Tags | product_tag | Products → Tags |
| The global Color attribute | pa_color | Products → Attributes |
Create a Mugs category with the slug mugs in the admin panel and put the mug into it.
A product's categories
// wp-content/plugins/acme-shop/includes/products.php
add_action('woocommerce_single_product_summary', function () {
global $product;
$names = wc_get_product_terms($product->get_id(), 'product_cat', ['fields' => 'names']);
if ($names) {
echo '<p>Section: ' . esc_html(implode(', ', $names)) . '</p>';
}
}, 7);wc_get_product_terms() returns a product's terms in the given taxonomy. With fields => names it is an array of names; without it, an array of WP_Term objects with the term_id, name and slug fields. The line Section: Mugs appears under the product name.
Checking a category
if (has_term('mugs', 'product_cat', $product->get_id())) {
echo '<p>Dishwasher safe.</p>';
}has_term() accepts a term slug, name or ID. This is how a block is shown only for products of one category.
Assigning in code
// wp-content/plugins/acme-shop/scripts/assign-category.php
$term = wp_insert_term('Plates', 'product_cat', ['slug' => 'plates']);
$product = wc_get_product(18);
$product->set_category_ids([$term['term_id']]);
$product->save();wp_insert_term() creates a category and returns an array with its ID. set_category_ids() replaces the product's category list. Tags have the same pair, get_tag_ids() and set_tag_ids().
Attributes: global and custom
A global attribute is created once in Products → Attributes and used by many products; the catalog can be filtered by it. For an attribute with the slug color the taxonomy is called pa_color. A custom attribute is typed right in the product editor and exists only on that product.
Reading an attribute
// wp-content/plugins/acme-shop/includes/products.php
add_action('woocommerce_single_product_summary', function () {
global $product;
$color = $product->get_attribute('pa_color');
if ($color !== '') {
echo '<p>Color: ' . esc_html($color) . '</p>';
}
}, 21);get_attribute() returns the values as a comma-separated string: White, Blue. It works for both global and custom attributes. An array of a global attribute's values comes from wc_get_product_terms($product->get_id(), 'pa_color', ['fields' => 'names']).
A list of categories
$categories = get_terms([
'taxonomy' => 'product_cat',
'hide_empty' => true,
]);
foreach ($categories as $category) {
printf('<a href="%s">%s</a> ', esc_url(get_term_link($category)), esc_html($category->name));
}The code prints links to all categories that contain products. Such a block is convenient to attach to the woocommerce_before_shop_loop hook.
Common mistake
A global attribute is looked up by its name without the prefix: wc_get_product_terms($id, 'color') returns an empty array. An attribute taxonomy always starts with pa_. The exact name is visible in the address of the Configure terms page in Products → Attributes: taxonomy=pa_color.