diff --git a/css/recurly.css b/css/recurly.css
index 9ba1448..aaff68d 100644
--- a/css/recurly.css
+++ b/css/recurly.css
@@ -96,6 +96,46 @@
   font-size: inherit;
 }
 
+/* Subscription signup */
+.recurly-plan-list {
+  margin: 0 -10px;
+}
+.recurly-plan-list .plan {
+  border: 1px solid #CCC;
+  border-radius: 10px;
+  padding: 10px;
+  margin: 10px;
+  float: left;
+  width: 120px;
+  background-color: white;
+}
+.recurly-plan-list .plan-hover {
+  background-color: #FFFDF2;
+  border-color: #ED5;
+}
+.recurly-plan-list .plan-selected {
+  background-color: #FFFCE5;
+}
+.recurly-plan-list .plan h2 {
+  margin: 0;
+  padding: 0;
+}
+.recurly-plan-list .plan-signup {
+  text-align: center;
+}
+.recurly-plan-list a.plan-select {
+  display: block;
+}
+.recurly-plan-list .plan-selected a.plan-select {
+  font-weight: bold;
+}
+.recurly-plan-list a.plan-select input {
+  display: none;
+}
+#recurly-subscription-change-form .form-actions {
+  text-align: center;
+}
+
 /* Invoice list (user/x/subscription/invoices) */
 table.invoice-list tr.past_due,
 table.invoice-list tr.failed {
diff --git a/includes/recurly.admin.inc b/includes/recurly.admin.inc
index 1db50db..532940a 100644
--- a/includes/recurly.admin.inc
+++ b/includes/recurly.admin.inc
@@ -149,6 +149,22 @@
       ),
     ),
   );
+  $form['pages']['recurly_subscription_change_timeframe'] = array(
+    '#title' => t('Change plan behavior'),
+    '#type' => 'radios',
+    '#options' => array(
+      'now' => t('Change plan immediately (pro-rating billing period usage)'),
+      'renewal' => t('On next renewal'),
+    ),
+    '#description' => t('Affects users who are able to change their own plan (if more than one is enabled). Overriddable when changing plans as users with "Administer Recurly" permission.'),
+    '#enabled' => count($plan_options),
+    '#default_value' => variable_get('recurly_subscription_change_timeframe', 'now'),
+    '#states' => array(
+      'visible' => array(
+        'select[name="recurly_entity_type"]' => array('!value' => ''),
+      ),
+    ),
+  );
 
   $form = system_settings_form($form);
   $form['#submit'][] = 'recurly_settings_form_submit';
diff --git a/includes/recurly.pages.inc b/includes/recurly.pages.inc
index c8c0714..e62bfe7 100644
--- a/includes/recurly.pages.inc
+++ b/includes/recurly.pages.inc
@@ -8,7 +8,7 @@
 /**
  * Menu callback; Display a summary of a Recurly account subscriptions.
  */
-function recurly_subscription_page($entity_type, $entity) {
+function recurly_subscription_list_page($entity_type, $entity) {
   $subscriptions = array();
 
   // Initialize the Recurly client with the site-wide settings.
@@ -16,7 +16,8 @@
     return t('Could not initialize the Recurly client.');
   }
 
-  // See if we have a local mapping of entity ID to Recurly account code.
+  // Load the account information. This should already be cached by the access
+  // check to this page by recurly_subscription_page_access().
   list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
   $account = recurly_account_load(array('entity_type' => $entity_type, 'entity_id' => $id));
 
@@ -40,11 +41,11 @@
 
     // Generate the list of links for this subscription.
     $subscription_links = array();
-    $subscription_links['update'] = array(
-      'href' => $entity_type . '/' . $id . '/subscription/id/' . $subscription->uuid,
-      'title' => t('Change plan'),
-    );
     if ($subscription->state === 'active') {
+      $subscription_links['change'] = array(
+        'href' => $entity_type . '/' . $id . '/subscription/id/' . $subscription->uuid,
+        'title' => t('Change plan'),
+      );
       $subscription_links['cancel'] = array(
         'href' => $entity_type . '/' . $id . '/subscription/id/' . $subscription->uuid . '/cancel',
         'title' => t('Cancel'),
@@ -103,7 +104,7 @@
     '#access' => $subscription_list->count() > $per_page,
   );
 
-  drupal_alter('recurly_subscription_page', $subscriptions);
+  drupal_alter('recurly_subscription_list_page', $subscriptions);
   return $subscriptions;
 }
 
@@ -182,6 +183,210 @@
   return $states;
 }
 
