diff --git a/quiz.admin.inc b/quiz.admin.inc
index 0f4707a..b41f8fd 100644
--- a/quiz.admin.inc
+++ b/quiz.admin.inc
@@ -119,7 +119,7 @@ function quiz_admin_settings($form, &$form_state) {
   $form['quiz_global_settings']['quiz_admin_review_options']['#title'] = t('Administrator review options');
   $form['quiz_global_settings']['quiz_admin_review_options']['#type'] = 'fieldset';
   $form['quiz_global_settings']['quiz_admin_review_options']['#description'] = t('Control what feedback types quiz administrators will see when viewing results for other users.');
-  foreach (array('question' => t('After the question'), 'end' => t('After the @quiz', array('@quiz' => QUIZ_NAME))) as $key => $when) {
+  foreach (quiz_get_feedback_times() as $key => $when) {
     $form['quiz_global_settings']['quiz_admin_review_options']["quiz_admin_review_options_$key"] = array(
       '#title' => $when,
       '#type' => 'checkboxes',
diff --git a/quiz.api.php b/quiz.api.php
index 8e02195..056392b 100644
--- a/quiz.api.php
+++ b/quiz.api.php
@@ -83,3 +83,57 @@ function hook_quiz_question_info() {
     ),
   );
 }
+
+/**
+ * Expose a feedback option to Quiz so that Quiz administrators can choose when
+ * to show it to Quiz takers.
+ *
+ * @return array
+ *   An array of feedback options keyed by machine name.
+ */
+function hook_quiz_feedback_options() {
+  return array(
+    'percentile' => t('Percentile'),
+  );
+}
+
+/**
+ * Allow modules to alter the quiz feedback options.
+ *
+ * @param array $review_options
+ *   An array of review options keyed by a machine name.
+ */
+function hook_quiz_feedback_options_alter(&$review_options) {
+  // Change label.
+  $review_options['quiz_feedback'] = t('General feedback from the Quiz.');
+
+  // Disable showing correct answer.
+  unset($review_options['solution']);
+}
+
+/**
+ * Allow modules to define feedback times.
+ *
+ * Feedback times are configurable by Rules.
+ *
+ * @return array
+ *   An array of feedback times keyed by machine name.
+ */
+function hook_quiz_feedback_times() {
+  return array(
+    '2_weeks_later' => t('Two weeks after finishing'),
+  );
+}
+
+/**
+ * Allow modules to alter the feedback times.
+ *
+ * @param array $feedback_times
+ */
+function hook_quiz_feedback_times_alter(&$feedback_times) {
+  // Change label.
+  $feedback_times['end'] = t('At the end of a quiz');
+
+  // Do not allow question feedback.
+  unset($feedback_times['question']);
+}
diff --git a/quiz.info b/quiz.info
index d6b8ee4..9c8330a 100644
--- a/quiz.info
+++ b/quiz.info
@@ -5,6 +5,7 @@ core = 7.x
 dependencies[] = ctools
 dependencies[] = entity
 dependencies[] = filter
+dependencies[] = rules
 dependencies[] = views
 dependencies[] = views_bulk_operations
 test_dependencies[] = taxonomy
diff --git a/quiz.module b/quiz.module
index ac78a6a..1eec67a 100644
--- a/quiz.module
+++ b/quiz.module
@@ -486,6 +486,9 @@ function quiz_menu() {
     );
   }
 
+  $items += rules_ui()->config_menu('admin/quiz/feedback');
+
+
   return $items;
 }
 
@@ -1137,6 +1140,7 @@ function quiz_form(&$node, &$form_state) {
     . '<br/>' . t('<strong>Categorized random questions</strong> - specific number of questions are drawn from each specified taxonomy term'),
     '#default_value' => $node->randomization,
   );
