Shortcodes should return a string, not echo data… so you have one of two options here:
- Change all echo statements and all functions that ‘echo’ content to use with return (concatenate all on a string, then return it)
- Use output buffering
For output buffering, your code would end up like:
function upcoming_events_shortcode() {
$args = array( 'post_type' => 'upcoming_event', 'posts_per_page' => 3 );
$query = new WP_Query( $args );
ob_start();
while ( $query->have_posts() ) : $query->the_post();
echo '<div class="upcomingevents">';
echo '<h4>';
the_title();
echo '</h4>';
echo '<div class="upcomingeventimage">';
the_post_thumbnail('medium');
echo '</div>';
echo '<div class="upcoming-event-entry-content">';
the_content();
echo '</div>';
echo '</div>';
endwhile;
wp_reset_postdata();
return ob_get_clean();
}
That way, all the echo’ed content will be captured by the output buffer.