diff --git a/domain.field.inc b/domain.field.inc
new file mode 100644
index 0000000..70f54bd
--- /dev/null
+++ b/domain.field.inc
@@ -0,0 +1,166 @@
+<?php
+
+/**
+ * @file
+ * Field integration for the domain module.
+ */
+
+/**
+ * Implements hook_field_info().
+ */
+function domain_field_info() {
+  return array(
+    'domain_reference' => array(
+      'label' => t('Domain reference'),
+      'description' => t('This field stores a reference to a domain.'),
+      'default_widget' => 'options_select',
+      'default_formatter' => 'domain_reference_plain',
+    ),
+  );
+}
+
+/**
+ * Implements hook_field_widget_info_alter().
+ */
+function domain_field_widget_info_alter(&$info) {
+  $info['options_select']['field types'][] = 'domain_reference';
+  $info['options_buttons']['field types'][] = 'domain_reference';
+}
+
+/**
+ * Implements hook_field_is_empty().
+ */
+function domain_field_is_empty($item, $field) {
+  if (!is_array($item) || empty($item['domain'])) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Implements hook_field_validate().
+ */
+function domain_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
+  // Build an array of existing domain machine names.
+  $machine_names = array();
+  foreach ($items as $delta => $item) {
+    if (!empty($item['domain'])) {
+      $machine_names[] = $item['domain'];
+    }
+  }
+
+  if (!empty($machine_names)) {
+    if (array_diff($machine_names, domain_machine_names())) {
+      $errors[$field['field_name']][$langcode][$delta][] = array(
+        'error' => 'domain_reference_illegal_value',
+        'message' => t('%name: illegal value.', array('%name' => $instance['label'])),
+      );
+    }
+  }
+}
+
+/**
+ * Implements hook_options_list().
+ */
+function domain_options_list($field, $instance, $entity_type, $entity) {
+  $function = !empty($field['settings']['options_list_callback']) ? $field['settings']['options_list_callback'] : 'domain_field_allowed_values';
+  return $function($field);
+}
+
+/**
+ * Returns the set of valid domains for a domain reference field.
+ */
+function domain_field_allowed_values($field) {
+  return domain_get_domain_options(array(
+    'key' => 'machine_name', // Domain reference fields need machine names.
+    'sanitize' => FALSE, // Field API takes care of sanitizing list options.
+  ));
+}
+
+/**
+ * Implements hook_field_formatter_info().
+ */
+function domain_field_formatter_info() {
+  return array(
+    'domain_reference_link' => array(
+      'label' => t('Link'),
+      'field types' => array('domain_reference'),
+    ),
+    'domain_reference_plain' => array(
+      'label' => t('Plain text'),
+      'field types' => array('domain_reference'),
+    ),
+  );
+}
+
+/**
+ * Implements hook_field_formatter_prepare_view().
+ */
+function domain_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
+  $machine_names = array();
+
+  // Collect every possible term attached to any of the fieldable entities.
+  foreach ($entities as $id => $entity) {
+    foreach ($items[$id] as $delta => $item) {
+      // Force the array key to prevent duplicates.
+      $machine_names[$item['domain']] = $item['domain'];
+    }
+  }
+
+  if ($machine_names) {
+    $domains = domain_machine_name_load_multiple($machine_names, TRUE);
+
+    // Iterate through the fieldable entities again to attach the loaded domain data.
+    foreach ($entities as $id => $entity) {
+      $rekey = FALSE;
+
+      foreach ($items[$id] as $delta => $item) {
+        // Check whether the domain field instance value could be loaded.
+        if (isset($domains[$item['domain']])) {
+          // Replace the instance value with the domain data.
+          $items[$id][$delta]['domain'] = $domains[$item['domain']];
+        }
+        // Otherwise, unset the instance value, since the domain does not exist.
+        else {
+          unset($items[$id][$delta]);
+          $rekey = TRUE;
+        }
+      }
+
+      if ($rekey) {
+        // Rekey the items array.
+        $items[$id] = array_values($items[$id]);
+      }
+    }
+  }
+}
+
+/**
+ * Implements hook_field_formatter_view().
+ */
+function domain_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
+  $element = array();
+
+  switch ($display['type']) {
+    case 'domain_reference_link':
+      foreach ($items as $delta => $item) {
+        $domain = $item['domain'];
+        $element[$delta] = array(
+          '#type' => 'link',
+          '#title' => $domain['sitename'],
+          '#href' => $domain['path'],
+        );
+      }
+      break;
+
+    case 'domain_reference_plain':
+      foreach ($items as $delta => $item) {
+        $element[$delta] = array(
+          '#markup' => check_plain($item['domain']['sitename']),
+        );
+      }
+      break;
+  }
+
+  return $element;
+}
diff --git a/domain.install b/domain.install
index 893d9c3..1b6fa23 100644
--- a/domain.install
+++ b/domain.install
@@ -77,6 +77,32 @@ function domain_schema() {
 }
 
 /**
+ * Implements hook_field_schema().
+ */
+function domain_field_schema() {
+  $schema = array(
+    'columns' => array(
+      'domain' => array(
+        'type' => 'varchar',
+        'length' => '255',
+        'not null' => TRUE,
+      ),
+    ),
+    'indexes' => array(
+      'domain' => array('domain'),
+    ),
+    'foreign keys' => array(
+      'domain' => array(
+        'table' => 'domain',
+        'columns' => array('domain' => 'domain'),
+      ),
+    ),
+  );
+
+  return $schema;
+}
+
+/**
  * Implements hook_uninstall().
  */
 function domain_uninstall() {
diff --git a/domain.module b/domain.module
index 8ba8466..62ba7aa 100644
--- a/domain.module
+++ b/domain.module
@@ -6,6 +6,9 @@
  * The core Domain Access module.
  */
 
+// @todo Remove when http://drupal.org/node/977052 is fixed.
+require_once dirname(__FILE__) . '/domain.field.inc';
+
 /**
  * @file
  * Core module functions for the Domain Access suite.
@@ -674,13 +677,9 @@ function domain_form_user_form_alter(&$form, &$form_state) {
   }
   if (user_access('assign domain editors')) {
     // Set the form options.
-    $domains = domain_domains();
-    $options = array();
-    foreach ($domains as $domain) {
-      $options[$domain['domain_id']] = check_plain($domain['sitename']);
-    }
     $format = domain_select_format();
-
+    // Checkboxes must be filtered, select lists should not.
+    $options = domain_get_domain_options(array('sanitize' => emtpy($format)));
     $form['domain_user'] = array(
       '#type' => 'fieldset',
       '#title' => t('Domain access'),
@@ -2330,13 +2329,8 @@ function domain_form_alter(&$form, &$form_state, $form_id) {
   $options = array();
   // Get the display format of the form element.
   $format = domain_select_format();
-  foreach (domain_domains() as $data) {
-    // The domain must be valid.
-    if ($data['valid'] || user_access('access inactive domains')) {
-      // Checkboxes must be filtered, select lists should not.
-      $options[$data['domain_id']] = empty($format) ? check_plain($data['sitename']) : $data['sitename'];
-    }
-  }
+  // Checkboxes must be filtered, select lists should not.
+  $options = domain_get_domain_options(array('sanitize' => empty($format)));
   // If the user is a site admin, show the form, otherwise pass it silently.
   if (user_access('set domain access')) {
     $form['domain'] = array(
@@ -2572,13 +2566,8 @@ function domain_form_devel_generate_content_form_alter(&$form, &$form_state) {
   );
   // Get the display format of the form element.
   $format = domain_select_format();
-  foreach (domain_domains() as $data) {
-    // The domain must be valid.
-    if ($data['valid'] || user_access('access inactive domains')) {
-      // Checkboxes must be filtered, select lists should not.
-      $options[$data['domain_id']] = empty($format) ? check_plain($data['sitename']) : $data['sitename'];
-    }
-  }
+  // Checkboxes must be filtered, select lists should not.
+  $options = domain_get_domain_options(array('sanitize' => empty($format)));
   $form['domain']['domains'] = array(
     '#type' => empty($format) ? 'checkboxes' : 'select',
     '#title' => t('Publish to'),
@@ -3460,14 +3449,32 @@ function domain_features_api() {
  *  Boolean indicator to run hook_domain_load() or not.
  *
  * @return
- *  A Domain array or -1 on failure.
+ *  A Domain array or FALSE on failure.
  */
 function domain_machine_name_load($machine_name, $full = FALSE) {
-  $domain = db_query('SELECT domain_id, subdomain, sitename, scheme, valid, weight, is_default, machine_name FROM {domain} WHERE machine_name = :machine_name', array(':machine_name' => $machine_name))->fetchAssoc();
-  if ($full && !empty($domain)) {
-    domain_api($domain, TRUE);
+  $domains = domain_machine_name_load_multiple(array($machine_name));
+  return !empty($domains) ? reset($domains) : FALSE;
+}
+
+/**
+ * Loads multiple domains from their machine names.
+ *
+ * @param array $machine_names
+ *  The machine names of the domain records.
+ * @param $full
+ *  Boolean indicator to run hook_domain_load() or not.
+ *
+ * @return array
+ *  An array of Domain arrays.
+ */
+function domain_machine_name_load_multiple(array $machine_names, $full = FALSE) {
+  $domains = db_query('SELECT domain_id, subdomain, sitename, scheme, valid, weight, is_default, machine_name FROM {domain} WHERE machine_name IN (:machine_names)', array(':machine_names' => $machine_names))->fetchAllAssoc('machine_name', PDO::FETCH_ASSOC);
+  if ($full && !empty($domains)) {
+    foreach ($domains as $key => $domain) {
+      $domains[$key] = domain_api($domain, TRUE);
+    }
   }
-  return $domain;
+  return $domains;
 }
 
 /**
@@ -3918,3 +3925,36 @@ function domain_get_tokens($prefixes = array()) {
   }
   return $tokens;
 }
+
+/**
+ * Provides domains as an array of options that can be used in FAPI #options.
+ *
+ * Note that when this array is used for checkboxes, the array must be run
+ * through $options = array_map($options, 'check_plain') to sanitize the
+ * domain names.
+ */
+function domain_get_domain_options(array $options = array()) {
+  $options += array(
+    'key' => 'domain_id',
+    'value' => 'sitename',
+    'sanitize' => TRUE,
+    'valid' => TRUE,
+  );
+
+  $return = array();
+  foreach (domain_domains() as $domain) {
+    // The domain must be valid.
+    if (!empty($options['valid']) && empty($data['valid']) && !user_access('access inactive domains')) {
+      continue;
+    }
+
+    // Add the domain to the list of available options.
+    $return[$domain[$options['key']]] = $domain[$options['value']];
+  }
+
+  if (!empty($options['sanitize'])) {
+    $return = array_map('check_plain', $return);
+  }
+
+  return $return;
+}
