diff --git a/geocoder.admin.inc b/geocoder.admin.inc
index c4ca49b..419cc3a 100644
--- a/geocoder.admin.inc
+++ b/geocoder.admin.inc
@@ -34,6 +34,14 @@ function geocoder_admin_settings($form, &$form_state) {
     '#required' => FALSE,
   );
 
+  $form['geocoder_region_google'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Google region code'),
+    '#description' => t('This regional context helps Google choose the right location. See ') . 'https://developers.google.com/maps/documentation/geocoding/#RegionCodes',
+    '#default_value' => empty($geocoder_settings['geocoder_region_google']) ? '' : $geocoder_settings['geocoder_region_google'],
+    '#required' => FALSE,
+  );
+
   $form['geocoder_google_delay'] = array(
     '#type' => 'textfield',
     '#title' => t('Delay between Google geocoding requests (in milliseconds)'),
@@ -57,5 +65,6 @@ function geocoder_admin_settings_submit($form, &$form_state) {
   $geocoder_settings['geocoder_apikey_yahoo'] = trim($form_state['values']['geocoder_apikey_yahoo']);
   $geocoder_settings['geocoder_apikey_yandex'] = trim($form_state['values']['geocoder_apikey_yandex']);
   $geocoder_settings['geocoder_apikey_bing'] = trim($form_state['values']['geocoder_apikey_bing']);
+  $geocoder_settings['geocoder_region_google'] = trim($form_state['values']['geocoder_region_google']);
   variable_set("geocoder_settings", $geocoder_settings);
 }
diff --git a/plugins/geocoder_handler/google.inc b/plugins/geocoder_handler/google.inc
index ee7a6e1..bfcdae9 100644
--- a/plugins/geocoder_handler/google.inc
+++ b/plugins/geocoder_handler/google.inc
@@ -22,7 +22,7 @@ $plugin = array(
 /**
  * Process Markup
  */
-function geocoder_google($address, $options = array()) {
+function geocoder_google($address, $options = array(), $components = array()) {
   try {
     $delay_trigger = &drupal_static(__FUNCTION__);
     $delay = variable_get('geocoder_google_delay', 0);
@@ -52,6 +52,18 @@ function geocoder_google($address, $options = array()) {
       $query['components'] = $options['biasing']['components'];
     }
 
+    if (!empty($components)) {
+      foreach ($components as $key => $value) {
+        $components[$key] = $key . ':' . $value;
+      }
+      $query['components'] = implode('|', $components);
+    }
+
+    $geocoder_settings = variable_get("geocoder_settings", array());
+    if (isset($geocoder_settings['geocoder_region_google']) && isset($geocoder_settings['geocoder_region_google'])) {
+      $query['region'] = $geocoder_settings['geocoder_region_google'];
+    }
+
     $url = url("http://maps.googleapis.com/maps/api/geocode/json", array('query' => $query));
     $result = drupal_http_request($url);
     $delay_trigger = TRUE;
@@ -148,7 +160,8 @@ function geocoder_google_field($field, $field_item, $options = array()) {
   }
   if ($field['type'] == 'addressfield' && module_exists('addressfield') && !addressfield_field_is_empty($field_item, $field)) {
     $address = geocoder_widget_parse_addressfield($field_item);
-    return geocoder_google($address, $options);
+    $components = geocoder_google_parse_addressfield($field_item);
+    return geocoder_google($address, $options, $components);
   }
   if ($field['type'] == 'location') {
     $address = geocoder_widget_parse_locationfield($field_item);
@@ -224,3 +237,20 @@ function geocoder_google_form($default_values = array()) {
 
   return $form;
 }
+
+function geocoder_google_parse_addressfield($field_item) {
+  $components = array();
+  if (!empty($field_item['locality'])) {
+    $components['locality'] = $field_item['locality'];
+  }
+  if (!empty($field_item['sub_administrative_area'])) {
+    $components['administrative_area'] = $field_item['sub_administrative_area'];
+  }
+  elseif (!empty($field_item['administrative_area'])) {
+    $components['administrative_area'] = $field_item['administrative_area'];
+  }
+  if (!empty($field_item['country'])) {
+    $components['country'] = $field_item['country'];
+  }
+  return $components;
+}
diff --git a/plugins/geocoder_handler/mapquest_nominatim.inc b/plugins/geocoder_handler/mapquest_nominatim.inc
index a1b41c7..dc3fd96 100644
--- a/plugins/geocoder_handler/mapquest_nominatim.inc
+++ b/plugins/geocoder_handler/mapquest_nominatim.inc
@@ -21,18 +21,31 @@ $plugin = array(
 /**
  * Process Markup
  */
-function geocoder_mapquest_nominatim($address, $options = array()) {
+function geocoder_mapquest_nominatim($address, $options = array(), $components = array()) {
   $geocoder_settings = variable_get("geocoder_settings", array());
   $api_url = "http://open.mapquestapi.com/nominatim/v1/search";
-  $params = array(
-    'q' => str_replace(' ', '+', $address),
+  $static_params = array(
     'format' => 'json',
     'addressdetails' => 0,
     'limit' => 1,
     'osm_type' => 'N',
   );
-  $request = drupal_http_request($api_url . '?' . drupal_http_build_query($params));
-  $data = json_decode($request->data);
+  do {
+    if (!empty($components)) {
+      // Use structured request format for better results.
+      // See http://wiki.openstreetmap.org/wiki/Nominatim
+      $params = array_merge($static_params, $components);
+      // Mapquest can fail for an unknown street, even if it knows the city. So
+      // we'll ask again with less details if it fails.
+      array_shift($components);
+    }
+    else {
+      $params = $static_params;
+      $params['q'] = str_replace(' ', '+', $address);
+    }
+    $request = drupal_http_request($api_url . '?' . drupal_http_build_query($params));
+    $data = json_decode($request->data);
+  } while (empty($data) && !empty($components));
   return _geocoder_mapquest_nominatim_geometry($data);
 }
 
@@ -42,7 +55,8 @@ function geocoder_mapquest_nominatim_field($field, $field_item) {
   }
   if ($field['type'] == 'addressfield' && module_exists('addressfield') && !addressfield_field_is_empty($field_item, $field)) {
     $address = geocoder_widget_parse_addressfield($field_item);
-    return geocoder_mapquest_nominatim($address);
+    $components = geocoder_mapquest_nominatim_parse_addressfield($field_item);
+    return geocoder_mapquest_nominatim($address, array(), $components);
   }
   if ($field['type'] == 'location') {
     $address = geocoder_widget_parse_locationfield($field_item);
@@ -61,3 +75,28 @@ function _geocoder_mapquest_nominatim_geometry(&$data) {
   geophp_load();
   return new Point($data[0]->lon, $data[0]->lat);
 }
+
+function geocoder_mapquest_nominatim_parse_addressfield($field_item) {
+  $components = array();
+  // Params order matters. The more precise params first.
+  // See geocoder_mapquest_nominatim().
+  if (!empty($field_item['thoroughfare'])) {
+    $components['street'] = $field_item['thoroughfare'];
+  }
+  if (!empty($field_item['postal_code'])) {
+    $components['postalcode'] = $field_item['postal_code'];
+  }
+  if (!empty($field_item['locality'])) {
+    $components['city'] = $field_item['locality'];
+  }
+  if (!empty($field_item['sub_administrative_area'])) {
+    $components['county'] = $field_item['sub_administrative_area'];
+  }
+  if (!empty($field_item['administrative_area'])) {
+    $components['state'] = $field_item['administrative_area'];
+  }
+  if (!empty($field_item['country'])) {
+    $components['country'] = $field_item['country'];
+  }
+  return $components;
+}
