diff --git a/modules/salesforce_mapping/includes/salesforce_mapping.admin.inc b/modules/salesforce_mapping/includes/salesforce_mapping.admin.inc
index 036bb91..ccd4f16 100644
--- a/modules/salesforce_mapping/includes/salesforce_mapping.admin.inc
+++ b/modules/salesforce_mapping/includes/salesforce_mapping.admin.inc
@@ -213,7 +213,19 @@ function salesforce_mapping_form($form, &$form_state, SalesforceMapping $mapping
           '#default_value' => isset($mapping) ? $mapping->field_mappings[$delta]['drupal_field']['fieldmap_value'] : NULL,
         );
         if (!empty($fieldmap_type['options_callback'])) {
-          $fieldmap_value_element['#options'] = call_user_func($fieldmap_type['options_callback'], $form_state['values']['drupal_entity_type']);
+          $entity_type = isset($mapping->drupal_entity_type) ? $mapping->drupal_entity_type : $form_state['values']['drupal_entity_type'];
+          $entity_bundle = isset($mapping->drupal_bundle) ? $mapping->drupal_bundle : $form_state['values']['drupal_bundle'];
+          if (isset($entity_type) && isset($entity_bundle)) {
+            $options_variable_name = 'salesforce_mapping-' . $fieldmap_type_name . '-' . $entity_type . '-' . $entity_bundle;
+            $options = cache_get($options_variable_name);
+            if ($options === FALSE) {
+              $options = call_user_func($fieldmap_type['options_callback'], $entity_type, $entity_bundle);
+              cache_set($options_variable_name, $options);
+            } else {
+              $options = $options->data;
+            }
+            $fieldmap_value_element['#options'] = $options;
+          }
         }
       }
 
diff --git a/modules/salesforce_mapping/includes/salesforce_mapping.fieldmap_type.inc b/modules/salesforce_mapping/includes/salesforce_mapping.fieldmap_type.inc
index 69bee0f..2535059 100644
--- a/modules/salesforce_mapping/includes/salesforce_mapping.fieldmap_type.inc
+++ b/modules/salesforce_mapping/includes/salesforce_mapping.fieldmap_type.inc
@@ -19,6 +19,13 @@ function salesforce_mapping_salesforce_mapping_fieldmap_type() {
       'pull_value_callback' => 'salesforce_mapping_property_fieldmap_pull_value',
       'validation_callback' => 'salesforce_mapping_property_validation',
     ),
