Try this

    function get_products($atts) {
      return ob_get_clean();
    add_shortcode('products', 'get_products');

Little explanation

php just outputs your content right away when its see print statement. What we do here is, we are holding all the output in buffer and not giving it in print until the whole things finish.

then we are returning the final whole results(outputs). This gives control on our side to when and where to print outputs.

You can even assign it to in `variable` and return them when needed

      $output =  ob_get_clean();
      //now you can return the output whenever you want with $output