In the previous articles of this series, we learned how to create custom post types (CPTs) and add custom fields to them. This allowed us to manage CPTs with greater focus and flexibility compared to traditional posts. However, there’s room for further improvement! A custom taxonomy in WordPress offer a fantastic way to organize your content.

Custom Taxonomy in WordPress Explained

Let’s dispel any initial confusion surrounding the term “taxonomy.” In the context of WordPress, a custom taxonomy functions like an organization system for your CPTs. You establish categories (think “Billing,” “Account Management,” etc.) and assign them to individual entries. This allows for the grouping of related content, making it significantly easier for visitors to find the information they seek.

In my case, I’m creating a new FAQ section for my kids’ Cub Scout pack. This system will help categorize similar questions together, making it simple for parents to find the answers they need.

Creating the Custom Taxonomy in WordPress

There isn’t an easy way to break this one down. So I’ll show you the full code example, then we’ll break it down line-by-line. The following snippet crafts a custom taxonomy specifically for our FAQ CPT:

function create_faq_taxonomy() {

  $labels = array(
    'name' => _x( 'FAQ Categories', 'Taxonomy General Name', 'textdomain' ),
    'singular_name' => _x( 'FAQ Category', 'Taxonomy Singular Name', 'textdomain' ),
    'menu_name' => __( 'FAQ Categories', 'textdomain' ),
    'all_items' => __( 'All Categories', 'textdomain' ),
    'edit_item' => __( 'Edit Category', 'textdomain' ),
    'update_item' => __( 'Update Category', 'textdomain' ),
    'add_new_item' => __( 'Add New Category', 'textdomain' ),
    'new_item_name' => __( 'New FAQ Category', 'textdomain' ),
    'parent_item' => __( 'Parent Category', 'textdomain' ),
    'parent_item_colon' => __( 'Parent Category:', 'textdomain' ),
    'search_items' => __( 'Search Categories', 'textdomain' ),
    'popular_items' => __( 'Popular Categories', 'textdomain' ),
    'separate_items_with_commas' => __( 'Separate categories with commas', 'textdomain' ),
    'has_empty_terms' => __( 'No categories found', 'textdomain' ),
    'not_found' => __( 'No categories found', 'textdomain' ),
  );

  $args = array(
    'labels' => $labels,
    'public' => true,
    'hierarchical' => true, // Allows for parent-child relationships
    'show_ui' => true,
    'show_admin_column' => true,
    'query_var' => true,
    'rewrite' => array( 'slug' => 'faq-category' ), // Optional: Set slug for category URLs
    'singular_slug' => 'faq-category', // Optional: Set slug for singular category pages
  );

  register_taxonomy( 'faq_category', array( 'faq' ), $args ); // Register the taxonomy for the 'faq' post type

}
add_action( 'init', 'create_faq_taxonomy' );

1. Defining the Labels

The initial section, $labels, focuses on defining the various labels that will be used throughout the WordPress admin area in relation to your custom taxonomy. These labels serve the purpose of providing clear and user-friendly terminology for actions like editing or adding categories.

Full details on label arguments can be found in the WordPress documentation here: https://developer.wordpress.org/reference/functions/register_taxonomy/#arguments.

2. Configuring the Taxonomy