+
+/**
+ * Menu callback; Show a list of available plans to which a user may subscribe.
+ *
+ * This menu callback is used both for new subscriptions and for updating
+ * existing subscriptions.
+ *
+ * @param $entity_type
+ *   The type of the entity whose subscription is being changed.
+ * @param $entity
+ *   The entity whose subscription is being changed.
+ * @param $currency
+ *   If this is a new subscription, the currency to be used.
+ * @param $subscription_id
+ *   The UUID of the current subscription if changing the plan on an existing
+ *   subscription.
+ */
+function recurly_subscription_plan_list($entity_type, $entity, $currency = NULL, $subscription_id = NULL) {
+  // Initialize the Recurly client with the site-wide settings.
+  if (!recurly_client_initialize()) {
+    return t('Could not initialize the Recurly client.');
+  }
+
+  // If loading an existing subscription.
+  if ($subscription_id) {
+    try {
+      $subscription = Recurly_Subscription::get($subscription_id);
+      $currency = $subscription->plan->currency;
+      $mode = 'change';
+    }
+    catch (Recurly_NotFoundError $e) {
+      drupal_set_message(t('Subscription not found'));
+      return MENU_NOT_FOUND;
+    }
+  }
+  else {
+    $subscription = NULL;
+    $currency = isset($currency) ? $currency : variable_get('recurly_default_currency', 'USD');
+    $mode = 'subscribe';
+  }
+
+  $all_plans = recurly_subscription_plans();
+  $enabled_plan_keys = variable_get('recurly_subscription_plans', array());
+  $enabled_plans = array();
+  foreach ($all_plans as $plan) {
+    if (in_array($plan->plan_code, $enabled_plan_keys)) {
+      $enabled_plans[$plan->plan_code] = $plan;
+    }
+  }
+  return theme('recurly_subscription_plan_list', array('plans' => $enabled_plans, 'entity_type' => $entity_type, 'entity' => $entity, 'currency' => $currency, 'mode' => $mode, 'subscription' => $subscription));
+}
+
+/**
+ * Shared preprocess function for the presentation of the signup and change page.
+ */
+function template_preprocess_recurly_subscription_plan_list(&$variables) {
+  $plans = $variables['plans'];
+  $currency = $variables['currency'];
+  $entity_type = $variables['entity_type'];
+  $entity = $variables['entity'];
+  $subscription = $variables['subscription'];
+  $variables['filtered_plans'] = array();
+  foreach ($plans as $plan_code => $plan) {
+    $setup_fee_amount = NULL;
+    foreach ($plan->setup_fee_in_cents as $setup_currency) {
+      if ($setup_currency->currencyCode === $currency) {
+        $setup_fee_amount = recurly_format_currency($setup_currency->amount_in_cents, $setup_currency->currencyCode, TRUE);
+        break;
+      }
+    }
+    $unit_amount = NULL;
+    foreach ($plan->unit_amount_in_cents as $unit_currency) {
+      if ($unit_currency->currencyCode === $currency) {
+        $unit_amount = recurly_format_currency($unit_currency->amount_in_cents, $unit_currency->currencyCode, TRUE);
+        break;
+      }
+    }
+    list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+    $variables['filtered_plans'][$plan_code] = array(
+      'plan_code' => check_plain($plan_code),
+      'name' => check_plain($plan->name),
+      'description' => check_plain($plan->description),
+      'setup_fee' => $setup_fee_amount,
+      'amount' => $unit_amount,
+      'plan_interval' => recurly_format_price_interval($unit_amount, $plan->plan_interval_length, $plan->plan_interval_unit, TRUE),
+      'trial_interval' => $plan->trial_interval_length ? recurly_format_price_interval(NULL, $plan->trial_interval_length, $plan->trial_interval_unit, TRUE) : NULL,
+      'signup_url' => recurly_url('subscribe', array('entity_type' => $entity_type, 'entity' => $entity, 'plan_code' => $plan_code, 'currency' => $currency)),
+      'change_url' => $subscription ? url($entity_type . '/' . $id . '/subscription/id/' . $subscription->uuid . '/change/' . $plan_code) : NULL,
+    );
+  }
+}
+
+/**
+ * Page callback; Prepare the call to recurly_subscription_plan_change_confirm().
+ */
+function recurly_subscription_plan_change_page($entity_type, $entity, $subscription_id, $new_plan_code) {
+  // Initialize the Recurly client with the site-wide settings.
+  if (!recurly_client_initialize()) {
+    return t('Could not initialize the Recurly client.');
+  }
+
+  // Load the subscription.
+  try {
+    $subscription = Recurly_Subscription::get($subscription_id);
+    // Fully load the plan.
+    $previous_plan = Recurly_Plan::get($subscription->plan->plan_code);
+  }
+  catch (Recurly_NotFoundError $e) {
+    drupal_set_message(t('Subscription not found'));
+    return MENU_NOT_FOUND;
+  }
+
+  // Load the plan.
+  try {
+    $new_plan = Recurly_Plan::get($new_plan_code);
+  }
+  catch (Recurly_NotFoundError $e) {
+    drupal_set_message(t('Plan code not found'));
+    return MENU_NOT_FOUND;
+  }
+
+  return drupal_get_form('recurly_subscription_plan_change_confirm', $entity_type, $entity, $subscription, $previous_plan, $new_plan);
+}
+
+/**
+ * Form callback; Display a confirmation form for changing a subscription plan.
+ */
+function recurly_subscription_plan_change_confirm($form, $form_state, $entity_type, $entity, $subscription, $previous_plan, $new_plan) {
+  // Note that currently Recurly does not have the ability to change the
+  // subscription currency after it has started.
+  // See http://docs.recurly.com/currencies
+  $currency = $subscription->currency;
+  $previous_amount = $previous_plan->unit_amount_in_cents[$currency];
+  $new_amount = $new_plan->unit_amount_in_cents[$currency];
+
+  drupal_set_title(t('Confirm switch to @plan?', array('@plan' => $new_plan->name)), FALSE);
+
+  $form['#entity_type'] = $entity_type;
+  $form['#entity'] = $entity;
+  $form['#subscription'] = $subscription;
+  $form['#previous_plan'] = $previous_plan;
+  $form['#new_plan'] = $new_plan;
+
+  $timeframe = variable_get('recurly_subscription_change_timeframe', 'now');
+  $form['timeframe'] = array(
+    '#type' => 'radios',
+    '#title' => t('Changes take effect'),
+    '#options' => array(
+      'now' => t('Immediately'),
+      'renewal' => t('On next renewal'),
+    ),
+    '#description' => t('If changes take effect immediately, the price difference will either result in a credit applied when the subscription renews or will trigger a prorated charge within the hour.'),
+    '#default_value' => $timeframe,
+    '#access' => user_access('administer recurly'),
+  );
+
+  // TODO: We could potentially calculate the charge/credit amount here, but
+  // math gets messy when switching between plans with different lengths.
+  if ($timeframe === 'now') {
+    $timeframe_message = '<p>' . t('The new plan will take effect immediately and a prorated charge (or credit) will be applied to this account.') . '</p>';
+  }
+  else {
+    $timeframe_message = '<p>' . t('The new plan will take effect on the next billing cycle.') . '</p>';
+  }
+  $form['timeframe_help'] = array(
+    '#markup' => $timeframe_message,
+    '#access' => !user_access('administer recurly'),
+  );
+  $form['actions'] = array(
+    '#type' => 'actions',
+  );
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Change plan'),
+  );
+  return $form;
+}
+
+function recurly_subscription_plan_change_confirm_submit($form, &$form_state) {
+  $entity = $form['#entity'];
+  $entity_type = $form['#entity_type'];
+  $subscription = $form['#subscription'];
+  $new_plan = $form['#new_plan'];
+  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
+
+  // Update the plan.
+  $subscription->plan_code = $new_plan->plan_code;
+  try {
+    if ($form_state['values']['timeframe'] === 'now') {
+      $subscription->updateImmediately();
+    }
+    else {
+      $subscription->updateAtRenewal();
+    }
+  }
+  catch (Recurly_Error $e) {
+    drupal_set_message(t('The plan could not be updated because the billing service encountered an error.'));
+    return;
+  }
+
+  drupal_set_message(t('Plan changed to @plan!', array('@plan' => $new_plan->name)));
+  $form_state['redirect'] = $entity_type . '/' . $id . '/subscription';
+}
+
 /**
  * Menu callback; Display a list of all invoices for a user.
  */
