How to filter archives both by category and tag?

What you are looking for is a custom search that can be created via rewrite rules. What I’m gonna do is to create a rule that adds some queries to the URL.

First, let’s define a rewrite tag so that WordPress recognizes our custom URL.

function my_rewrite_tag() {
  add_rewrite_tag('%custom-categories%', '([^&]+)');
}
add_action('init', 'my_rewrite_tag', 10, 0);

Now, we create a rule to redirect our data to another path.

function my_rewrite_rule() {
  add_rewrite_rule(
      '^custom-categories/([^/]*)/([^/]*)/([^/]*)/([^/]*)/?',
      'index.php?post_type=post&customCat=$matches[1]&customSubCat=$matches[2]&customTag1=$matches[3]&customTag2=$matches[4]',
      'top'
  );
}
add_action('init', 'my_rewrite_rule', 10, 0);

So if we try and access:

http://example.com/custom-categories/cat1/subcat1/tag/tag1

we will actually be redirected to:

http://example.com/index.php?post_type=post&customCat=cat1&customSubCat=subcat1&customTag1=tag&customTag2=tag1

Which is the archive for normal post types. Now is the trick. We will alter the query if these data are set:

// We only want to do this if every data is set, so let's check for them all
if(isset($_['customCat']) && isset($_['customSubCat']) && isset($_['customTag1']) && isset($_['customTag2'])) {
    // Now alter the main query
    function photogram_include_blog_posts($query) {
        if ( !is_admin() && $query->is_main_query() && $query->is_archive() ) {
            // Set the tags
            $query->set('tag__in', array($_['customTag1'],$_['customTag2']));
            // Set the categories
            $query->set('category__in', array($_['customSubCat'],$_['customCat']));
        }
    }
    add_action( 'pre_get_posts', 'photogram_include_blog_posts' );
}

So we are redirected to an archive page that runs our custom query. Done.