The subsequent section, $args, delves into the core configuration of our custom taxonomy. Here’s a breakdown of the key parameters:

  • 'labels' => $labels: This line essentially references the labels we meticulously defined in the previous section. These labels will now be incorporated throughout the admin area, ensuring consistency and user-friendliness.
  • 'public' => true: This setting makes our custom taxonomy publicly accessible. This implies that categories associated with this taxonomy will be visible on the front-end of your website, allowing visitors to filter FAQs based on category.
  • 'hierarchical' => true: This parameter enables a hierarchical structure for your categories. Imagine it as a family tree, where you can establish parent-child relationships between categories. For instance, you could create a parent category named “Billing,” and then have child categories like “Payments” and “Subscriptions” nested underneath it.
  • 'show_ui' => true and 'show_admin_column' => true: These settings work in tandem to guarantee that your custom taxonomy is prominently displayed within the WordPress admin area. A dedicated menu item will be present for managing categories, and a column showcasing the assigned categories will be visible when editing individual FAQs.
  • 'query_var' => true: This enables you to leverage the custom taxonomy within URLs on your website. For example, you could potentially create archive pages showcasing all FAQs belonging to a specific category.
  • 'rewrite' => array( 'slug' => 'faq-category' ) (Optional): This section allows you to customize the slug that appears in your URLs for categories. By default, WordPress uses the taxonomy name. In this case, we’re opting for a more descriptive slug, “faq-category.”
  • 'singular_slug' => 'faq-category' (Optional): Similar to the previous setting, this line enables you to customize the slug used for singular category pages. We’ve maintained consistency by using “faq-category” here as well.

3. Registering the Taxonomy

The final line of code, register_taxonomy, is the piece that brings everything together. It essentially registers our custom taxonomy, named “faq_category,” and associates it with our previously established FAQ CPT (“faq”). This connection allows us to assign categories to individual FAQ entries, enabling the organization and filtering functionality we discussed earlier.

Adding Custom Taxonomy to Content in WordPress

Assigning categories to your content is easy enough. Within the WordPress admin area, when you edit an custom post entry, you’ll notice a new section dedicated to “Custom Post Categories.” Here, you can select the appropriate categories that best represent the subject matter.

By leveraging custom taxonomies, you’ll significantly enhance the user experience of your website’s custom post section. Visitors will no longer have to navigate a labyrinth of information. Instead, they’ll be able to effortlessly find the answers they seek by filtering based on relevant categories. This not only improves user satisfaction but also reduces bounce rates and keeps visitors engaged on your website.

Enhancing the User Experience with Custom Columns

Now that we’ve established a way to categorize your content, let’s add another layer of convenience: custom columns. This functionality allows you to display additional information alongside the standard details within the custom post type list screen in the WordPress admin area.

For instance, I’ve assigned a “weight” to each FAQ, signifying its priority or order of importance. By creating a custom column named “Weight,” you can effortlessly view these weight values within the list, saving you time and simplifying organization.

Here’s the code that creates this custom column functionality:

// Add custom column to the FAQ list screen
function add_faq_columns($columns) {
  $columns['faq_weight'] = 'Weight';
  return $columns;
}
add_filter('manage_edit-faq_columns', 'add_faq_columns');

// Display data in the custom column
function custom_faq_column_content($column_name, $post_id) {
  if ($column_name == 'faq_weight') {
    $weight = get_post_meta($post_id, 'faq_weight', true);
    echo $weight ? $weight : '0'; // Default to 0 if no weight is set
  }
}
add_action('manage_faq_posts_custom_column', 'custom_faq_column_content', 10, 2);

// Make the custom column sortable
function sortable_faq_columns($columns) {
  $columns['faq_weight'] = 'faq_weight';
  return $columns;
}
add_filter('manage_edit-faq_sortable_columns', 'sortable_faq_columns');

// Modify the query to sort by the custom field
function sort_faq_by_custom_column($query) {
  if (!is_admin()) {
    return;
  }

  $orderby = $query->get('orderby');

  if ($orderby == 'faq_weight') {
    $query->set('meta_key', 'faq_weight');
    $query->set('orderby', 'meta_value_num');
  }
}
add_action('pre_get_posts', 'sort_faq_by_custom_column');

Explanation of the Custom Column Code

  • The add_faq_columns function adds a new column named “Weight” to the FAQ list screen.
  • The custom_faq_column_content function retrieves the weight value assigned to a specific FAQ using the get_post_meta function. If no weight is set, it defaults to 0.
  • The sortable_faq_columns function makes the custom “Weight” column sortable, allowing you to order FAQs by weight.
  • The sort_faq_by_custom_column function modifies the database query behind the scenes when sorting by the custom column. It ensures that the sorting happens based on the numeric value of the weight meta field.