@@ -191,7 +396,8 @@
     return t('Could not initialize the Recurly client.');
   }
 
-  // See if we have a local mapping of entity ID to Recurly account code.
+  // Load the account information. This should already be cached by the access
+  // check to this page by recurly_subscription_page_access().
   list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
   $account = recurly_account_load(array('entity_type' => $entity_type, 'entity_id' => $id));
 
@@ -249,7 +455,8 @@
     return t('Could not initialize the Recurly client.');
   }
 
-  // See if we have a local mapping of entity ID to Recurly account code.
+  // Load the account information. This should already be cached by the access
+  // check to this page by recurly_subscription_page_access().
   list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
   $account = recurly_account_load(array('entity_type' => $entity_type, 'entity_id' => $id));
 
@@ -338,7 +545,8 @@
     return t('Could not initialize the Recurly client.');
   }
 
-  // See if we have a local mapping of entity ID to Recurly account code.
+  // Load the account information. This should already be cached by the access
+  // check to this page by recurly_subscription_page_access().
   list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
   $account = recurly_account_load(array('entity_type' => $entity_type, 'entity_id' => $id));
 
@@ -374,62 +582,6 @@
     // drupal_add_http_header('Content-Length', filesize($pdf), TRUE);
     print $pdf;
     drupal_exit();
