You could use the 'posts_orderby'
filter:
function custom_loops($query) {
if ( is_post_type_archive('my_post_type') ){
$query->set( 'posts_per_page', 40);
$query->set( 'meta_key', 'custom_meta_sponsored');
$query->set( 'orderby', 'custom_meta_sponsored');
$query->set( 'order', 'DESC');
add_filter( 'posts_orderby', function ( $orderby, $query ) {
if ( $query->get( 'orderby' ) != 'custom_meta_sponsored' ) return $orderby;
global $wpdb;
$orderby = $wpdb->prepare(
'CASE WHEN ' . $wpdb->postmeta . '.meta_value != %s THEN CONCAT(%s, RAND()) ELSE '
. $wpdb->posts . '.post_date END ' . $query->get( 'order' )
, 'X', 'z'
);
return $orderby;
}, 10, 2 );
}
remove_action( 'pre_get_posts', 'custom_loops' );
}
add_action('pre_get_posts', 'custom_loops');