Enhancing Convenience with Quick Edit

The previous code snippets focused on creating and managing the custom “Weight” column within the FAQ list screen. But what if you could edit the weight value directly without needing to open each FAQ entry? That’s where Quick Edit comes in.

This additional code allows you to modify the weight value for an FAQ straight from the list screen using the Quick Edit feature.

// Enqueue script for Quick Edit
function enqueue_quick_edit_script($hook) {
    global $post_type;
    if ($hook == 'edit.php' && $post_type == 'faq') {
        wp_enqueue_script('faq-quick-edit', get_template_directory_uri() . '/js/faq-quick-edit.js', array('jquery'), null, true);
    }
}
add_action('admin_enqueue_scripts', 'enqueue_quick_edit_script');

// Add custom field to Quick Edit
function add_custom_quick_edit_field($column_name, $post_type) {
    if ($column_name == 'faq_weight') {
        echo '<fieldset class="inline-edit-col-right"><div class="inline-edit-col"><label><span class="title">Weight</span><input type="text" name="faq_weight" class="faq_weight" /></label></div></fieldset>';
    }
}
add_action('quick_edit_custom_box', 'add_custom_quick_edit_field', 10, 2);

// Save custom field value from Quick Edit
function save_custom_quick_edit_field($post_id) {
    if (isset($_REQUEST['faq_weight'])) {
        $weight = sanitize_text_field($_REQUEST['faq_weight']);
        update_post_meta($post_id, 'faq_weight', $weight);
    }
}
add_action('save_post_faq', 'save_custom_quick_edit_field');

Here’s a breakdown of what each code snippet achieves:

1. Enqueuing the Script (enqueue_quick_edit_script)

This function checks if the current page is the edit screen for the FAQ post type. If so, it enqueues a custom JavaScript file named “faq-quick-edit.js” located in your theme’s directory (replace /js/faq-quick-edit.js with the actual file path if different). This JavaScript file contains the logic for capturing user input when editing the weight via Quick Edit.

2. Adding the Custom Field to Quick Edit (add_custom_quick_edit_field)

This function checks if the current column being edited is the “faq_weight” column. If it is, it dynamically adds the necessary HTML structure to display an input field labeled “Weight” within the Quick Edit box. This allows you to enter a new weight value directly.

3. Saving the Custom Field Value (save_custom_quick_edit_field)

This function captures the user-entered weight value from the Quick Edit form when saving changes. It then sanitizes the input and updates the corresponding weight meta field for the specific FAQ using the update_post_meta function.

Full Code Example

function create_faq_taxonomy() {

  $labels = array(
    'name' => _x( 'FAQ Categories', 'Taxonomy General Name', 'textdomain' ),
    'singular_name' => _x( 'FAQ Category', 'Taxonomy Singular Name', 'textdomain' ),
    'menu_name' => __( 'FAQ Categories', 'textdomain' ),
    'all_items' => __( 'All Categories', 'textdomain' ),
    'edit_item' => __( 'Edit Category', 'textdomain' ),
    'update_item' => __( 'Update Category', 'textdomain' ),
    'add_new_item' => __( 'Add New Category', 'textdomain' ),
    'new_item_name' => __( 'New FAQ Category', 'textdomain' ),
    'parent_item' => __( 'Parent Category', 'textdomain' ),
    'parent_item_colon' => __( 'Parent Category:', 'textdomain' ),
    'search_items' => __( 'Search Categories', 'textdomain' ),
    'popular_items' => __( 'Popular Categories', 'textdomain' ),
    'separate_items_with_commas' => __( 'Separate categories with commas', 'textdomain' ),
    'has_empty_terms' => __( 'No categories found', 'textdomain' ),
    'not_found' => __( 'No categories found', 'textdomain' ),
  );

  $args = array(
    'labels' => $labels,
    'public' => true,
    'hierarchical' => true, // Allows for parent-child relationships
    'show_ui' => true,
    'show_admin_column' => true,
    'query_var' => true,
    'rewrite' => array( 'slug' => 'faq-category' ), // Optional: Set slug for category URLs
    'singular_slug' => 'faq-category', // Optional: Set slug for singular category pages
  );

  register_taxonomy( 'faq_category', array( 'faq' ), $args ); // Register the taxonomy for the 'faq' post type

}
add_action( 'init', 'create_faq_taxonomy' );

