Custom post type archive with rand and meta_value

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');