How do I Use Nested Loops of Custom Post Types for MultiSite Blogs using WP_Query()

This Plugin gives you a list of posts for each Site already, but it does not exactly do what you want to do.

Basically, it gives you a list of all posts in your network. What you need to do afterwards is sort them by site_id and create an output for that.

I do not know if this is the best version – but as WP_Query returns an one-dimensional array, you need something else to group and sort it by site_id

$args_outer = array(
    'multisite' => 1,
    'sites__not_in' => array(1),
    'post_type' => 'my_cpt',
    'numberposts' => -1,
    'posts_per_page' => -1
);
$child_site_query = new WP_Query_Multisite( $args_outer );

while($child_site_query->have_posts()) : $child_site_query->the_post();
    global $blog_id, $post;
    $blogs[$blog_id][] = $post; // create array with first parameter blogid, and the posts inside
    // --------------------------------------------------
endwhile;  // END: Outer Loop
wp_reset_postdata();     

// loop through all blogs
foreach( $blogs as $thisblog => $posts ) {
    // switch to this blog and create output
    switch_to_blog( $thisblog );
    echo 'Site ' . $thisblog . '<br /><ul>';
    // loop through all posts on this blog
    foreach( $posts as $thispost ) {
        echo '<li><a href="' . get_permalink( $thispost->ID ) . '">' . $thispost->post_title . '</a></li>';
    }
    echo '</ul>';
}
restore_current_blog();