is_single()
and is_page()
refer to the main query and as far as I know are not altered to match the individual posts in a Loop. They refer to the type of page not to the individual posts. Try and you should see what I mean:
$data = array();
$args = array(
'posts_per_page' => '-1',
'post_type' => array('post', 'page'),
'orderby' => 'menu_order',
'order' => 'ASC',
);
$loop = new WP_Query($args);
if( $loop->have_posts() ):
while( $loop->have_posts() ): $loop->the_post();
$id = $post->ID;
the_title(); var_dump($post->post_type,is_single(),is_page(),$loop->is_single(),$loop->is_page());
echo '<br>';
endwhile;
endif;
wp_reset_postdata();
The simple solution is just to check the post type itself
if('post' == $post->post_type) {
$type="article";
} elseif('page' == $post->post_type) {
$type="page";
}
Also this,
$id = $loop->post->ID;
is overly complicated. $post->ID
is the same value. Or use get_theID()