-  }
-}
-
-/**
- * Signup page that lists all the available plans for an object.
- */
-function recurly_subscription_signup($entity_type, $entity, $currency = NULL) {
-  // Initialize the Recurly client with the site-wide settings.
-  if (!recurly_client_initialize()) {
-    return t('Could not initialize the Recurly client.');
-  }
-
-  $currency = isset($currency) ? $currency : variable_get('recurly_default_currency', 'USD');
-  $all_plans = recurly_subscription_plans();
-  $enabled_plan_keys = variable_get('recurly_subscription_plans', array());
-  $enabled_plans = array();
-  foreach ($all_plans as $plan) {
-    if (in_array($plan->plan_code, $enabled_plan_keys)) {
-      $enabled_plans[$plan->plan_code] = $plan;
-    }
-  }
-  return theme('recurly_subscription_signup', array('plans' => $enabled_plans, 'entity_type' => $entity_type, 'entity' => $entity, 'currency' => $currency));
-}
-
-/**
- * Preprocess variables for the presentation of the signup page.
- */
-function template_preprocess_recurly_subscription_signup(&$variables) {
-  $plans = $variables['plans'];
-  $currency = $variables['currency'];
-  $variables['filtered_plans'] = array();
-  foreach ($plans as $plan_code => $plan) {
-    $setup_fee_amount = NULL;
-    foreach ($plan->setup_fee_in_cents as $setup_currency) {
-      if ($setup_currency->currencyCode === $currency) {
-        $setup_fee_amount = recurly_format_currency($setup_currency->amount_in_cents, $setup_currency->currencyCode, TRUE);
-        break;
-      }
-    }
-    $unit_amount = NULL;
-    foreach ($plan->unit_amount_in_cents as $unit_currency) {
-      if ($unit_currency->currencyCode === $currency) {
-        $unit_amount = recurly_format_currency($unit_currency->amount_in_cents, $unit_currency->currencyCode, TRUE);
-        break;
-      }
-    }
-    $variables['filtered_plans'][$plan_code] = array(
-      'plan_code' => check_plain($plan_code),
-      'name' => check_plain($plan->name),
-      'description' => check_plain($plan->description),
-      'setup_fee' => $setup_fee_amount,
-      'amount' => $unit_amount,
-      'plan_interval' => recurly_format_price_interval($unit_amount, $plan->plan_interval_length, $plan->plan_interval_unit, TRUE),
-      'trial_interval' => $plan->trial_interval_length ? recurly_format_price_interval(NULL, $plan->trial_interval_length, $plan->trial_interval_unit, TRUE) : NULL,
-      'signup_url' => recurly_url('subscribe', array('entity_type' => $variables['entity_type'], 'entity' => $variables['entity'], 'plan_code' => $plan_code, 'currency' => $currency)),
-    );
   }
 }
 
