diff --git a/contrib/views/README.txt b/contrib/views/README.txt
new file mode 100644
index 0000000..126f149
--- /dev/null
+++ b/contrib/views/README.txt
@@ -0,0 +1,42 @@
+
+-- Summary --
+
+The "facetapi views" module integrates the facet api into views.
+Main goal is to provide a connection between the views exposed filters and the
+facets.
+
+
+-- Features --
+
+* Keep selected facets when changing views exposed filters.
+* Use views filters to preset facet links
+
+
+-- Requirements --
+
+facetapi & views
+
+
+-- Installation
+
+* Install as usual, see following link for further information:
+  http://drupal.org/documentation/install/modules-themes/modules-7
+
+
+-- Configuration
+
+* Configure the facetapi filter in the views where you'd like to keep the facets
+  when changing the views exposed filter.
+* Configure the URL processor for facetapi to use views filters to preset the
+  facets.
+
+
+-- Credits
+
+Source Issue: http://drupal.org/node/1797616
+* mErilainen for the URL processor - see his blog post:
+  http://wunderkraut.com/blog/marrying-facets-and-exposed-filters/2012-10-24
+* Soul88 for the intial views code - see his sandbox:
+  http://drupal.org/sandbox/Soul88/1865682
+* das-peter for merging and polishing both approaches into one module ;)
+
diff --git a/contrib/views/facetapi_views.info b/contrib/views/facetapi_views.info
new file mode 100644
index 0000000..9b49e5a
--- /dev/null
+++ b/contrib/views/facetapi_views.info
@@ -0,0 +1,12 @@
+name = Facet API Views
+description = "Views integration for Fact API."
+package = FacetAPI
+core = "7.x"
+
+dependencies[] = facetapi
+dependencies[] = views
+
+configure = admin/config/search/facetapi/views
+
+files[] = plugins/facetapi/url_processor_exposed_facets.inc
+files[] = views/facetapi_views_handler_filter_keep_facet_values.inc
diff --git a/contrib/views/facetapi_views.install b/contrib/views/facetapi_views.install
new file mode 100644
index 0000000..1e0acea
--- /dev/null
+++ b/contrib/views/facetapi_views.install
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @file
+ * Facet API views integration.
+ */
+
+/**
+ * Implements hook_uninstall().
+ */
+function facetapi_views_uninstall() {
+  variable_del('facetapi_views_url_processor_searchers');
+  variable_del('facetapi_views_url_processor_for_all_searchers');
+}
diff --git a/contrib/views/facetapi_views.module b/contrib/views/facetapi_views.module
new file mode 100644
index 0000000..6634c61
--- /dev/null
+++ b/contrib/views/facetapi_views.module
@@ -0,0 +1,107 @@
+<?php
+
+/**
+ * @file
+ * Facet API views integration.
+ */
+
+/**
+ * Implements hook_facetapi_url_processors().
+ */
+function facetapi_views_facetapi_url_processors() {
+  return array(
+    'exposed_facets' => array(
+      'handler' => array(
+        'label' => t('Views exposed filter format'),
+        'class' => 'FacetapiUrlProcessorExposedFacets',
+      ),
+    ),
+  );
+}
+
+/**
+ * Implements hook_facetapi_searcher_info().
+ *
+ * Allows for alterations to the searcher definitions.
+ */
+function facetapi_views_facetapi_searcher_info_alter(array &$searcher_info) {
+  $enabled_searcher = array_filter(variable_get('facetapi_views_url_processor_searchers', array()));
+  $use_for_all_searchers = variable_get('facetapi_views_url_processor_for_all_searchers', TRUE);
+  foreach ($searcher_info as $name => &$info) {
+    if ($use_for_all_searchers || isset($enabled_searcher[$name])) {
+      // Activate custom URL processor.
+      $id = 'exposed_facets_searcher_' . $info['name'];
+      $info['url processor'] = 'exposed_facets';
+    }
+  }
+}
+
+/**
+ * Implements hook_views_api().
+ */
+function facetapi_views_views_api() {
+  return array(
+    'api' => 3,
+    'path' => drupal_get_path('module', 'facetapi_views') . '/views',
+  );
+}
+
+/**
+ * Implements hook_menu().
+ */
+function facetapi_views_menu() {
+  $items['admin/config/search/facetapi/views'] = array(
+    'title' => 'Facet API Views Settings',
+    'description' => 'Configure the Facet API Views integration.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('facetapi_views_settings_form'),
+    'access arguments' => array('administer facets'),
+    'type' => MENU_LOCAL_TASK,
+  );
+  return $items;
+}
+
+/**
+ * Implements hook_menu_alter().
+ */
+function facetapi_views_menu_alter(&$items) {
+  // Set parent menu item if none is set yet.
+  if (!isset($items['admin/config/search/facetapi'])) {
+    $items['admin/config/search/facetapi'] = array(
+      'title' => 'Facet API Settings',
+      'description' => 'Configure Facet API.',
+      'access arguments' => array('administer facets'),
+    ) + $items['admin/config/search/facetapi/views'];
+    unset($items['admin/config/search/facetapi']['type']);
+  }
+}
+
+/**
+ * Facet API Views settings form.
+ */
+function facetapi_views_settings_form($form, &$form_state) {
+  $form['facetapi_views_url_processor_for_all_searchers'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Use views exposed filter facet format for all searchers'),
+    '#default_value' => variable_get('facetapi_views_url_processor_for_all_searchers', TRUE),
+    '#description' => t('If enabled all searchers will use the facet format which is compatible with the views exposed filters.'),
+  );
+  $searchers = array();
+  foreach (facetapi_get_searcher_info() as $name => $settings) {
+    $searchers[$name] = $name;
+  }
+  $form['facetapi_views_url_processor_searchers'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Enable views facet format for following searchers'),
+    '#default_value' => variable_get('facetapi_views_url_processor_searchers', array()),
+    '#options' => $searchers,
+    '#description' => t("Define which of the availabel searchers have to use the facet format which is compatible with the views exposed filters."),
+    '#states' => array(
+      'invisible' => array(
+        ':input[name="facetapi_views_url_processor_for_all_searchers"]' => array('checked' => TRUE),
+      ),
+    ),
+  );
+  $form = system_settings_form($form);
+  return $form;
+}
diff --git a/contrib/views/plugins/facetapi/url_processor_exposed_facets.inc b/contrib/views/plugins/facetapi/url_processor_exposed_facets.inc
new file mode 100644
index 0000000..01a0860
--- /dev/null
+++ b/contrib/views/plugins/facetapi/url_processor_exposed_facets.inc
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * @file
+ * A custom URL processor which works with Views exposed filters.
+ */
+
+/**
+ * Extension of FacetapiUrlProcessor.
+ */
+class FacetapiUrlProcessorExposedFacets extends FacetapiUrlProcessorStandard {
+  /**
+   * Implements FacetapiUrlProcessor::fetchParams().
+   *
+   * Use $_GET as the source for facet data.
+   */
+  public function fetchParams() {
+    $params = array();
+    $filter_key = $this->filterKey;
+    $enabled_facets = $this->adapter->getEnabledFacets();
+    // Rewriting facet's format with only underscores which matches Views
+    // exposed filters formatting.
+    foreach ($enabled_facets as $facetapi_alias => $array_values) {
+      $enabled_facets[str_replace(':', '_', $facetapi_alias)]['field type'] = $enabled_facets[$facetapi_alias]['field type'];
+      // Saving original facetapi alias to use when returning parameters for
+      // facetapi.
+      $enabled_facets[str_replace(':', '_', $facetapi_alias)]['facetapi alias'] = $facetapi_alias;
+    }
+
+    foreach ($_GET as $filter_alias => $filter_values) {
+      if (is_array($filter_values)) {
+        foreach ($filter_values as $pos => $value) {
+          // If the field type for the facet is taxonomy term, then handle it
+          // differently.
+          if (isset($enabled_facets[$filter_alias]) && $enabled_facets[$filter_alias]['field type'] == 'taxonomy_term' && !strpos($value, "!")) {
+            $params[$filter_key][$pos] = rawurlencode($enabled_facets[$filter_alias]['facetapi alias']) . ':' . $value;
+          }
+          else {
+            // Saving parameters as they are when no need to make them match
+            // with Views exposed filters.
+            $params[$filter_key][$pos] = $value;
+          }
+        }
+      }
+      else {
+        $params[$filter_alias] = $filter_values;
+      }
+    }
+    return $params;
+  }
+
+  /**
+   * Implements FacetapiUrlProcessor::getQueryString().
+   */
+  public function getQueryString(array $facet, array $values, $active) {
+    $qstring = $this->params;
+    $active_items = $this->adapter->getActiveItems($facet);
+
+    // Appends to qstring if inactive, removes if active.
+    foreach ($values as $value) {
+      if ($active && isset($active_items[$value])) {
+        unset($qstring[$this->filterKey][$active_items[$value]['pos']]);
+      }
+      elseif (!$active) {
+        $field_alias = rawurlencode($facet['field alias']);
+        $qstring[$this->filterKey][] = $field_alias . ':' . $value;
+      }
+    }
+
+    // Removes duplicates, resets array keys and returns query string.
+    // @see http://drupal.org/node/1340528
+    $qstring[$this->filterKey] = array_values(array_unique($qstring[$this->filterKey]));
+
+    // We need to rewrite the query in the format which Views exposed filters
+    // use.
+    $enabled_facets = $this->adapter->getEnabledFacets();
+    $query = array();
+
+    foreach ($qstring[$this->filterKey] as $pos => $filter_value) {
+      // Inverted explode, field alias can have multiple colons,
+      // but the last one is always value.
+      $parts = array_map('strrev', explode(':', strrev($filter_value), 2));
+
+      // Checking if the facet's field type is taxonomy term and making sure
+      // it's not a facet for missing values (with a value of "!") and rewriting
+      // the output in views exposed filters structure.
+      if (isset($enabled_facets[rawurldecode($parts[1])]) && $enabled_facets[rawurldecode($parts[1])]['field type'] == 'taxonomy_term' && $parts[0] != '!') {
+        // Removing the query part with filterKey.
+        unset($qstring[$this->filterKey][$pos]);
+        // Rewriting facet URL using only underscores like Views exposed filters
+        // do.
+        $parts[1] = rawurldecode($parts[1]);
+        $parts[1] = str_replace(':', '_', $parts[1]);
+        $qstring[$parts[1]][$pos] = $parts[0];
+      }
+      else {
+        $qstring[$this->filterKey][$pos] = $filter_value;
+      }
+    }
+    return $qstring;
+  }
+}
diff --git a/contrib/views/views/facetapi_views.views.inc b/contrib/views/views/facetapi_views.views.inc
new file mode 100644
index 0000000..5069f65
--- /dev/null
+++ b/contrib/views/views/facetapi_views.views.inc
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @file
+ * Provide Views handlers for facetapi.
+ */
+
+/**
+ * Implements hook_views_data().
+ */
+function facetapi_views_views_data() {
+  $data['facetapi']['table']['group'] = t('Facet API');
+  $data['facetapi']['table']['join'] = array(
+    // #global is a special flag which let's a table appear all the time.
+    '#global' => array(),
+  );
+  $data['facetapi']['keep_facet_values'] = array(
+    'title' => t('Keep facets'),
+    'help' => t('Keeps the selected facets when updating the exposed filter.'),
+    'filter' => array(
+      'handler' => 'facetapi_views_handler_filter_keep_facet_values',
+    ),
+  );
+  return $data;
+}
diff --git a/contrib/views/views/facetapi_views_handler_filter_keep_facet_values.inc b/contrib/views/views/facetapi_views_handler_filter_keep_facet_values.inc
new file mode 100644
index 0000000..e54e90b
--- /dev/null
+++ b/contrib/views/views/facetapi_views_handler_filter_keep_facet_values.inc
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * @file
+ * Facet API views integration - filter to keep the set facets.
+ */
+
+/**
+ * Filter to keep the set facets.
+ *
+ * @ingroup views_filter_handlers
+ */
+class facetapi_views_handler_filter_keep_facet_values extends views_handler_filter {
+
+  /**
+   * Remove expose option from options form.
+   */
+  public function options_form(&$form, &$form_state) {
+    parent::options_form($form, $form_state);
+    unset($form['expose_button']);
+  }
+
+  /**
+   * Has no summary.
+   */
+  public function admin_summary() {
+    return '';
+  }
+
+  /**
+   * Always exposed.
+   */
+  public function can_expose() {
+    return TRUE;
+  }
+
+  /**
+   * Always expose.
+   */
+  public function is_exposed() {
+    return TRUE;
+  }
+
+  /**
+   * Ensure we don't modify the query.
+   */
+  public function query() {}
+
+  /**
+   * No need for output here.
+   */
+  public function render($empty = FALSE) {}
+
+  /**
+   * Placeholder to use for the form output.
+   *
+   * @return string
+   *   Unique placeholder to be able to inject the facet fields.
+   */
+  public function getFormPlaceholder() {
+    return '<!--facetapi_keep_facets_placeholder:' . $this->view->name . ':' . $this->view->current_display . '-->';
+  }
+
+  /**
+   * Inject the facets into the exposed form.
+   *
+   * With the query run we've active searchers and we can access the facet
+   * parameters of them.
+   *
+   * @see facetapi_get_active_searchers()
+   */
+  public function post_execute(&$values) {
+    // Iterate over active searchers and collect the facet values.
+    $facets = array();
+    foreach (facetapi_get_active_searchers() as $searcher) {
+      $adapter = facetapi_adapter_load($searcher);
+      $url_processor = $adapter->getUrlProcessor();
+      $filter_key = $url_processor->getFilterKey();
+      $params = $url_processor->getParams();
+      if (isset($params[$filter_key])) {
+        foreach ($params[$filter_key] as $index => $value) {
+          $facets[$filter_key][$index] = array(
+            '#type' => 'hidden',
+            '#value' => $value,
+            '#name' => $filter_key . '[' . $index . ']',
+          );
+        }
+      }
+    }
+
+    // Inject the hidden fields into the exposed widget output.
+    $this->view->exposed_widgets = str_replace($this->getFormPlaceholder(), drupal_render($facets), $this->view->exposed_widgets);
+    return parent::post_execute($values);
+  }
+
+  /**
+   * This doesn't output the facet fields but a placeholder for later injection.
+   *
+   * We can't output the hidden fields here because at that point it's not sure
+   * that facetapi_get_active_searchers() will provide the necessary
+   * information. This due the fact that the exposed form handling takes place
+   * before the views query is run. And only with the query run we might get the
+   * searcher related to this view.
+   *
+   * @see facetapi_get_active_searchers()
+   */
+  public function exposed_form(&$form, &$form_state) {
+    $form['facetapi_keep_facets_placeholder'][] = array(
+      '#type' => 'markup',
+      '#markup' => $this->getFormPlaceholder(),
+    );
+  }
+
+}