// Replace 'textdomain' with your actual text domain for translations

// Add custom column to the FAQ list screen
function add_faq_columns($columns) {
    $columns['faq_weight'] = 'Weight';
    return $columns;
}
add_filter('manage_edit-faq_columns', 'add_faq_columns');

// Display data in the custom column
function custom_faq_column_content($column_name, $post_id) {
    if ($column_name == 'faq_weight') {
        $weight = get_post_meta($post_id, 'faq_weight', true);
        echo $weight ? $weight : '0'; // Default to 0 if no weight is set
    }
}
add_action('manage_faq_posts_custom_column', 'custom_faq_column_content', 10, 2);

// Make the custom column sortable
function sortable_faq_columns($columns) {
    $columns['faq_weight'] = 'faq_weight';
    return $columns;
}
add_filter('manage_edit-faq_sortable_columns', 'sortable_faq_columns');

// Modify the query to sort by the custom field
function sort_faq_by_custom_column($query) {
    if (!is_admin()) {
        return;
    }

    $orderby = $query->get('orderby');

    if ($orderby == 'faq_weight') {
        $query->set('meta_key', 'faq_weight');
        $query->set('orderby', 'meta_value_num');
    }
}
add_action('pre_get_posts', 'sort_faq_by_custom_column');

// Enqueue script for Quick Edit
function enqueue_quick_edit_script($hook) {
    global $post_type;
    if ($hook == 'edit.php' && $post_type == 'faq') {
        wp_enqueue_script('faq-quick-edit', get_template_directory_uri() . '/js/faq-quick-edit.js', array('jquery'), null, true);
    }
}
add_action('admin_enqueue_scripts', 'enqueue_quick_edit_script');

// Add custom field to Quick Edit
function add_custom_quick_edit_field($column_name, $post_type) {
    if ($column_name == 'faq_weight') {
        echo '<fieldset class="inline-edit-col-right"><div class="inline-edit-col"><label><span class="title">Weight</span><input type="text" name="faq_weight" class="faq_weight" /></label></div></fieldset>';
    }
}
add_action('quick_edit_custom_box', 'add_custom_quick_edit_field', 10, 2);

// Save custom field value from Quick Edit
function save_custom_quick_edit_field($post_id) {
    if (isset($_REQUEST['faq_weight'])) {
        $weight = sanitize_text_field($_REQUEST['faq_weight']);
        update_post_meta($post_id, 'faq_weight', $weight);
    }
}
add_action('save_post_faq', 'save_custom_quick_edit_field');

Conclusion: Custom Taxonomy in WordPress

In this article, we’ve successfully add a custom taxonomy to our custom post type in WordPress. This step-by-step explanation should enable you to implement this functionality on your own websites. Remember, well-organized content is a key element in crafting a positive user experience.

In the fourth and final article of this series, we’ll craft the front-end template for our FAQs. This will allow us to customize the way content is displayed on your website, ensuring a visually appealing and user-friendly experience for visitors.

Categories: WordPress

Mitchell Opitz

Mitchell is a dedicated web developer with a flair for creativity, constantly exploring new horizons. Dive into his journey through web development, Arduino projects, and game development on his blog: MitchellOpitz.net

Tweet
Share
Share