diff --git a/js/recurly.js b/js/recurly.js
new file mode 100644
index 0000000..43299a5
--- /dev/null
+++ b/js/recurly.js
@@ -0,0 +1,35 @@
+/**
+ * @file
+ * JavaScript provided to enhance UI elements of the Recurly module.
+ */
+(function ($) {
+
+/**
+ * Behavior to change the radio buttons on the change subscription form.
+ */
+Drupal.behaviors.recurlyPlanSelect = {};
+Drupal.behaviors.recurlyPlanSelect.attach = function(context, settings) {
+  $('.plan-signup a.plan-select', context).each(function() {
+    var link = this;
+    var $link = $(this);
+    $link.parents('.plan:first').click(function(e) {
+      if (e.target !== link) {
+        // Click on the link if it's a real URL and not just an anchor.
+        if (!link.href.match(/#$/)) {
+          window.location = link.href;
+        }
+        // Otherwise trigger the handler which selects the radio button.
+        else {
+          $(this).find('a.plan-select').click();
+        }
+      }
+    });
+    $link.parents('.plan:first').hover(function() {
+      $(this).addClass('plan-hover');
+    }, function() {
+      $(this).removeClass('plan-hover');
+    });
+  });
+};
+
+})(jQuery);
diff --git a/recurly.module b/recurly.module
index f215557..16a7d8b 100644
--- a/recurly.module
+++ b/recurly.module
@@ -61,7 +61,7 @@
     $entity_path = $entity_type . '/%' . $entity_type;
     $items[$entity_path . '/subscription'] = array(
       'title' => variable_get('recurly_entity_display_title', 'Billing'),
-      'page callback' => 'recurly_subscription_page',
+      'page callback' => 'recurly_subscription_list_page',
       'page arguments' => array($entity_type, 1),
       'access callback' => 'recurly_subscription_page_access',
       'access arguments' => array($entity_type, 1, 'summary'),
@@ -77,6 +77,52 @@
       'access arguments' => array($entity_type, 1, 'subscriptions'),
       'type' => MENU_DEFAULT_LOCAL_TASK,
       'weight' => 0,
+      'file' => 'includes/recurly.pages.inc',
+    );
+    $items[$entity_path . '/subscription/signup'] = array(
+      'title' => 'Signup',
+      'page callback' => 'recurly_subscription_plan_list',
+      'page arguments' => array($entity_type, 1),
+      'access callback' => 'recurly_subscription_page_access',
+      'access arguments' => array($entity_type, 1, 'subscribe'),
+      'type' => MENU_DEFAULT_LOCAL_TASK,
+      'weight' => 0,
+      'file' => 'includes/recurly.pages.inc',
+    );
+    $items[$entity_path . '/subscription/id/%'] = array(
+      'title' => 'Select a new plan',
+      'page callback' => 'recurly_subscription_plan_list',
+      'page arguments' => array($entity_type, 1, NULL, 4),
+      'access callback' => 'recurly_subscription_page_access',
+      'access arguments' => array($entity_type, 1, 'change'),
+      'type' => MENU_CALLBACK,
+      'file' => 'includes/recurly.pages.inc',
+    );
+    $items[$entity_path . '/subscription/id/%/change/%'] = array(
+      'title' => 'Change subscription',
+      'page callback' => 'recurly_subscription_plan_change_page',
+      'page arguments' => array($entity_type, 1, 4, 6),
+      'access callback' => 'recurly_subscription_page_access',
+      'access arguments' => array($entity_type, 1, 'change'),
+      'type' => MENU_CALLBACK,
+      'file' => 'includes/recurly.pages.inc',
+    );
+    $items[$entity_path . '/subscription/id/%/cancel'] = array(
+      'title' => 'Cancel subscription',
+      'page callback' => 'recurly_subscription_cancel_page',
+      'page arguments' => array($entity_type, 1, 4),
+      'access callback' => 'recurly_subscription_page_access',
+      'access arguments' => array($entity_type, 1, 'cancel'),
+      'type' => MENU_CALLBACK,
+      'file' => 'includes/recurly.pages.inc',
+    );
+    $items[$entity_path . '/subscription/id/%/reactivate'] = array(
+      'title' => 'Reactivate subscription',
+      'page callback' => 'recurly_subscription_reactivate_page',
+      'page arguments' => array($entity_type, 1, 4),
+      'access callback' => 'recurly_subscription_page_access',
+      'access arguments' => array($entity_type, 1, 'reactivate'),
+      'type' => MENU_CALLBACK,
       'file' => 'includes/recurly.pages.inc',
     );
     $items[$entity_path . '/subscription/invoices'] = array(
@@ -105,16 +151,6 @@
       'access callback' => 'recurly_subscription_page_access',
       'access arguments' => array($entity_type, 1, 'invoices'),
       'type' => MENU_CALLBACK,
-      'file' => 'includes/recurly.pages.inc',
-    );
-    $items[$entity_path . '/subscription/signup'] = array(
-      'title' => 'Signup',
-      'page callback' => 'recurly_subscription_signup',
-      'page arguments' => array($entity_type, 1),
-      'access callback' => 'recurly_subscription_page_access',
-      'access arguments' => array($entity_type, 1, 'subscribe'),
-      'type' => MENU_DEFAULT_LOCAL_TASK,
-      'weight' => 0,
       'file' => 'includes/recurly.pages.inc',
     );
   }