+    'reference' => array(
+      'label' => t('References'),
+      'field_type' => 'select',
+      'description' => t('Select a Drupal reference field or property to map to a Salesforce field.'),
+      'options_callback' => 'salesforce_mapping_reference_fieldmap_options',
+      'pull_value_callback' => 'salesforce_mapping_reference_fieldmap_pull_value',
+    ),
     'token' => array(
       'label' => t('Token'),
       'description' => t('Enter a token to map a Salesforce field..'),
@@ -56,45 +63,119 @@ function salesforce_mapping_salesforce_mapping_fieldmap_type() {
 }
 
 /**
- * Return all possible Drupal properties for a given entity type.
+ * Return all possible Drupal properties for a given entity type.  Or if specified only properties for a specific bundle of that entity type.
  *
  * @param $entity_type
- * @param $include_entities
+ * @param $entity_bundle
  *
  * @return array
  */
-function salesforce_mapping_property_fieldmap_options($entity_type, $include_entities = FALSE) {
+function salesforce_mapping_fieldmap_properties($entity_type, $entity_bundle = NULL) {
   $options = array('' => t('-- Select --'));
+  
+  if (isset($entity_bundle)) {
+    $info = entity_get_property_info($entity_type);
+    $properties = $info['properties'] += $info['bundles'][$entity_bundle]['properties'];
+  } else {
+    $properties = entity_get_all_property_info($entity_type);
+  }
+  
+  return $properties;
+}
 
-  $properties = entity_get_all_property_info($entity_type);
+/**
+ * Given an array of entity properties, return them as options.
+ *
+ * @param $properties
+ *
+ * @return array
+ */
+function salesforce_mapping_property_return_options($properties) {  
+  $options = array('' => t('-- Select --'));
+  
   foreach ($properties as $key => $property) {
-    $type = isset($property['type']) ? entity_property_extract_innermost_type($property['type']) : 'text';
-    $is_entity = ($type == 'entity') || (bool) entity_get_info($type);
-    // Leave entities out of this.
-    if (($is_entity && $include_entities) || (!$is_entity && !$include_entities)) {
-      if (isset($property['field']) && $property['field'] && !empty($property['property info'])) {
-        foreach ($property['property info'] as $sub_key => $sub_prop) {
-          $options[$property['label']][$key . ':' . $sub_key] = $sub_prop['label'];
-        }
-      }
-      else {
-        $options[$key] = $property['label'];
+    if (isset($property['field']) && $property['field'] && !empty($property['property info'])) {
+      foreach ($property['property info'] as $sub_key => $sub_prop) {
+        $options[$property['label']][$key . ':' . $sub_key] = $sub_prop['label'];
       }
     }
+    else {
+      $options[$key] = $property['label'];
+    }
   }
 
   return $options;
 }
 
 /**
+ * Check if an entity property is itself an entity.
+ *
+ * @param $property
+ *
+ * @return boolean
+ */
+function salesforce_mapping_property_is_entity($property) {
+  $type = isset($property['type']) ? entity_property_extract_innermost_type($property['type']) : 'text';
+  return ($type == 'entity') || (bool) entity_get_info($type);
+}
+
+/**
+ * Return all possible Drupal properties for a given entity type.
+ *
+ * @param $entity_type
+ * @param $entity_bundle
+ *
+ * @return array
+ */
+function salesforce_mapping_property_fieldmap_options($entity_type, $entity_bundle = NULL) {
+  $properties = salesforce_mapping_fieldmap_properties($entity_type, $entity_bundle);
+  
+  foreach ($properties as $key => $property) {
+    // Leave entities out of this.
+    if (salesforce_mapping_property_is_entity($property)) {
+      unset($properties[$key]);
+    }
+  }
+
+  return salesforce_mapping_property_return_options($properties);
+}
+
+/**
+ * Return all possible Drupal properties of type reference for a given entity type.
+ *
+ * @param $entity_type
+ * @param $entity_bundle
+ *
+ * @return array
+ */
+function salesforce_mapping_reference_fieldmap_options($entity_type, $entity_bundle) {
+  $properties = salesforce_mapping_fieldmap_properties($entity_type, $entity_bundle);
+  
+  foreach ($properties as $key => $property) {
+    if (!salesforce_mapping_property_is_entity($property) || (isset($property["relation_type"]) || $property["computed"]) ) {
+      unset($properties[$key]);
+    }
+  }
+  return salesforce_mapping_property_return_options($properties);
+}
+
+/**
  * Return all possible Drupal properties of type entity for a given entity type.
  *
  * @param $entity_type
+ * @param $entity_bundle
  *
  * @return array
  */
-function salesforce_mapping_related_entity_fieldmap_options($entity_type) {
-  return salesforce_mapping_property_fieldmap_options($entity_type, TRUE);
+function salesforce_mapping_related_entity_fieldmap_options($entity_type, $entity_bundle) {
+  $properties = salesforce_mapping_fieldmap_properties($entity_type, $entity_bundle);
+  
+  foreach ($properties as $key => $property) {
+    if (!isset($property["relation_type"])) {
+      unset($properties[$key]);
+    }
+  }
+  return salesforce_mapping_property_return_options($properties);
 }
 
 /**
@@ -192,8 +273,8 @@ function salesforce_mapping_related_entity_fieldmap_pull_value($entity_wrapper,
  *
  * @return array
  */
-function salesforce_mapping_relation_endpoints_fieldmap_options($entity_type) {
-  $properties = salesforce_mapping_property_fieldmap_options($entity_type);
+function salesforce_mapping_relation_endpoints_fieldmap_options($entity_type, $entity_bundle) {
+  $properties = salesforce_mapping_property_fieldmap_options($entity_type, $entity_bundle);
   if (isset($properties['endpoints'])) {
     return array('endpoints' => $properties['endpoints']);
   }
@@ -343,6 +424,63 @@ function salesforce_mapping_property_validation($drupal_field, $sf_field, $direc
 }
 
 /**
+ * Pull value callback for reference fieldmap type.
+ */
+function salesforce_mapping_reference_fieldmap_pull_value($entity_wrapper, $sf_object, $field_map) {
+  $value = $sf_object[$field_map['salesforce_field']['name']];
+
+  switch ($entity_wrapper->type()) {
+    case 'list<taxonomy_term>':
+      $terms =  explode(';',$value);
+      $bundle = $entity_wrapper->info();
+      $bundle = $bundle["bundle"];
+      $field_info = field_info_instance('taxonomy_term',$field_map['drupal_field']['fieldmap_value'],$bundle);
+      $create = ($field_info['widget']['type'] == 'taxonomy_autocomplete') ? TRUE : FALSE; 
+      foreach ($terms as $key => $name) {
+        $term = salesforce_mapping_reference_fieldmap_get_term($name, $bundle, $create); 
+        if ($term) {
+          $terms[$key] = $term->tid;
+        } else {
+          unset($terms[$key]);
+        }
+      }
+      $value = $terms; 
+      break;
+    case 'taxonomy_term':
+      $bundle = $entity_wrapper->info();
+      $bundle = $bundle["bundle"];
+      $term = salesforce_mapping_reference_fieldmap_get_term($value, $bundle); 
+      if ($term) {
+        $value = $term->tid;
+      }
+      break;
+  }
+
+  return $value;
+}
+
+/**
+ * Helper function for salesforce_mapping_reference_fieldmap_pull_value.
+ */
+function salesforce_mapping_reference_fieldmap_get_term($name, $bundle, $create = FALSE) {
+  if (empty($name)) {
+    return FALSE; //No empty terms please
+  }
+  $matches = taxonomy_get_term_by_name($name, $bundle); 
+  if (empty($matches) && !$create) {
+    return FALSE; 
+  } else if (empty($matches) && $create) {
+    $term = new stdClass();
+    $term->name = $name;
+    $term->vid = db_query("SELECT vid FROM {taxonomy_vocabulary} WHERE machine_name = '$bundle'")->fetchField();
+    taxonomy_term_save($term);
+  } else {
+    $term = array_pop($matches);
+  }
+  return $term;
+}
+
+/**
  * Value callback for token fieldmap type.
  *
  * @param $fieldmap
