diff --git a/google_appliance.module b/google_appliance.module
index e56c12f..3264d0a 100644
--- a/google_appliance.module
+++ b/google_appliance.module
@@ -426,6 +426,17 @@ function google_appliance_parse_device_response_xml($gsa_xml) {
       return $results;
     }
     else {  // parse results
+      
+      foreach ($payload->xpath('//GM') as $km) {
+        $keymatch = array();
+        
+        // keymatch information
+        $keymatch['description'] = (string) $km->GD;
+        $keymatch['url'] = (string) $km->GL;
+
+        $results['keymatch'][] = $keymatch;
+      }
+
       foreach ($payload->xpath('//R') as $res) {
         $result = array();
         
diff --git a/theme/google-appliance-keymatch.tpl.php b/theme/google-appliance-keymatch.tpl.php
new file mode 100644
index 0000000..8aa7fb5
--- /dev/null
+++ b/theme/google-appliance-keymatch.tpl.php
@@ -0,0 +1,20 @@
+<?php
+// $Id$
+/**
+ * @file 
+ *    default theme implementation for displaying a single keymatch
+ *
+ * This template renders a single keymatch result and is collected into
+ * google-applinace-results.tpl.php. This and the parent template are
+ * dependent on one another sharing the markup for keymatch listings.
+ *
+ * @see template_preprocess_google_appliance_keymatch()
+ * @see google-appliance-results.tpl.php
+ */
+?>
+<li class="keymatch <?php print $classes; ?>" id="keymatch-<?php print $keymatch_idx; ?>"<?php print $attributes; ?>>
+  <h3 class="keymatch-description"><a href="<?php print render($url); ?>"><?php print render($description); ?></a></h3>
+  <div class="google-appliance-snippet-info">
+    <p class="google-appliance-info"><?php print render($url); ?></p>
+  </div>
+</li>
diff --git a/theme/google-appliance-result.tpl.php b/theme/google-appliance-result.tpl.php
index ab91adb..8a2c97c 100644
--- a/theme/google-appliance-result.tpl.php
+++ b/theme/google-appliance-result.tpl.php
@@ -3,7 +3,7 @@
 /**
  * @file 
  *    default theme implementation for displaying a single search result.
- 
+ *
  * This template renders a single search result and is collected into
  * google-applinace-results.tpl.php. This and the parent template are
  * dependent on one another sharing the markup for results listings.
diff --git a/theme/google-appliance-results.tpl.php b/theme/google-appliance-results.tpl.php
index d8e2ada..2a006fe 100644
--- a/theme/google-appliance-results.tpl.php
+++ b/theme/google-appliance-results.tpl.php
@@ -23,6 +23,10 @@
     <?php print $sort_headers; ?>
   </div>
   
+  <ol class="keymatch-results google-appliance-keymatch-results">
+    <?php print $keymatch_results; ?>
+  </ol>
+
   <ol class="search-results google-appliance-results">
     <?php print $search_results; ?>
   </ol>
diff --git a/theme/google_appliance.css b/theme/google_appliance.css
index 57e7806..afb8094 100644
--- a/theme/google_appliance.css
+++ b/theme/google_appliance.css
@@ -8,8 +8,9 @@
   margin-top: 0;
   margin-bottom: 4px;
 }
-.google-appliance-results {
-  list-style: none;
+.google-appliance-results,
+.google-appliance-keymatch-results {
+  list-style: none;  
 }
 
 /* result entries */
@@ -25,11 +26,32 @@
 .google-appliance-results .google-appliance-snippet-info {
   padding-left:0; 
 }
-.google-appliance-results .google-appliance-info {
+.google-appliance-results .google-appliance-info,
+.google-appliance-keymatch-results {
   font-size: 0.85em;
   color: #aaa;
 }
 
+/* key match results */
+.google-appliance-keymatch-results {
+	padding-left:0;
+}
+.google-appliance-keymatch-results li {
+	background:#f1f1ed;
+	border-bottom:1px solid #e7e7e3;
+	padding:10px 10px;
+	border-radius: 6px;
+  -webkit-border-radius:6px;
+  -moz-border-radius:6px;
+  margin-bottom:10px;
+}
+.google-appliance-keymatch-results h3 {
+	margin: 0;
+}
+.google-appliance-keymatch-results p {
+	margin:0;
+}
+
 /* results listings "control" bar */
 .google-appliance-results-control-bar {
   border: 1px solid #ddd;
diff --git a/theme/google_appliance.theme.inc b/theme/google_appliance.theme.inc
index e287c86..3902e8a 100644
--- a/theme/google_appliance.theme.inc
+++ b/theme/google_appliance.theme.inc
@@ -13,7 +13,7 @@ function google_appliance_theme() {
   $registry = array();
   $ga_template_dir = drupal_get_path('module', 'google_appliance') . '/theme';
   
-  // full search form on results pages
+  // Full search form on results pages.
   $registry['google_appliance_search_form'] = array(
     'arguments' => array('form' => NULL),
     'render element' => 'form',
@@ -21,40 +21,47 @@ function google_appliance_theme() {
     'path' => $ga_template_dir,
   );
   
-  // block search form
+  // Block search form.
   $registry['google_appliance_block_form'] = array(
     'render element' => 'form',
     'template' => 'google-appliance-block-form',
     'path' => $ga_template_dir,
   );
   
-  // results page (top level template for the rest)
+  // Results page (top level template for the rest).
   $registry['google_appliance_results'] = array(
     'variables' => array('search_query_data' => NULL, 'response_data' => NULL),
     'template' => 'google-appliance-results',
     'path' => $ga_template_dir,
   );
   
-  // single result within the results page
+  // Single result within the results page.
   $registry['google_appliance_result'] = array(
     'variables' => array('result_data' => NULL),
     'template' => 'google-appliance-result',
     'path' => $ga_template_dir,
   );
+
+  // Single keymatch within the results page.
+  $registry['google_appliance_keymatch'] = array(
+    'variables' => array('keymatch_data' => NULL),
+    'template' => 'google-appliance-keymatch',
+    'path' => $ga_template_dir,
+  );
   
-  // pager
+  // Pager.
   $registry['google_appliance_pager'] = array(
     'varaibles' => array('pager_data' => NULL),
   );
   
-  // sort headers
+  // Sort headers.
   $registry['google_appliance_sort_headers'] = array(
     'variables' => array('sort_header_data' => NULL),
     'template' => 'google-appliance-sort-headers',
     'path' => $ga_template_dir,
   );
   
-  // search stats
+  // Search stats.
   $registry['google_appliance_search_stats'] = array(
     'variables' => array('search_stats_data' => NULL),
     'template' => 'google-appliance-search-stats',
@@ -66,14 +73,14 @@ function google_appliance_theme() {
 
  
 /**
- * preprocess for block search form 
+ * Preprocess block search form 
  */
 function template_preprocess_google_appliance_block_form(&$vars) {
   
   $vars['block_search_form'] = array();
   $hidden = array();
   
-  // vars named after form keys so themers can print each element independently.
+  // Vars named after form keys so themers can print each element independently.
   foreach (element_children($vars['form']) as $key) {
     
     $type = $vars['form'][$key]['#type'];
@@ -85,24 +92,24 @@ function template_preprocess_google_appliance_block_form(&$vars) {
     }
   }
   
-  // no theming value on hidden elements, so collapse them
+  // No theming value on hidden elements, so collapse them.
   $vars['block_search_form']['hidden'] = implode($hidden);
   
-  // collect the whole shebang so the complete form can be rendered with one var
+  // Collect the whole shebang so the complete form can be rendered with one var.
   $vars['block_search_form_complete'] = implode($vars['block_search_form']);
    
-  // render template
+  // Render template.
 }
 
 /**
- * preprocess for the full search form 
+ * Preprocess the full search form. 
  */
 function template_preprocess_google_appliance_search_form(&$vars) {
   
   $vars['search_form'] = array();
   $hidden = array();
   
-  // vars named after form keys so themers can print each element independently.
+  // Vars named after form keys so themers can print each element independently.
   foreach (element_children($vars['form']) as $key) {
     
     $type = $vars['form'][$key]['#type'];
@@ -114,24 +121,24 @@ function template_preprocess_google_appliance_search_form(&$vars) {
     }
   }
   
-  // no theming value on hidden elements, so collapse them
+  // No theming value on hidden elements, so collapse them.
   $vars['search_form']['hidden'] = implode($hidden);
   
-  // collect the whole shebang so the complete form can be rendered with one var
+  // Collect the whole shebang so the complete form can be rendered with one var.
   $vars['search_form_complete'] = implode($vars['search_form']);
   
-  // render template
+  // Render template.
 }
 
 /**
- * preprocess for google-search-appliance-results.tpl.php (results page)
+ * Preprocess google-search-appliance-results.tpl.php (results page).
  */
 function template_preprocess_google_appliance_results(&$vars) {
 
-  // grab module settings
+  // Grab module settings.
   $settings = _google_appliance_get_settings();
   
-  // report debug info to admins if module settings 
+  // Report debug info to admins if module settings.
   if ($vars['is_admin'] && $settings['query_inspection'] == '1') {
     if (isset($vars['search_query_data']['debug_info'])) {
       foreach ($vars['search_query_data']['debug_info'] as $info_slice) {
@@ -140,36 +147,36 @@ function template_preprocess_google_appliance_results(&$vars) {
     }
   }
   
-  // grab the search form
+  // Grab the search form.
   $vars['search_form'] = drupal_get_form(
     'google_appliance_search_form',
     $vars['search_query_data']['gsa_query_params']['q']
   );
   
-  // if we have errors, decode them and skip building results entities
+  // If we have errors, decode them and skip building results entities.
   if (isset($vars['response_data']['error'])) {
     
     $vars['results_heading'] = t('No Results Found');
     $vars['error_reason'] = '';
     $log_message_errors = '';
     
-    // build hook_help-based error messages for display
+    // Build hook_help-based error messages for display.
     foreach ($vars['response_data']['error'] as $error_key => $error_response) {
-      // replace error responses with hook_help messages that exist
-      // if they don't exist, just relay the error response
+      // Replace error responses with hook_help messages that exist,
+      // if they don't exist, just relay the error response.
       $help_message = google_appliance_help(
         'google_appliance#error_' . $error_key, 
         drupal_help_arg()
       );
       $vars['error_reason'] .= ($help_message != '') ? $help_message : $error_response;
       
-      // build error message for the log (ignore 'no results' condition)
+      // Build error message for the log (ignore 'no results' condition).
       if ($error_key != 'gsa_no_results') {
         $log_message_errors .= '{ ' . $error_response . ' } ';
       }
     }
 
-    // report communication errors to the log
+    // Report communication errors to the log.
     if ($log_message_errors != '') {
       _google_appliance_log_search_error(
         $vars['search_query_data']['gsa_query_params']['q'], 
@@ -178,16 +185,24 @@ function template_preprocess_google_appliance_results(&$vars) {
     }
     
   }
-  else {  // build results entities
-    
+  else {
+    // Build results entities.
     $vars['results_heading'] = t('Search Results');
     
-    // get themed sort headers
+    // Get themed sort headers.
     $vars['sort_headers'] = theme(
       'google_appliance_sort_headers', $vars['search_query_data']
     );
     
-    // get themed results listing
+    // Get themed keymatch listing.
+    $vars['keymatch_results'] = '';
+    $count = 0;
+    foreach ($vars['response_data']['keymatch'] as $keymatch) {
+      $keymatch['keymatch_idx'] = ++$count;
+      $vars['keymatch_results'] .= theme('google_appliance_keymatch', $keymatch);
+    }
+
+    // Get themed results listing.
     $vars['search_results'] = '';
     $count = 0;
     foreach ($vars['response_data']['entry'] as $result) {
@@ -195,14 +210,14 @@ function template_preprocess_google_appliance_results(&$vars) {
       $vars['search_results'] .= theme('google_appliance_result', $result);
     }
         
-    // get themed search stats
+    // Get themed search stats.
     $search_stats_data = array(
       'response_data' => $vars['response_data'],
       'search_query_data' => $vars['search_query_data']
     );
     $vars['search_stats'] = theme('google_appliance_search_stats', $search_stats_data);
     
-    // get themed drupal pager
+    // Get themed drupal pager.
     $pager_data = array(
       'total_results_count' => $vars['response_data']['total_results'],
       'last_result_index' => $vars['response_data']['last_result'],
@@ -210,25 +225,25 @@ function template_preprocess_google_appliance_results(&$vars) {
     $vars['pager'] = theme('google_appliance_pager', $pager_data);
   }
   
-  // render template
+  // Render template.
 }
 
 /**
- * preprocess for a single search result
+ * Preprocess a single search result.
  */
 function template_preprocess_google_appliance_result(&$vars) {
 
-  // sanatize urls
+  // Sanatize urls.
   $vars['short_url'] = check_url($vars['short_url']);
   $vars['enc_url'] = check_url($vars['enc_url']);
   $vars['abs_url'] = check_url($vars['abs_url']);
 
-  // sanatize snippet and title ... 
-  // allow boldface through for keywork highlighting
+  // Sanatize snippet and title ... 
+  // Allow boldface through for keywork highlighting.
   $vars['snippet'] = filter_xss($vars['snippet'], array('b', 'strong'));
   $vars['title'] = filter_xss($vars['title'], array('b', 'strong'));
   
-  // sanitize crawl date
+  // Sanitize crawl date.
   $vars['crawl_date'] = check_plain($vars['crawl_date']);
 
   // Add a google-appliance-levelx class if we're sub-levels
@@ -240,55 +255,69 @@ function template_preprocess_google_appliance_result(&$vars) {
 }
 
 /**
- * Set up Drupal pager for pagination of GSA-provided search results
+ * Preprocess a single keymatch.
+ */
+function template_preprocess_google_appliance_keymatch(&$vars) {
+
+  // Sanatize urls.
+  $vars['url'] = check_url($vars['url']);
+  $vars['description'] = filter_xss($vars['description'], array('b', 'string'));
+
+  // Render template.
+}
+
+/**
+ * Set up Drupal pager for pagination of GSA-provided search results.
  *
- * We're not paging druppal-database content in this version, so the core pager is not aware 
- * of the page-able results provided by the GSA ...  we're only requesting one page of the 
- * results at a time, but we get enough stats from that query to fake the pager, and provide 
- * a familiar interface.
+ * We're not paging druppal-database content in this version, so the core
+ * pager is not aware of the page-able results provided by the GSA ...
+ * We're only requesting one page of the results at a time, but we get
+ * enough stats from that query to fake the pager, and provide a familiar
+ * interface.
  */
 function theme_google_appliance_pager(&$vars) {
 
-  // grab module settings
+  // Grab module settings.
   $settings = _google_appliance_get_settings();
   
-  // globals required to manually configure the pager
+  // Globals required to manually configure the pager.
   global $pager_page_array, $pager_total, $pager_total_items;
   
   $control_tags = array();  // default labels
   $element = 0;             
   $limit = $settings['results_per_page'];  
   
-  // total # of pages in list
+  // Total # of pages in list.
   $total_pages = ceil($vars['total_results_count'] / $limit);
-  // NOTE: the total results count from teh GSA is unreliable. The docs state 
-  // that it is an *approximation*, but if you click around on enough searches, you'll find that
-  // it's off by a considerable amount ... enough to break the math used to create pager
-  // links. It's not all that noticeable unless you click on the "last" link in the pager, and
-  // notice that in some searches, the last page is paginated at a number less than was previously
-  // viewable when the first page of results came up on the initial search view.
-  
-  // The problem is rooted in public vs. access-controlled indexing. see...
-  // groups.google.com/group/Google-Search-Appliance-Help/browse_thread/thread/019b77fb3e7950c7
-  // ... access-controled results are counted before we know if we can actually view it. Device
-  // configuration can help.
-  
-  //@TODO: perhaps a better solution is to just query the device for the first X (up to 1000)
-  // results and cache them locally.
-  
-  //
-  // manually configure (fake) the pager
-  //
-  
+  /**
+   * NOTE: the total results count from the GSA is unreliable. The docs
+   * state that it is an *approximation*, but if you click around on
+   * enough searches, you'll find that it's off by a considerable amount -
+   * enough to break the math used to create pager links. It's not all that
+   * noticeable unless you click on the "last" link in the pager, and
+   * notice that in some searches, the last page is paginated at a number
+   * less than was previously viewable when the first page of results came
+   * up on the initial search view.
+   *
+   * The problem is rooted in public vs. access-controlled indexing.
+   * @see groups.google.com/group/Google-Search-Appliance-Help/browse_thread/thread/019b77fb3e7950c7
+   * Access-controled results are counted before we know if we can actually
+   * view it. Device configuration can help.
+   *
+   * @TODO: perhaps a better solution is to just query the device for the
+   * first X (up to 1000) results and cache them locally.
+   */
+
+  // Manually configure (fake) the pager.
   $page = ( isset($_GET['page']) ) ? check_plain($_GET['page']) : 0;
   
-  // convert page id to array
+  // Convert page id to array.
   $pager_page_array = explode(',', $page);
   
-  // set the total results 
+  // Set the total results.
   $pager_total_items[$element] = (int)$vars['total_results_count']; 
   
-  // set the total # of pages 
+  // Set the total # of pages. 
   $pager_total[$element] = ceil($pager_total_items[$element] / $limit);  
   $pager_page_array[$element] = max(0, min((int)$pager_page_array[$element], ((int)$pager_total[$element]) - 1));
   
@@ -296,11 +325,11 @@ function theme_google_appliance_pager(&$vars) {
 }
 
 /** 
- * preprocess for google-appliance-sort-headers.tpl.php
+ * Preprocess google-appliance-sort-headers.tpl.php.
  */
 function template_preprocess_google_appliance_sort_headers(&$vars) {
 
-  // possible sort options
+  // Possible sort options.
   $vars['sort_options'] = array(
     array(  // default sort
       'sort' => 'rel',
@@ -321,7 +350,7 @@ function template_preprocess_google_appliance_sort_headers(&$vars) {
     */
   );
   
-  // figure out which page we are on
+  // Figure out which page we are on.
   $cur_page = 0;
   if (isset($_GET['page']) ) {
     $cur_page = check_plain($_GET['page']);
@@ -333,42 +362,44 @@ function template_preprocess_google_appliance_sort_headers(&$vars) {
   $sort_found = FALSE;
   foreach ($vars['sort_options'] as $sort_opt ) {
     
-    // if we haven't yet found the current sort, look for params again
+    // If we haven't yet found the current sort, look for params again.
     $sort_is_current = FALSE;
     $sort_param = $vars['gsa_query_params']['sort'];
-    // was a sort requested in the query?
-    if ( (!$sort_found) && ($sort_param != '') ) {
+    // Was a sort requested in the query?
+    if ((!$sort_found) && ($sort_param != '')) {
       
-      // is the sort param one of the valid ones?
-      if ( ($sort_param == $sort_opt['gsa_key']) ) {
+      // Is the sort param one of the valid ones?
+      if (($sort_param == $sort_opt['gsa_key'])) {
         $sort_is_current = TRUE;
         $sort_found = TRUE;
       } 
     } 
-    elseif ( (!$sort_found) && ($sort_param == '') ) { // we had no sort parameters
-      if ($sort_opt['sort'] == 'rel') { // and we are looking at the default sort
+    elseif ((!$sort_found) && ($sort_param == '')) {
+      // We had no sort parameters.
+      if ($sort_opt['sort'] == 'rel') {
+        // And we are looking at the default sort.
         $sort_is_current = TRUE;
         $sort_found = TRUE;
       }
     }
     
-    // if we are on the current sort, then we just create non-linked text
-    // for the sort label
+    // If we are on the current sort, then we just create non-linked text
+    // for the sort label.
     $sorter_display_content = '';
     if ($sort_is_current) {
       $vars['sorters'][$sort_idx]['display'] = '<span class="active-sort">' . $sort_opt['label'] . '</span>';
     }
     else {
-      // we're not on the current sort, so create a link
+      // We're not on the current sort, so create a link.
       $link_attributes = array();
       $link_attributes['query'] = array(
         'page' => $cur_page,
       );
             
-      // append the query to the base url of the serach page
+      // Append the query to the base url of the serach page.
       $link_path = 'gsearch/' . $vars['gsa_query_params']['q'];
       
-      // append the sort param if any
+      // Append the sort param if any.
       $link_path .= '/' . $sort_opt['sort'];
       
       $vars['sorters'][$sort_idx]['display'] = l($sort_opt['label'], $link_path, $link_attributes);
@@ -376,11 +407,11 @@ function template_preprocess_google_appliance_sort_headers(&$vars) {
     $sort_idx++;
   }
   
-  // render template
+  // Render template.
 }
 
 /**
- * preprocess for google-appliance-search-stats.tpl.php
+ * Preprocess google-appliance-search-stats.tpl.php.
  */
 function template_preprocess_google_appliance_search_stats(&$vars) {
   
@@ -389,9 +420,9 @@ function template_preprocess_google_appliance_search_stats(&$vars) {
     '@last' => $vars['response_data']['last_result'],
     '%query' => urldecode($vars['search_query_data']['gsa_query_params']['urlencoded_q']),
     '@total' => $vars['response_data']['total_results'],
-    // the total results reported by the GSA is unreliable, display at your own risk
+    // The total results reported by the GSA is unreliable, display at your own risk
     // @see: theme_google_appliance_pager 
   );
-  
+
   // render
 }
