Only ask for a shipping address if a real product is ordered
you could use hook_commerce_checkout_pane_info_alter and do 

unset($checkout_pane['customer_profile_shipping']);

only if all line_items contains physical products:

function mymodule_commerce_checkout_pane_info_alter(&amp;$checkout_pane) {
  global $user;

  foreach ($checkout_pane as $pane_name =&gt; &amp; $pane_data) {
    if ($pane_name == 'customer_profile_shipping') {
      $order = commerce_cart_order_load($user-&gt;uid);
     if ($order) {
       $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
       $lines = $order_wrapper-&gt;commerce_line_items-&gt;value();

       $ask_shipping = FALSE;
       foreach ($lines as $line) {
         if ($line-&gt;type == 'product') {
           $line_wrapper = entity_metadata_wrapper('commerce_line_item', $line);
           $product = $line_wrapper-&gt;commerce_product-&gt;value();
           if ($product-&gt;type == '---&gt; you physical product type &lt;---') {
             $ask_shipping = TRUE;
           }
         }
       }

       if (!$ask_shipping) {
         unset($checkout_pane['customer_profile_shipping']);
       }
     }
   }
 }
}