diff --git a/salsa_advocacy/salsa_advocacy.module b/salsa_advocacy/salsa_advocacy.module
index 31b05ce..2da19c2 100644
--- a/salsa_advocacy/salsa_advocacy.module
+++ b/salsa_advocacy/salsa_advocacy.module
@@ -181,6 +181,21 @@ function salsa_advocacy_petition_form($form, &$form_state, $action) {
   }
   $action_content_detail = entity_load('salsa_action_content_detail', FALSE, array('action_content_KEY' => $action_content->action_content_KEY));
   $action_content_detail = reset($action_content_detail);
+
+  // Check if progress bar is enabled.
+  if (!empty($action->Signature_Goal) && $action->Signatures != 'Do not show signatures') {
+    // Add the progress bar.
+    salsa_entity_add_progress_bar(
+      $action,
+      $form_state['build_info']['form_id'],
+      salsa_advocacy_get_supporter_actions_total($action),
+      $action->Signature_Goal,
+      $form
+    );
+  }
+  // Set weight in order to display on top of supporter fieldset.
+  $form['progress']['#weight'] = -200;
+
   if ($action_content_detail->Recommended_Content) {
     // @todo For some reason petition content are highlighted on public page,
     // so I added the prefix and suffix, but it can be removed if there is no need.
@@ -344,6 +359,9 @@ function salsa_advocacy_petition_form_submit($form, &$form_state) {
   // Create a new one or update existing supporter.
   salsa_entity_supporter_fieldset_submit($form, $form_state);
 
+  // Clear the cached count of supporter actions on this action.
+  cache_clear_all('salsa_advocacy_supporter_action_count:' . $form_state['salsa_object']->action_KEY, 'cache');
+
   // Save comments, if any.
   if (!empty($form_state['values']['Comment'])) {
     $supporter_action_comment = new SalsaEntity(array(), 'salsa_supporter_action_comment');
@@ -409,6 +427,7 @@ function salsa_advocacy_petition_form_submit($form, &$form_state) {
  * Salsa targeted action form callback.
  */
 function salsa_advocacy_targeted_form($form, &$form_state, $action) {
+  $form_state['salsa_object'] = $action;
   $action_content = reset(entity_load('salsa_action_content', FALSE, array('action_KEY' => $action->action_KEY)));
   $action_content_detail = reset(entity_load('salsa_action_content_detail', FALSE, array('action_content_KEY' => $action_content->key)));
   $action_target = reset(entity_load('salsa_action_target', FALSE, array('action_KEY' => $action->action_KEY)));
@@ -504,6 +523,18 @@ function salsa_advocacy_targeted_form($form, &$form_state, $action) {
       }
     }
 
+    // Check if progress bar is enabled.
+    $field_key = variable_get('salsa_advocacy_targeted_goal_field');
+    if (!empty($action->{$field_key})) {
+      salsa_entity_add_progress_bar(
+        $action,
+        $form_state['build_info']['form_id'],
+        salsa_advocacy_get_supporter_actions_total($action),
+        $action->{$field_key},
+        $form
+      );
+    }
+
     // Action content fieldset.
     $form['action_content'] = array(
       '#type' => 'fieldset',
@@ -566,9 +597,6 @@ function salsa_advocacy_targeted_form($form, &$form_state, $action) {
     // Add hidden fields.
     salsa_advocacy_targeted_form_hidden_fields($form, $form_state);
 
-    // Submit this form directly to salsa page.
-    $form['#action'] = variable_get('salsa_api_url') . '/o/' . $action->organization_KEY . '/action/wrapperProcessAction2.jsp';
-
     // Submit button.
     $form['submit'] = array(
       '#type' => 'submit',
@@ -586,6 +614,39 @@ function salsa_advocacy_targeted_form($form, &$form_state, $action) {
 }
 
 /**
+ * Submit handler for the single target action form.
+ *
+ * Necessary to clear the cache for the supporter actions count and for the
+ * mollom captcha validation.
+ */
+function salsa_advocacy_targeted_form_submit($form, &$form_state) {
+  $action = $form_state['salsa_object'];
+  // Clear the cached count of supporter actions on this action.
+  cache_clear_all('salsa_advocacy_supporter_action_count:' . $action->action_KEY, 'cache');
+
+  // Eventually submit the data to the salsa page.
+  $salsa_url = variable_get('salsa_api_url') . '/o/' . $action->organization_KEY . '/action/wrapperProcessAction2.jsp';
+  // Get data from raw request body instead of using http_build_query() as
+  // fields with same names get missing that way.
+  $options = array(
+    'method' => 'POST',
+    'data' => file_get_contents('php://input'),
+    'headers' => array(
+      'Content-Type' => 'application/x-www-form-urlencoded',
+    ),
+  );
+  drupal_http_request($salsa_url, $options);
+
+  // Redirect the the configured uri or the frontpage otherwise.
+  if (!empty($action->redirect_path)) {
+    $form_state['redirect'] = $action->redirect_path;
+  }
+  else {
+    $form_state['redirect'] = '<front>';
+  }
+}
+
+/**
  * Hidden fields for targeted actions form.
  */
 function salsa_advocacy_targeted_form_hidden_fields(&$form, $form_state) {
@@ -1044,6 +1105,27 @@ function salsa_advocacy_fetch_action_targets($action_key) {
  *   A form array set for theming by theme_salsa_advocacy_settings_form()
  */
 function salsa_advocacy_settings_form($form, &$form_state) {
+  // Custom fields used as goal for progress bars on action forms.
+  $custom_fields = salsa_entity_custom_fields('action');
+  if (!empty($custom_fields)) {
+    $form['progress'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Progress bar'),
+    );
+
+    foreach ($custom_fields as $field_name => $field) {
+      $options[$field_name] = $field['label'];
+    }
+    $form['progress']['ssalsa_advocacy_targeted_goal_field'] = array(
+      '#type' => 'select',
+      '#title' => t('Salsa Advocacy Goal Field'),
+      '#description' => t('Salsa custom field that contains the submission goal for actions.'),
+      '#options' => $options,
+      '#default_value' => variable_get('salsa_advocacy_targeted_goal_field'),
+      '#empty_option' => t('- None -'),
+    );
+  }
+
   $form['items']['#tree'] = TRUE;
 
   // Fetch custom fields.
@@ -1152,19 +1234,49 @@ function theme_salsa_advocacy_settings_form($variables) {
  * Submit handler for advocacy settings form.
  */
 function salsa_advocacy_settings_form_submit($form, &$form_state) {
-  $custom_fields_settings = array();
-  foreach ($form_state['values']['items'] as $item) {
-    $custom_fields_settings[$item['name']] = array(
-      'weight' => $item['weight'],
-      'fixed_value' => $item['fixed'],
-      'default_value' => $item['default_value'],
-      'default_value_callback' => '',
-      'enabled' => $item['enabled'] ? TRUE : FALSE,
-    );
+  if (isset($form_state['values']['items'])) {
+    $custom_fields_settings = array();
+    foreach ($form_state['values']['items'] as $item) {
+      $custom_fields_settings[$item['name']] = array(
+        'weight' => $item['weight'],
+        'fixed_value' => $item['fixed'],
+        'default_value' => $item['default_value'],
+        'default_value_callback' => '',
+        'enabled' => $item['enabled'] ? TRUE : FALSE,
+      );
+    }
+    variable_set('salsa_advocacy_custom_fields', $custom_fields_settings);
   }
-  variable_set('salsa_advocacy_custom_fields', $custom_fields_settings);
+
+  // Set the field for the barometer goal targeted actions.
+  variable_set('salsa_advocacy_targeted_goal_field', $form_state['values']['salsa_advocacy_targeted_goal_field']);
+
   cache_clear_all('salsa_advocacy_mapping', 'cache');
   cache_clear_all('salsa_advocacy_filters', 'cache');
   cache_clear_all('salsa_advocacy_custom_fields', 'cache');
   drupal_set_message(t('Settings have been saved.'));
 }
+
+/**
+ * Retrieves the supporter action objects related to a given action.
+ *
+ * Caches the data that is fetched from Salsa if the count isn't cached yet,
+ * otherwise cached data is returned.
+ *
+ * @param object $action
+ *   The Salsa entity of type action.
+ *
+ * @return int
+ *   The amount ob supporter actions for the given action.
+ */
+function salsa_advocacy_get_supporter_actions_total($action) {
+  $cache = cache_get('salsa_advocacy_supporter_action_count:' . $action->action_KEY);
+  if (!$cache) {
+    $salsa_api = salsa_api();
+    $count = $salsa_api->getCount('supporter_action', array('action_KEY' => $action->action_KEY));
+    cache_set('salsa_advocacy_supporter_action_count:' . $action->action_KEY, $count);
+    return $count;
+  }
+
+  return $cache->data;
+}
diff --git a/salsa_donate_page/salsa_donate_page.module b/salsa_donate_page/salsa_donate_page.module
index 7e07ad4..5596d49 100644
--- a/salsa_donate_page/salsa_donate_page.module
+++ b/salsa_donate_page/salsa_donate_page.module
@@ -45,13 +45,6 @@ function salsa_donate_page_menu() {
  */
 function salsa_donate_page_theme() {
   return array(
-    'salsa_donate_page_progress_bar' => array(
-      'variables' => array(
-        'goal' => NULL,
-        'value' => NULL,
-        'total' => NULL,
-      ),
-    ),
     'salsa_donate_page_donors_list' => array(
       'variables' => array(
         'row_values' => array(),
@@ -85,6 +78,19 @@ function salsa_donate_page_mollom_form_info($form_id) {
 }
 
 /**
+ * Implements hook_salsa_entity_progress_bar_labels().
+ *
+ * Add currencies to the amounts and change the labels of the donation progress
+ * bar.
+ */
+function salsa_donate_page_salsa_entity_progress_bar_labels(&$labels) {
+  $labels['goal'] = salsa_entity_get_amount($labels['goal'], TRUE);
+  $labels['total'] = salsa_entity_get_amount($labels['total'], TRUE);
+  $labels['goal_label'] = t('Donation goal:');
+  $labels['total_label'] = t('Donated:');
+}
+
+/**
  * Donate Page form.
  *
  * @todo State / Province should be dynamic.
@@ -110,11 +116,6 @@ function salsa_donate_page_form($form, &$form_state, $donate_page, $view_mode) {
         'data' => drupal_get_path('module', 'salsa_entity') . '/salsa_donate_page/js/salsa_donate_page.behaviors.js',
       ),
     ),
-    'css' => array(
-      array(
-        'data' => drupal_get_path('module', 'salsa_donate_page') . '/includes/salsa_donate_page.css'
-      ),
-    ),
   );
 
   // Add default required fields for a donation.
@@ -210,9 +211,16 @@ function salsa_donate_page_form($form, &$form_state, $donate_page, $view_mode) {
     '#title' => t('Donation Amount'),
   );
 
-  $form['Donation']['progress'] = array(
-    '#markup' => salsa_donate_page_get_barometer($donate_page),
-  );
+  $field_key = variable_get('salsa_donations_goal_field');
+  if (!empty($donate_page->{$field_key})) {
+    salsa_entity_add_progress_bar(
+      $donate_page,
+      $form_state['build_info']['form_id'],
+      salsa_donate_page_total_donation_amount($donate_page->donate_page_KEY),
+      $donate_page->{$field_key},
+      $form
+    );
+  }
 
   if (variable_get('salsa_donations_donors_list_row_count', 0)) {
     $form['Donation']['donors_list'] = salsa_donate_page_get_donors_list($donate_page);
@@ -1014,20 +1022,6 @@ function salsa_donate_page_get_latest_donations($donate_page_key, $limit) {
 }
 
 /**
- * Theme function for the donation barometer.
- */
-function theme_salsa_donate_page_progress_bar($vars) {
-  $output =  '<div class="donate-page-barometer-wrapper">';
-  $output .=   '<div class="donate-page-donation-goal">' . t('Donation goal:') . '&nbsp;' . $vars['goal'] . '</div>';
-  $output .=   '<div class="donate-page-barometer">';
-  $output .=     '<span class="donate-page-barometer-label">' . t('Donated:') . '&nbsp;' . $vars['total'] . '</span>';
-  $output .=     '<div class="donate-page-barometer-progress" style="width:' . min($vars['value'], 100) . '%;"></div>';
-  $output .=   '</div>';
-  $output .= '</div>';
-  return $output;
-}
-
-/**
  * Theme function for the donors list.
  */
 function theme_salsa_donate_page_donors_list($vars) {
@@ -1064,31 +1058,6 @@ function theme_salsa_donate_page_donors_list($vars) {
 }
 
 /**
- * Wrapper function to get the markup of the barometer.
- *
- * @param object $donate_page
- *   The salsa donation object.
- *
- * @return string
- *   The markup of the barometer.
- */
-function salsa_donate_page_get_barometer($donate_page) {
-  $field_name = variable_get('salsa_donations_goal_field');
-  // Return an empty string if the goal isn't set.
-  if (empty($donate_page->{$field_name})) {
-    return '';
-  }
-  $total = salsa_donate_page_total_donation_amount($donate_page->donate_page_KEY);
-  $goal = $donate_page->{$field_name};
-  $value = (($total / $goal) < 1) ? ($total / $goal) : 1;
-  return theme('salsa_donate_page_progress_bar', array(
-    'goal' => salsa_entity_get_amount($goal, TRUE),
-    'value' => min(round($value * 100), 100),
-    'total' => salsa_entity_get_amount(salsa_donate_page_total_donation_amount($donate_page->donate_page_KEY), TRUE),
-  ));
-}
-
-/**
  * Wrapper that prints the markup for the donors list.
  *
  * @param object $donate_page
diff --git a/salsa_entity.module b/salsa_entity.module
index 8f39734..57598ba 100644
--- a/salsa_entity.module
+++ b/salsa_entity.module
@@ -66,6 +66,16 @@ function salsa_entity_theme() {
         'title' => NULL,
       ),
     ),
+    'salsa_entity_progress_bar' => array(
+      'variables' => array(
+        'goal' => NULL,
+        'value' => NULL,
+        'total' => NULL,
+        'goal_label' => NULL,
+        'total_label' => NULL,
+        'barometer_type' => NULL,
+      ),
+    ),
   );
 }
 
@@ -825,6 +835,76 @@ function salsa_entity_filter_info() {
 }
 
 /**
+ *
+ * @param $salsa_object
+ * @param $barometer_type
+ * @param $total
+ * @param $goal_field_key
+ * @param $form
+ * @return string
+ */
+
+/**
+ * Creates the markup of the barometer.
+ *
+ * Also adds the corresponding CSS to the form and gives other modules a chance
+ * to alter the labels that will be used.
+ *
+ * @param object $salsa_object
+ *   Salsa entity object of any type.
+ * @param string $barometer_type
+ *   Identifier passed by the requesting function, can be used as translation
+ *   context to have varying labels for progress bars on the different salsa
+ *   forms.
+ * @param int $total
+ *   Counted amount for the current progress.
+ * @param string $goal_field_key
+ *   Key for the property on the salsa object that contains the goal amount.
+ * @param array $form
+ *   The form on which the progress bar will be displayed, passed by reference.
+ *
+ * @return string
+ *   The markup for the barometer.
+ */
+function salsa_entity_add_progress_bar($salsa_object, $barometer_type, $total, $goal, &$container) {
+  // Don't allow rendering of progress bar without values that make sense.
+  if (!$total && !$goal) {
+    return '';
+  }
+
+  // Calculate the percentage of the total for the styling of the progress bar.
+  $value = (($total / $goal) < 1) ? ($total / $goal) : 1;
+
+  // Give other modules a chance to alter the labels.
+  $labels = array(
+    'goal' => $goal,
+    'total' =>  $total,
+    'goal_label' => t('Goal'),
+    'total_label' => t('Total'),
+  );
+  drupal_alter('salsa_entity_progress_bar_labels', $labels);
+
+  // Add the progress bar CSS to the requesting form.
+  $container['#attached']['css'] = array(
+    array(
+      'data' => drupal_get_path('module', 'salsa_entity') . '/theme/salsa_progress_bar.css'
+    ),
+  );
+
+  // Theme the progress bar with the collected values and add it to the form.
+  $container['progress'] = array(
+    '#markup' => theme('salsa_entity_progress_bar', array(
+      'goal' => $labels['goal'],
+      'goal_label' => $labels['goal_label'],
+      'total' => $labels['total'],
+      'total_label' => $labels['total_label'],
+      'value' => min(round($value * 100), 100),
+      'barometer_type' => $barometer_type,
+    )),
+  );
+}
+
+/**
  * Filter process callback to render an entity.
  */
 function _salsa_entity_filter_entity_view($text, $filter, $format, $langcode, $cache, $cache_id) {
@@ -853,3 +933,17 @@ function _salsa_entity_filter_replace_callback($matches) {
     }
   }
 }
+
+/**
+ * Theme function for the progress barometer.
+ */
+function theme_salsa_entity_progress_bar($vars) {
+  $output =  '<div class="salsa-barometer-wrapper">';
+  $output .=   '<div class="salsa-barometer-goal">' . $vars['goal_label'] . '&nbsp;' . $vars['goal'] . '</div>';
+  $output .=   '<div class="salsa-barometer">';
+  $output .=     '<span class="salsa-barometer-label">' . $vars['total_label'] . '&nbsp;' . $vars['total'] . '</span>';
+  $output .=     '<div class="salsa-barometer-progress" style="width:' . min($vars['value'], 100) . '%;"></div>';
+  $output .=   '</div>';
+  $output .= '</div>';
+  return $output;
+}
