diff --git a/Civi/DataProcessor/Factory.php b/Civi/DataProcessor/Factory.php
index d7a7eb543293d9843f31ba3d34de866ecd01c19d..24224c87cca101906e282d9562d85c6a2cdf6682 100644
--- a/Civi/DataProcessor/Factory.php
+++ b/Civi/DataProcessor/Factory.php
@@ -126,6 +126,7 @@ class Factory {
     $this->addOutput('participant_search', 'CRM_DataprocessorSearch_ParticipantSearch', E::ts('Participant Search'));
     $this->addOutput('export_csv', 'CRM_DataprocessorOutputExport_CSV', E::ts('CSV Export'));
     $this->addFilter('simple_sql_filter', 'Civi\DataProcessor\FilterHandler\SimpleSqlFilter', E::ts('Field filter'));
+    $this->addFilter('activity_filter', 'Civi\DataProcessor\FilterHandler\ActivityFilter', E::ts('Activity filter'));
     $this->addFilter('contact_filter', 'Civi\DataProcessor\FilterHandler\ContactFilter', E::ts('Contact filter'));
     $this->addFilter('contact_in_group_filter', 'Civi\DataProcessor\FilterHandler\ContactInGroupFilter', E::ts('Contact in Group filter'));
     $this->addFilter('case_role_filter', 'Civi\DataProcessor\FilterHandler\CaseRoleFilter', E::ts('Case Role filter'));
diff --git a/Civi/DataProcessor/FilterHandler/ActivityFilter.php b/Civi/DataProcessor/FilterHandler/ActivityFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..fa58ad51efa039270c86dfada23c2527b67ae6c7
--- /dev/null
+++ b/Civi/DataProcessor/FilterHandler/ActivityFilter.php
@@ -0,0 +1,194 @@
+<?php
+/**
+ * @author Jaap Jansma <jaap.jansma@civicoop.org>
+ * @license AGPL-3.0
+ */
+
+namespace Civi\DataProcessor\FilterHandler;
+
+use Civi\DataProcessor\Exception\InvalidConfigurationException;
+use CRM_Dataprocessor_ExtensionUtil as E;
+
+class ActivityFilter extends AbstractFieldFilterHandler {
+
+  /**
+   * @var array
+   *   Filter configuration
+   */
+  protected $configuration;
+
+  public function __construct() {
+    parent::__construct();
+  }
+
+  /**
+   * Initialize the filter
+   *
+   * @throws \Civi\DataProcessor\Exception\DataSourceNotFoundException
+   * @throws \Civi\DataProcessor\Exception\InvalidConfigurationException
+   * @throws \Civi\DataProcessor\Exception\FieldNotFoundException
+   */
+  protected function doInitialization() {
+    if (!isset($this->configuration['datasource']) || !isset($this->configuration['field'])) {
+      throw new InvalidConfigurationException(E::ts("Filter %1 requires a field to filter on. None given.", array(1=>$this->title)));
+    }
+    $this->initializeField($this->configuration['datasource'], $this->configuration['field']);
+  }
+
+  /**
+   * Returns true when this filter has additional configuration
+   *
+   * @return bool
+   */
+  public function hasConfiguration() {
+    return true;
+  }
+
+  /**
+   * When this filter type has additional configuration you can add
+   * the fields on the form with this function.
+   *
+   * @param \CRM_Core_Form $form
+   * @param array $filter
+   */
+  public function buildConfigurationForm(\CRM_Core_Form $form, $filter=array()) {
+    $fieldSelect = \CRM_Dataprocessor_Utils_DataSourceFields::getAvailableFilterFieldsInDataSources($filter['data_processor_id']);
+
+    $form->add('select', 'field', E::ts('Contact ID Field'), $fieldSelect, true, array(
+      'style' => 'min-width:250px',
+      'class' => 'crm-select2 huge data-processor-field-for-name',
+      'placeholder' => E::ts('- select -'),
+    ));
+
+    $optionValueApi = civicrm_api3('OptionValue', 'get', array('option_group_id' => "activity_type", 'options' => array('limit' => 0)));
+
+    $activityType = array();
+    foreach($optionValueApi['values'] as $option) {
+      $activityType[$option['id']] = $option['label'];
+    }
+
+    $form->add('select', 'limit_activity_types', E::ts('Limit to Contacts of activity types'), $activityType, false, array(
+      'style' => 'min-width:250px',
+      'class' => 'crm-select2 huge',
+      'placeholder' => E::ts('- Show all activity types -'),
+      'multiple' => true,
+    ));
+
+    if (isset($filter['configuration'])) {
+      $configuration = $filter['configuration'];
+      $defaults = array();
+      if (isset($configuration['field']) && isset($configuration['datasource'])) {
+        $defaults['field'] = $configuration['datasource'] . '::' . $configuration['field'];
+      }
+      if (isset($configuration['limit_activity_types'])) {
+        $defaults['limit_activity_types'] = $configuration['limit_activity_types'];
+      }
+      $form->setDefaults($defaults);
+    }
+  }
+
+  /**
+   * When this filter type has configuration specify the template file name
+   * for the configuration form.
+   *
+   * @return false|string
+   */
+  public function getConfigurationTemplateFileName() {
+    return "CRM/Dataprocessor/Form/Filter/Configuration/ActivityFilter.tpl";
+  }
+
+
+  /**
+   * Process the submitted values and create a configuration array
+   *
+   * @param $submittedValues
+   * @return array
+   */
+  public function processConfiguration($submittedValues) {
+    list($datasource, $field) = explode('::', $submittedValues['field'], 2);
+    $configuration['field'] = $field;
+    $configuration['datasource'] = $datasource;
+    $configuration['limit_activity_types'] = isset($submittedValues['limit_activity_types']) ? $submittedValues['limit_activity_types'] : false;
+    return $configuration;
+  }
+
+  /**
+   * Add the elements to the filter form.
+   *
+   * @param \CRM_Core_Form $form
+   * @param array $defaultFilterValue
+   * @return array
+   *   Return variables belonging to this filter.
+   */
+  public function addToFilterForm(\CRM_Core_Form $form, $defaultFilterValue) {
+    $fieldSpec = $this->getFieldSpecification();
+    $operations = $this->getOperatorOptions($fieldSpec);
+    $defaults = array();
+
+    $title = $fieldSpec->title;
+    $alias = $fieldSpec->alias;
+    if ($this->isRequired()) {
+      $title .= ' <span class="crm-marker">*</span>';
+    }
+
+    $form->addElement('select', "{$alias}_op", E::ts('Operator:'), $operations);
+
+    $props = array(
+      'placeholder' => E::ts('Select a Contact'),
+      'entity' => 'Contact',
+      'create' => false,
+      'multiple' => true,
+    );
+    if (!empty($this->configuration['limit_activity_types'])) {
+      $optionValueApi = civicrm_api3('OptionValue', 'get', array('option_group_id' => "activity_type", 'options' => array('limit' => 0)));
+
+      $activityType = array();
+      foreach($optionValueApi['values'] as $option) {
+        $activityType[$option['id']] = $option['label'];
+      }
+      $param_activity_type = array();
+
+      foreach($this->configuration['limit_activity_types'] as $type_id){
+        array_push($param_activity_type, $activityType[$type_id]);
+      }
+
+      $result = civicrm_api3('ActivityContact', 'get', [
+        'activity_id.activity_type_id'  => ['IN' => $param_activity_type],
+        'options' => ['limit' => 0],
+      ]);
+
+      $contact_id_list = array();
+      foreach ($result['values'] as $contact) {
+        array_push($contact_id_list, $contact['contact_id']);
+      }
+      $contact_id_list = array_values(array_unique($contact_id_list));
+      $props['api'] = ['params' => ['contact_id' => ['IN' => $contact_id_list]]];
+    }
+    $props['select'] = ['minimumInputLength' => 0];
+    $form->addEntityRef( "{$alias}_value", '', $props);
+    if (isset($defaultFilterValue['op'])) {
+      $defaults[$alias . '_op'] = $defaultFilterValue['op'];
+    }
+    if (isset($defaultFilterValue['value'])) {
+      $defaults[$alias.'_value'] = $defaultFilterValue['value'];
+    }
+    if (count($defaults)) {
+      $form->setDefaults($defaults);
+    }
+
+    $filter['type'] = $fieldSpec->type;
+    $filter['title'] = $title;
+
+    return $filter;
+  }
+
+  protected function getOperatorOptions(\Civi\DataProcessor\DataSpecification\FieldSpecification $fieldSpec) {
+    return array(
+      'IN' => E::ts('Is one of'),
+      'NOT IN' => E::ts('Is not one of'),
+      'null' => E::ts('Is empty'),
+    );
+  }
+
+
+}
\ No newline at end of file
diff --git a/templates/CRM/Dataprocessor/Form/Filter/Configuration/ActivityFilter.tpl b/templates/CRM/Dataprocessor/Form/Filter/Configuration/ActivityFilter.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..ca3dc1cc0df6996c7bdd5faea2bde7b139764225
--- /dev/null
+++ b/templates/CRM/Dataprocessor/Form/Filter/Configuration/ActivityFilter.tpl
@@ -0,0 +1,12 @@
+{crmScope extensionKey='dataprocessor'}
+<div class="crm-section">
+    <div class="label">{$form.field.label}</div>
+    <div class="content">{$form.field.html}</div>
+    <div class="clear"></div>
+</div>
+<div class="crm-section">
+    <div class="label">{$form.limit_activity_types.label}</div>
+    <div class="content">{$form.limit_activity_types.html}</div>
+    <div class="clear"></div>
+</div>
+{/crmScope}
\ No newline at end of file