diff --git a/ccl.admin.inc b/ccl.admin.inc
index 08fb531..eb42ae1 100644
--- a/ccl.admin.inc
+++ b/ccl.admin.inc
@@ -119,6 +119,19 @@ function ccl_add_form($form, &$form_state, $clid = 0) {
     '#required' => TRUE,
   );
 
+  $form['link_group']['ccl_name'] = array(
+    '#type' => 'machine_name',
+    '#title' => t('Machine name'),
+    '#default_value' => $clid ? $link->name : '',
+    '#machine_name' => array(
+      'source' => array('link_group', 'ccl_title'),
+      'exists' => 'ccl_system_name_exists',
+    ),
+    '#disabled' => $clid ? TRUE : FALSE,
+    '#required' => TRUE,
+    '#maxlength' => 64,
+  );
+
   $form['link_group']['ccl_link'] = array(
     '#type' => 'textfield',
     '#title' => t('URL'),
@@ -265,6 +278,7 @@ function ccl_add_form_submit($form, &$form_state) {
 
   $record = array(
     'type' => $values['ccl_type'],
+    'name' => $values['ccl_name'],
     'title' => $values['ccl_title'],
     'link' => $values['ccl_link'],
     'options' => serialize($options)
diff --git a/ccl.features.inc b/ccl.features.inc
index e69de29..2727184 100644
--- a/ccl.features.inc
+++ b/ccl.features.inc
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * @file
+ *
+ * Integrates Features for Custom Contextual Links.
+ **/
+
+/**
+ * Implements hook_features_export_options. [component_hook]
+ */
+function ccl_features_export_options() {
+  foreach (ccl_get_presets() as $preset) {
+    $presets[$preset->name] = $preset->title;
+  }
+  return $presets;
+}
+
+/**
+ * Implements hook_features_export [component hook]
+ */
+function ccl_features_export($data, &$export, $module_name = '') {
+  $export['dependencies']['features'] = 'features';
+  $export['dependencies']['ccl'] = 'ccl';
+
+  foreach (ccl_get_presets() as $preset) {
+    if (in_array($preset->name, $data)) {
+
+      // Make the submodule required.
+      if ($preset->type != 'node') {
+        $export['dependencies']['ccl_' . $preset->type] = 'ccl_' . $preset->type;
+      }
+
+      $export['features']['ccl'][$preset->name] = $preset->name;
+    }
+  }
+
+  return $export;
+}
+
+/**
+ * Implements hook_features_export_render. [component hook]
+ */
+function ccl_features_export_render($module, $data) {
+  $code = array();
+  $presets = ccl_get_presets();
+
+  foreach ($data as $name) {
+    foreach ($presets as $preset) {
+      if ($preset->name == $name) {
+        $preset = clone $preset;
+        unset($preset->clid);
+        $code[$name] = $preset;
+      }
+    }
+  }
+  $code = "  return " . features_var_export($code, '  ') . ";";
+  return array('ccl_features_preset' => $code);
+}
+
+/**
+ * Implements hook_features_revert().
+ */
+function ccl_features_revert($module) {
+  ccl_features_rebuild($module);
+}
+
+/**
+ * Implements hook_features_rebuild().
+ *
+ * Rebuilds Custom Contextual Links from code defaults.
+ */
+function ccl_features_rebuild($module) {
+  $presets = module_invoke($module, 'ccl_features_preset');
+  foreach ($presets as $key => $preset) {
+    $preset = (object) $preset;
+
+    $current_record = current(ccl_get_presets($preset->name));
+    if (!empty($current_record)) {
+      $preset->clid = $current_record->clid;
+      drupal_write_record('ccl', $preset, 'clid');
+    }
+    else {
+      drupal_write_record('ccl', $preset);
+    }
+  }
+}
diff --git a/ccl.install b/ccl.install
index 6c9d594..6e4cc81 100644
--- a/ccl.install
+++ b/ccl.install
@@ -17,6 +17,12 @@ function ccl_schema() {
         'unsigned' => TRUE,
         'not null' => TRUE
       ),
+      'name' => array(
+        'description' => 'The machine name for a link.',
+        'type' => 'varchar',
+        'length' => 64,
+        'not null' => TRUE,
+      ),
       'type' => array(
         'description' => 'The type the link will target.',
         'type' => 'varchar',
@@ -46,6 +52,9 @@ function ccl_schema() {
       ),
     ),
     'primary key' => array('clid'),
+    'unique keys' => array(
+      'name' => array('name'),
+    ),
   );
   return $schema;
 }
@@ -124,3 +133,35 @@ function ccl_update_7102() {
 
   module_enable(array('ccl_blocks'));
 }
+
+/**
+ * Add a 'name' column to the Custom Contextual Links table.
+ */
+function ccl_update_7103() {
+
+  // Create a 'name' column.
+  db_add_field('ccl', 'name', array(
+    'description' => 'The machine name for a link.',
+    'type' => 'varchar',
+    'length' => 64,
+    'not null' => TRUE,
+    'default' => '',
+  ));
+
+  // Select the current links set defaults for the name column.
+  $result = db_select('ccl', 'ccl')
+    ->fields('ccl', array('clid'))
+    ->execute()
+    ->fetchAll();
+
+  foreach ($result as $row) {
+    $result = db_update('ccl')
+      ->fields(array('name' => 'link_' . $row->clid))
+      ->condition('clid', $row->clid, '=')
+      ->execute();
+  }
+
+  // The machine_name unique key can only be added after we ensure the
+  // name column contains unique values.
+  db_add_unique_key('ccl', 'name', array('name'));
+}
diff --git a/ccl.module b/ccl.module
index dd64c76..c1ab771 100644
--- a/ccl.module
+++ b/ccl.module
@@ -59,6 +59,46 @@ function ccl_menu() {
   return $items;
 }
 
+/**
+ * Helper function for the machine_name field in the admin form.
+ * It checks whether the 'name' field is already used.
+ */
+function ccl_system_name_exists($name) {
+  if (sizeof(ccl_get_presets($name)) > 0) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Implements hook_features_api().
+ */
+function ccl_features_api() {
+  return array(
+    'ccl' => array(
+      'name' => 'Custom Contextual Links',
+      'file' => drupal_get_path('module', 'ccl') . '/ccl.features.inc',
+      'default_hook' => 'ccl_features_preset',
+      'feature_source' => TRUE,
+    ),
+  );
+}
+
+function ccl_get_presets($name = NULL) {
+  $presets = array();
+  if ($name) {
+    $results = db_query('SELECT * FROM {ccl} WHERE name = :name;', array(':name' => $name));
+  }
+  else {
+    $results = db_query('SELECT * FROM {ccl};');
+  }
+
+  while ($result = $results->fetchObject()) {
+    $presets[] = $result;
+  }
+  return $presets;
+}
+
 /*
  * Implements hook_contextual_links_view_alter().
  *
