WP Query – if there are no posts with certain tag query other ones

WP_Query doesn’t have a fallback system in it. It just executes the query with the given parameters.

One option is just to check, if the first query has any posts and if not, then run another query with different parameters.

Another way is to conditionally build up the parameters. So first get the tag term and if it has any posts attached include it in the parameters.

$args = array(
  'post_type' => 'post',
  'posts_per_page' => 3,
  'post__not_in' => get_option( 'sticky_posts' ),
);

$category = get_query_var('cat');
if ( $category && is_int($category) ) {
  $args['cat'] => $category;
}

$popular_tag = get_term_by( 'slug', 'popular', 'post_tag' );
// Does the tag exist and does it have any post attached to it
if ( $popular_tag && $popular_tag->count ) {
  $args['tag_id'] => $popular_tag->term_id;
}

$query = new WP_Query($args);

From WP_Term class reference, https://developer.wordpress.org/reference/classes/wp_term/

Cached object count for this term.