You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress分类自定义URL结构配置及Yoast SEO站点地图子分类重定向需求

Solution for Custom Category URLs & Redirects with Yoast SEO

Got it, let's break this down step by step. You want to swap WordPress's default nested category URLs (like /category/cat1/cat2/cat3/) for a flat structure with query params (/category/cat1/?l2cat=cat2&l3cat=cat3), redirect any existing nested URLs to this new format, and make sure Yoast SEO's sitemap uses the updated URLs too. Here's how to implement this:

1. Generate Custom Category URLs

First, we'll hook into WordPress's term_link filter to override the default category URL generation. This will create the flat URL with query parameters for child categories.

Add this code to your theme's functions.php file (or a custom plugin—safer for avoiding lost changes during theme updates):

add_filter( 'term_link', 'custom_category_permalink', 10, 3 );
function custom_category_permalink( $url, $term, $taxonomy ) {
    // Only target category taxonomy
    if ( $taxonomy !== 'category' ) {
        return $url;
    }

    // Get the top-level parent category
    $top_parent = get_top_level_category( $term->term_id );
    if ( ! $top_parent ) {
        return $url;
    }

    // Build base URL using top-level category
    $base_url = get_term_link( $top_parent, 'category' );
    // Remove trailing slash for clean param appending
    $base_url = untrailingslashit( $base_url );

    // Collect child category slugs (level 2 and 3)
    $child_slugs = array();
    $current_term = $term;
    while ( $current_term->parent !== $top_parent->term_id && $current_term->parent !== 0 ) {
        array_unshift( $child_slugs, $current_term->slug );
        $current_term = get_term( $current_term->parent, 'category' );
    }
    // Add the direct child of top-level if exists
    if ( $current_term->parent === $top_parent->term_id ) {
        array_unshift( $child_slugs, $current_term->slug );
    }

    // Build query params
    $query_params = array();
    if ( isset( $child_slugs[0] ) ) {
        $query_params['l2cat'] = $child_slugs[0];
    }
    if ( isset( $child_slugs[1] ) ) {
        $query_params['l3cat'] = $child_slugs[1];
    }

    // If no child params, return base URL
    if ( empty( $query_params ) ) {
        return $base_url . '/';
    }

    // Combine base URL with query params
    return add_query_arg( $query_params, $base_url ) . '/';
}

// Helper function to get top-level parent category
function get_top_level_category( $term_id ) {
    $term = get_term( $term_id, 'category' );
    if ( ! $term || is_wp_error( $term ) ) {
        return false;
    }

    while ( $term->parent !== 0 ) {
        $term = get_term( $term->parent, 'category' );
        if ( is_wp_error( $term ) ) {
            return false;
        }
    }
    return $term;
}

How this works:

  • The custom_category_permalink function checks if we're dealing with a category, then finds its top-level parent.
  • It collects slugs for level 2 and 3 child categories, then builds the URL with l2cat and l3cat query params.
  • The helper function get_top_level_category traverses up the category hierarchy to find the root parent.

2. Redirect Nested Category URLs to the New Format

Next, we need to redirect any existing nested URLs (like /category/cat1/cat2/cat3/) to the new query param structure. We'll use the template_redirect hook for this:

Add this to your functions.php or custom plugin:

add_action( 'template_redirect', 'redirect_nested_categories' );
function redirect_nested_categories() {
    // Only run on category archive pages
    if ( ! is_category() ) {
        return;
    }

    $current_term = get_queried_object();
    $top_parent = get_top_level_category( $current_term->term_id );
    if ( ! $top_parent || $current_term->term_id === $top_parent->term_id ) {
        // No redirect needed for top-level categories
        return;
    }

    // Build the target URL using our custom permalink function
    $target_url = custom_category_permalink( '', $current_term, 'category' );

    // Check if we're already on the target URL to avoid redirect loops
    if ( untrailingslashit( $_SERVER['REQUEST_URI'] ) === untrailingslashit( parse_url( $target_url, PHP_URL_PATH ) . '?' . parse_url( $target_url, PHP_URL_QUERY ) ) ) {
        return;
    }

    // Perform 301 permanent redirect (preserves SEO value)
    wp_redirect( $target_url, 301 );
    exit;
}

Key notes:

  • This checks if the current page is a category archive, then verifies if it's a child category that needs redirecting.
  • It uses our existing custom_category_permalink function to generate the target URL, ensuring consistency.
  • We use a 301 redirect to preserve SEO value from the old URLs.

3. Update Yoast SEO Sitemap to Use Custom URLs

Yoast SEO generates sitemaps using its own logic, so we need to hook into its sitemap term link filter to make sure it uses our custom URLs instead of the default nested ones:

Add this code snippet:

add_filter( 'wpseo_xml_sitemap_term_link', 'yoast_custom_category_sitemap_link', 10, 2 );
function yoast_custom_category_sitemap_link( $url, $term ) {
    if ( $term->taxonomy === 'category' ) {
        return custom_category_permalink( $url, $term, 'category' );
    }
    return $url;
}

This tells Yoast to use our custom permalink function when generating category links in the sitemap, so your sitemap will show the updated ?l2cat=... URLs instead of nested paths.

Final Checks

  • After adding these snippets, flush your WordPress permalinks (go to Settings > Permalinks and click "Save Changes"—no need to edit anything). This ensures WordPress picks up the new URL structure.
  • Test a few category pages: visit a nested category URL (like /category/cat1/cat2/) and confirm it redirects to /category/cat1/?l2cat=cat2/.
  • Check your Yoast sitemap (usually at /sitemap_index.xml) to verify category links are using the new format.

内容的提问来源于stack exchange,提问作者Luka Juras

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 08:28:11