@@ -217,9 +253,9 @@
     'template' => 'templates/recurly-invoice-list',
     'file' => 'includes/recurly.pages.inc',
   );
-  $items['recurly_subscription_signup'] = array(
-    'variables' => array('plans' => NULL, 'entity_type' => NULL, 'entity' => NULL),
-    'template' => 'templates/recurly-subscription-signup',
+  $items['recurly_subscription_plan_list'] = array(
+    'variables' => array('plans' => NULL, 'entity_type' => NULL, 'entity' => NULL, 'currency' => NULL, 'mode' => 'subscribe', 'subscription' => NULL),
+    'template' => 'templates/recurly-subscription-plan-list',
     'file' => 'includes/recurly.pages.inc',
   );
 
@@ -324,9 +360,10 @@
         recurly_account_save($recurly_account, $local_account->entity_type, $local_account->entity_id, $local_account->data);
       }
     }
-  }
 
-  module_invoke_all('recurly_process_push_notification', $subdomain, $notification);
+    // Allow other modules to respond to incoming notifications.
+    module_invoke_all('recurly_process_push_notification', $subdomain, $notification);
+  }
 }
 
 /**
diff --git a/templates/recurly-subscription-plan-list.tpl.php b/templates/recurly-subscription-plan-list.tpl.php
index 01b1108..4f4612b 100644
--- a/templates/recurly-subscription-plan-list.tpl.php
+++ b/templates/recurly-subscription-plan-list.tpl.php
@@ -3,20 +3,30 @@
  * @file
  * Display a signup page listing all the available plans.
  */
+drupal_add_css(drupal_get_path('module', 'recurly') . '/css/recurly.css');
+drupal_add_js(drupal_get_path('module', 'recurly') . '/js/recurly.js');
 ?>
-<div class="recurly-signup">
+<div class="recurly-signup recurly-plan-list clearfix">
   <?php foreach ($filtered_plans as $plan): ?>
-    <div class="plan plan-<?php print $plan['plan_code']; ?>">
+    <div class="plan plan-<?php print $plan['plan_code']; ?><?php print ($mode == 'change' && $plan['plan_code'] === $subscription->plan->plan_code) ? ' plan-selected' : '' ?>">
       <h2><?php print $plan['name']; ?></h2>
       <div class="plan-interval"><?php print $plan['plan_interval']; ?></div>
       <?php if ($plan['trial_interval']): ?>
         <div class="plan-trial"><?php print $plan['trial_interval']; ?></div>
       <?php endif; ?>
       <div class="plan-signup">
-        <?php if ($plan['signup_url']): ?>
-        <a href="<?php print $plan['signup_url']; ?>"><?php print t('Sign up'); ?></a>
+        <?php if ($mode == 'subscribe'): ?>
+          <?php if ($plan['signup_url']): ?>
+            <a class="plan-select" href="<?php print $plan['signup_url']; ?>"><?php print t('Sign up'); ?></a>
+          <?php else: ?>
+            <?php print t('Contact us to sign up'); ?>
+          <?php endif; ?>
         <?php else: ?>
-        <?php print t('Contact us to sign up'); ?>
+          <?php if ($plan['plan_code'] === $subscription->plan->plan_code): ?>
+            <strong><?php print t('Current plan'); ?></strong>
+          <?php else: ?>
+            <a class="plan-select" href="<?php print $plan['change_url']; ?>"><?php print t('Select'); ?></a>
+          <?php endif; ?>
         <?php endif; ?>
       </div>
       <div class="plan-description"><?php print nl2br($plan['description']); ?></div>