+
   $form['taking']['review_options'] = array(
     '#type' => 'fieldset',
     '#title' => t('Review options'),
@@ -1148,7 +1152,7 @@ function quiz_form(&$node, &$form_state) {
 
   $review_options = quiz_get_feedback_options();
 
-  foreach (array('question' => t('After the question'), 'end' => t('After the @quiz', array('@quiz' => QUIZ_NAME))) as $key => $when) {
+  foreach (quiz_get_feedback_times() as $key => $when) {
     $form['taking']['review_options'][$key] = array(
       '#title' => $when,
       '#type' => 'checkboxes',
@@ -1156,6 +1160,7 @@ function quiz_form(&$node, &$form_state) {
       '#default_value' => isset($node->review_options[$key]) ? $node->review_options[$key] : array(),
     );
   }
+
   $options = array(t('Unlimited'));
   for ($i = 1; $i < 10; $i++) {
     $options[$i] = $i;
@@ -1343,17 +1348,17 @@ function quiz_form(&$node, &$form_state) {
   $options = !empty($node->resultoptions) ? $node->resultoptions : array();
   $num_options = max(count($options), variable_get('quiz_max_result_options', 5));
 
-  if ($num_options > 0) {
-    $form['resultoptions'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Result feedback'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-      '#tree' => TRUE,
-      '#attributes' => array('id' => 'resultoptions-fieldset'),
-      '#group' => 'additional_settings',
-    );
+  $form['resultoptions'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Result feedback'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#tree' => TRUE,
+    '#attributes' => array('id' => 'resultoptions-fieldset'),
+    '#group' => 'additional_settings',
+  );
 
+  if ($num_options > 0) {
     for ($i = 0; $i < $num_options; $i++) {
       $option = (count($options) > 0) ? array_shift($options) : NULL; // grab each option in the array
       $form['resultoptions'][$i] = array(
@@ -3804,23 +3809,43 @@ function quiz_feedback_can_review($option, $quiz_result) {
   $admin = node_access('update', $quiz);
 
   if ($admin) {
+    // Admin user uses the global feedback options.
     $review_options['end'] = variable_get('quiz_admin_review_options_end');
     $review_options['question'] = variable_get('quiz_admin_review_options_question');
   }
   else {
+    // Use this Quiz's feedback options.
     $review_options = $quiz->review_options;
   }
 
-  // Check what context the result is in.
-  if ($quiz_result->time_end && arg(2) != 'take') {
-    // Quiz is over. Pull from the "at quiz end" settings.
-    return !empty($review_options['end'][$option]);
-  }
-
-  if (!$quiz_result->time_end || $quiz_result->time_end >= REQUEST_TIME - 5) {
-    // Quiz ongoing. Pull from the "after question" settings.
-    return !empty($review_options['question'][$option]);
+  $all_shows = array();
+  foreach ($review_options as $time_key => $shows) {
+    // Loop through all the feedback times and check conditions.
+    if ($set = rules_config_load("quiz_feedback_{$time_key}")) {
+      if (!$set->execute($quiz_result)) {
+        // The rule did not pass. Remove the quiz feedback time from eligbility.
+        unset($review_options[$time_key]);
+      }
+      else {
+        // Rules pass so now do something.
+        
+        if ($time_key == 'end') {
+          if ($quiz_result->time_end && arg(2) != 'take') {
+            $all_shows += array_filter($shows);
+          }
+        }
+        else if ($time_key == 'question') {
+          if (!$quiz_result->time_end || $quiz_result->time_end >= REQUEST_TIME - 5) {
+            $all_shows += array_filter($shows);
+          }
+        }
+        else {
+          $all_shows += array_filter($shows);
+        }
+      }
+    }
   }
+  return !empty($all_shows[$option]);
 }
 
 /**
@@ -3853,6 +3878,20 @@ function quiz_get_feedback_options() {
 }
 
 /**
+ * Get the feedback options for Quizzes.
+ */
+function quiz_get_feedback_times() {
+  $feedback_times = array(
+    'question' => t('After the question'),
+    'end' => t('After the quiz'),
+  );
+
+  drupal_alter('quiz_feedback_times', $feedback_times);
+
+  return $feedback_times;
+}
+
+/**
  * Check if the question has already been answered in the requested attempt.
  *
  * @return boolean
diff --git a/quiz.rules_defaults.inc b/quiz.rules_defaults.inc
new file mode 100644
index 0000000..da5f307
--- /dev/null
+++ b/quiz.rules_defaults.inc
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * Implements hook_default_rules_configuration().
+ */
+function quiz_default_rules_configuration() {
+  $configs = array();
+  foreach (quiz_get_feedback_times() as $key => $title) {
+    $set = rules_and(array(
+      'quiz_result' => array('type' => 'quiz_result', 'label' => t('Quiz attempt')),
+    ));
+    $set->label = t('@title feedback conditions', array('@title' => $title));
+    $set->tags[] = 'quiz';
+
+    $configs["quiz_feedback_$key"] = $set;
+  }
+
+  return $configs;
+}
