Ok, I found a solution.
There's this plugin that adds support for orderby by post__in.
I've just tweaked it a bit and added support for orderby post_type
Add this code to your functions.php file
function tc_tag_for_cpt($query) {
if(is_tag() && empty( $query->query_vars['suppress_filters'] ) && !is_admin()) {
$post_type = get_query_var('post_type');
$post_type = ($post_type) ? $post_type : array('services','post','news'); //,'nav_menu_item'
$query->set('post_type',$post_type);
return $query;
}
}
add_filter( 'posts_orderby', 'sort_query_by_post_type', 10, 2 );
function sort_query_by_post_type( $sortby, $thequery ) {
if(is_tag() && empty( $query->query_vars['suppress_filters'] ) && !is_admin()) {
$thequery->set('orderby','post_type');
if ( !empty($thequery->query_vars['post_type']) && isset($thequery->query_vars['orderby']) && $thequery->query_vars['orderby'] == 'post_type' )
$sortby = "find_in_set(post_type, '" . implode( ',', $thequery->query_vars['post_type'] ) . "')";
}
return $sortby;
}
In the first function you will find this -
array('services','post','news')
Pass there the post_types you want by the order you want (i.e. - post, page, any_cpt)
My function will do this only on tag pages, but you can change the is_tag functions to is_archive if you want this on all archive type.
Hope you'll enjoy this :)