Creating a Custom WordPress Shortcode to Display Taxonomy Terms

When building custom post types with Advanced Custom Fields (ACF), you might find yourself needing to display taxonomy information in specific ways that go beyond Kadence WP’s Element template default capabilities. Recently, I needed to create a sponsor page that would dynamically show the sponsor’s level (Gold, Bronze, etc.) for a specific year without duplicating data already stored in taxonomies.

The Challenge

I was working with a WordPress site using KadenceWP elements with a template for sponsors and had:

  • Of course, the custom post type called “sponsor”
  • A custom taxonomy called “sponsor-level”
  • Taxonomy terms structured like “2026-Gold”, “2026-Bronze”, etc.
  • A need to display just the level portion (e.g., “2026 Gold”) within an existing H3 block

The goal was to avoid creating redundant ACF custom fields that mirror taxonomy terms when the taxonomy already contained the necessary data. And creating a template for every taxonomy term is certainly out of the question. So…

The Solution: A Custom Shortcode

Here’s the shortcode I created to solve this problem:

/**
 * Shortcode: [ncra_ru_sponsor_level_single year="2026"]
 *
 * Shows the sponsor level for the given year attached to the current sponsor.
 * Designed for use within existing H3 blocks.
 * Example output: "2026 Gold Sponsor"
 */
function ncra_ru_sponsor_level_shortcode( $atts ) {
    global $post;
    
    // Check if we're on a sponsor post
    if ( ! $post || $post->post_type !== 'sponsor' ) {
        return '';
    }
    
    // Get shortcode attributes
    $atts = shortcode_atts(
        [
            'year' => date('Y'), // default to current year if not specified
        ],
        $atts,
        'ncra_ru_sponsor_level_single'
    );
    
    $year = sanitize_text_field( $atts['year'] );
    
    // Get all sponsor-level terms for this sponsor
    $terms = get_the_terms( $post->ID, 'sponsor-level' );
    
    if ( empty( $terms ) || is_wp_error( $terms ) ) {
        return '';
    }
    
    // Look for the term whose slug starts with "{year}-"
    foreach ( $terms as $term ) {
        if ( strpos( $term->slug, $year . '-' ) === 0 ) {
            // Extract just the level part (everything after "YEAR-")
            $level_name = substr( $term->name, strlen( $year . '-' ) );
            if ( empty( $level_name ) ) {
                $level_name = $term->name; // fallback to full name if parsing fails
            }
            
            // Return just the text for use within existing H3
            return esc_attr( $year ) . " " . esc_html( $level_name ) . " Sponsor";
        }
    }
    
    return '';
}
add_shortcode( 'ncra_ru_sponsor_level_single', 'ncra_ru_sponsor_level_shortcode' );

How It Works

  1. Context Check: The shortcode first verifies it’s running on a sponsor post type
  2. Parameter Handling: It accepts a year parameter, defaulting to the current year
  3. Taxonomy Query: Uses get_the_terms() to retrieve all sponsor-level terms for the current post
  4. Pattern Matching: Looks for terms whose slug starts with the specified year and a hyphen
  5. Text Extraction: Parses out just the level portion from the term name
  6. Safe Output: Returns sanitized HTML suitable for embedding in existing elements

Implementation in Kadence Blocks

First, using the plugin “Code Snippets”, I added the above function and add_shortcode() to a new snippet, named it “Get Sponsor Level for Single Page”, saved and activated it. (Alternatively I could have added this to the functions.php for my child theme of the Kadence theme, but for my purposes, this is easier.)

Then, I created an h3 block in the Kadence Element “2026 Single Sponsor Template” in the right spot. I created as an H3 block, but edited it as html and added in the shortcode and set it again to edit visually. This avoids using the shortcode template inserter because it’s more difficult to style than an the h3 block. The style “2026_sponsor_level_single” was added in the h3’s advance style field. Yes, the shortcode works. (Probably should have used dashes instead of underscores, but this way, I’ve got a flag that the class is for a shortcode.)

<h3 class="kt-adv-heading321_eec8a2-6c wp-block-kadence-advancedheading" data-kb-block="kb-adv-heading321_eec8a2-6c">
[ncra_ru_sponsor_level_single year="2026"]
</h3>

This approach allowed me to maintain full control over the styling through Kadence’s interface while still getting dynamic content.

Key Benefits

  • No Data Duplication: Leverages existing taxonomy structure instead of creating redundant custom fields
  • Year-Specific: Can display different sponsor levels for different years using the same shortcode with a different year variable in next year’s template.
  • Graceful Degradation: Returns empty string when no matching terms are found, so unassigned sponsors simply don’t display anything
  • Reusable: Can be used across multiple templates and contexts
  • Secure: Properly sanitizes all output to prevent XSS vulnerabilities

Important Notes

  1. Taxonomy Name: Make sure to use the correct taxonomy key. In this case, it was sponsor-level (with hyphen), not sponsor_level (with underscore).
  2. Term Structure: The solution assumes taxonomy terms follow a “YEAR-LEVEL” naming convention.
  3. Shortcode Processing: When embedding in block HTML, WordPress may need explicit shortcode processing depending on your theme and block configuration. If you’re using Kadence theme, this will work.

Alternative Approaches Considered

  • Custom ACF Field: Would work but creates data redundancy that could cause confusing results for someone new stepping into an editor role.
  • Template Part: Less flexible for different contexts and styling needs

The shortcode approach provided the right balance of functionality, maintainability, and integration with existing systems until Kadence WP comes up with an ultimate solution.

It’s a solution that demonstrates how custom shortcodes can bridge the gap between WordPress’s built-in taxonomy system and Kadence WP’s element editor requirements, providing dynamic content without sacrificing design flexibility.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *