diff --git a/geocoder.admin.inc b/geocoder.admin.inc
index c4ca49b..a098bc6 100644
--- a/geocoder.admin.inc
+++ b/geocoder.admin.inc
@@ -10,30 +10,42 @@
  */
 function geocoder_admin_settings($form, &$form_state) {
   $geocoder_settings= variable_get("geocoder_settings", array());
+  $yahoo_url = 'http://developer.yahoo.com/geo/placefinder/';
   $form['geocoder_apikey_yahoo'] = array(
     '#type' => 'textfield',
     '#title' => t('Yahoo PlaceFinder API Key'),
-    '#description' => t('You can obtain a Yahoo PlaceFinder consumer key at') . ' ' . 'http://developer.yahoo.com/geo/placefinder/',
+    '#description' => t('You can obtain a Yahoo PlaceFinder consumer key at') . ' ' . l($yahoo_url, $yahoo_url, array('external' => TRUE)),
     '#default_value' => empty($geocoder_settings['geocoder_apikey_yahoo']) ? '' : $geocoder_settings['geocoder_apikey_yahoo'],
     '#required' => FALSE,
   );
 
+  $yandex_url = 'http://api.yandex.ru/maps/getkey.xml';
   $form['geocoder_apikey_yandex'] = array(
     '#type' => 'textfield',
     '#title' => t('Yandex Maps API Key'),
-    '#description' => t('You can obtain a Yandex API Key at ') . 'http://api.yandex.ru/maps/getkey.xml',
+    '#description' => t('You can obtain a Yandex API Key at ') . l($yandex_url, $yandex_url, array('external' => TRUE)),
     '#default_value' => empty($geocoder_settings['geocoder_apikey_yandex']) ? '' : $geocoder_settings['geocoder_apikey_yandex'],
     '#required' => FALSE,
   );
 
+  $bing_url = 'http://msdn.microsoft.com/en-us/library/ff428642.aspx';
   $form['geocoder_apikey_bing'] = array(
     '#type' => 'textfield',
     '#title' => t('Bing API Key'),
-    '#description' => t('You can obtain a Bing API Key at ') . 'http://msdn.microsoft.com/en-us/library/ff428642.aspx',
+    '#description' => t('You can obtain a Bing API Key at ') . l($bing_url, $bing_url, array('external' => TRUE)),
     '#default_value' => empty($geocoder_settings['geocoder_apikey_bing']) ? '' : $geocoder_settings['geocoder_apikey_bing'],
     '#required' => FALSE,
   );
 
+  $google_url = 'https://developers.google.com/maps/documentation/geocoding/#RegionCodes';
+  $form['geocoder_region_google'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Google Region Code'),
+    '#description' => t('This regional context helps Google choose the right location. See ') . l($google_url, $google_url, array('external' => TRUE)),
+    '#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 +69,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..c2cd4dd 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);
@@ -48,6 +48,12 @@ function geocoder_google($address, $options = array()) {
     if (!empty($options['biasing']['region'])) {
       $query['region'] = $options['biasing']['region'];
     }
+    else {
+      $geocoder_settings = variable_get("geocoder_settings", array());
+      if (isset($geocoder_settings['geocoder_region_google'])) {
+        $query['region'] = $geocoder_settings['geocoder_region_google'];
+      }
+    }
     if (!empty($options['biasing']['components'])) {
       $query['components'] = $options['biasing']['components'];
     }
@@ -148,7 +154,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 +231,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;
+}
