Create multiple rewrite endpoints for custom taxonomy archive

This code above works fine up to one endpoint but not working for multiple endpoints like following

https://example.com/dogs/shop/prod-cat1
https://example.com/dogs/shop/prod-cat2
https://example.com/cats/shop/prod-cat1
https://example.com/cats/shop/prod-cat2

Uses template shop-cat.php & value of query variable i.e prod-cat1, prod-cat2 available on template

Your request hook callback is always setting the query var to true, like so (for the shop var):

if (isset($vars['shop'])) {
    $vars['shop'] = true;
}

So instead of doing that, you can use this which sets the var to true only if it is empty(-ish):

if (isset($vars['shop']) && ! $vars['shop']) {
    $vars['shop'] = true;
}

So with that, at example.com/dogs/shop/, get_query_var( 'shop' ) would return true, whereas at example.com/dogs/shop/prod-cat1, you’d get prod-cat1.

And then now you could just use your own conditional to load different templates based on the query var value.

For example, in your template_include hook callback, replace the $end_template = ...; part with:

$filename = ( true === get_query_var( 'shop' ) ) ?
    // shop-cat.php is used if a custom value like prod-cat1 is set (in the URL)
    'shop.php' : 'shop-cat.php';

$end_template = plugin_dir_path( __FILE__ ) . "templates/$filename";

Just copy that and the above if for the other vars (sales and services), and replace shop with the correct var.

Alternate solution without having to modify the query var value.

  1. Remove the add_filter('request', function($vars) { ... }); from your code.

  2. Replace your entire template_include code with:

    add_filter( 'template_include', function ( $template ) {
        // Do nothing if we're not on a 'species' taxonomy/term archive page.
        if ( ! is_tax( 'species' ) ) {
            return $template;
        }
    
        // I used a `foreach` instead of 3 "if" blocks with identical code.
        foreach ( array( 'shop', 'sales', 'services' ) as $var ) {
            if ( isset( $GLOBALS['wp']->query_vars[ $var ] ) ) {
                // <var>-cat.php is used if a custom value like prod-cat1 is set (in the URL)
                $filename = get_query_var( $var ) ? "$var-cat.php" : "$var.php";
    
                return plugin_dir_path( __FILE__ ) . "templates/$filename";
            }
        }
    
        return $template;
    } );
    

So in the above code, if $GLOBALS['wp']->query_vars[ $var ] is set, then we change the template.