diff --git a/config/schema/facets.processor.schema.yml b/config/schema/facets.processor.schema.yml
index ebdd249..b380515 100644
--- a/config/schema/facets.processor.schema.yml
+++ b/config/schema/facets.processor.schema.yml
@@ -112,3 +112,11 @@ plugin.plugin_configuration.facets_processor.date_item:
     date_format:
       type: string
       label: 'Date format'
+
+plugin.plugin_configuration.facets_processor.granularity_item:
+  type: mapping
+  label: 'Granular item processor'
+  mapping:
+    granularity:
+      type: integer
+      label: 'Granularity'
diff --git a/facets.install b/facets.install
index df87d28..82a9f6b 100644
--- a/facets.install
+++ b/facets.install
@@ -126,3 +126,26 @@ function facets_update_8004() {
     }
   }
 }
+
+/**
+ * Migrate facets with granular widget to use date processors + links widget.
+ */
+function facets_update_8005() {
+  foreach (Facet::loadMultiple() as $facet) {
+    $widget = $facet->getWidget();
+    if ($widget['type'] === 'numericgranular') {
+      // Set widget to use links instead.
+      $facet->setWidget('links', ['show_numbers' => $widget['config']['show_numbers']]);
+      // Migrate widget to processor settings and enable date_item processor.
+      $settings = [
+        'granularity' => $widget['config']['granularity'],
+      ];
+      $facet->addProcessor([
+        'processor_id' => 'granularity_item',
+        'weights' => ['build' => 35],
+        'settings' => $settings,
+      ]);
+      $facet->save();
+    }
+  }
+}
diff --git a/src/Plugin/facets/widget/NumericGranularWidget.php b/src/Plugin/facets/processor/GranularItemProcessor.php
similarity index 56%
rename from src/Plugin/facets/widget/NumericGranularWidget.php
rename to src/Plugin/facets/processor/GranularItemProcessor.php
index 9490a73..05c590f 100644
--- a/src/Plugin/facets/widget/NumericGranularWidget.php
+++ b/src/Plugin/facets/processor/GranularItemProcessor.php
@@ -1,27 +1,39 @@
 <?php
 
-namespace Drupal\facets\Plugin\facets\widget;
+namespace Drupal\facets\Plugin\facets\processor;
 
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\facets\FacetInterface;
+use Drupal\facets\Processor\BuildProcessorInterface;
+use Drupal\facets\Processor\ProcessorPluginBase;
 
 /**
- * Basic granular widget.
+ * Provides a processor for granularity.
  *
- * @FacetsWidget(
- *   id = "numericgranular",
- *   label = @Translation("Granular numeric list"),
+ * @FacetsProcessor(
+ *   id = "granularity_item",
+ *   label = @Translation("Granularity item processor"),
  *   description = @Translation("List of numbers grouped in steps."),
+ *   stages = {
+ *     "build" = 35
+ *   }
  * )
  */
-class NumericGranularWidget extends LinksWidget {
+class GranularItemProcessor extends ProcessorPluginBase implements BuildProcessorInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function build(FacetInterface $facet, array $results) {
+    return $results;
+  }
 
   /**
    * {@inheritdoc}
    */
   public function defaultConfiguration() {
     return [
-      'granularity' => 0,
+      'granularity' => 1,
     ] + parent::defaultConfiguration();
   }
 
@@ -31,16 +43,14 @@ public function defaultConfiguration() {
   public function buildConfigurationForm(array $form, FormStateInterface $form_state, FacetInterface $facet) {
     $configuration = $this->getConfiguration();
 
-    $form += parent::buildConfigurationForm($form, $form_state, $facet);
-
-    $form['granularity'] = [
+    $build['granularity'] = [
       '#type' => 'number',
       '#title' => $this->t('Granularity'),
       '#default_value' => $configuration['granularity'],
       '#description' => $this->t('The numeric size of the steps to group the result facets in.'),
     ];
 
-    return $form;
+    return $build;
   }
 
   /**
diff --git a/src/Plugin/facets/query_type/SearchApiGranular.php b/src/Plugin/facets/query_type/SearchApiGranular.php
index b41594e..9eed200 100644
--- a/src/Plugin/facets/query_type/SearchApiGranular.php
+++ b/src/Plugin/facets/query_type/SearchApiGranular.php
@@ -42,11 +42,11 @@ public function calculateResultFilter($value) {
    *
    * Default behaviour an integer for the steps that the facet works in.
    *
-   * @return mixed
+   * @return int
    *   If not an integer the inheriting class needs to deal with calculations.
    */
   protected function getGranularity() {
-    return $this->facet->getWidgetInstance()->getConfiguration()['granularity'];
+    return $this->facet->getProcessors()['granularity_item']->getConfiguration()['granularity'];
   }
 
 }
diff --git a/tests/facets_custom_widget/src/Plugin/facets/widget/WidgetDateQT.php b/tests/facets_custom_widget/src/Plugin/facets/widget/WidgetDateQT.php
new file mode 100644
index 0000000..c9e50a4
--- /dev/null
+++ b/tests/facets_custom_widget/src/Plugin/facets/widget/WidgetDateQT.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Drupal\facets_custom_widget\Plugin\facets\widget;
+
+use Drupal\facets\Widget\WidgetPluginBase;
+
+/**
+ * Test widget.
+ *
+ * @FacetsWidget(
+ *   id = "widget_date_qt",
+ *   label = @Translation("Widget with date query type"),
+ *   description = @Translation("Widget with date query type"),
+ * )
+ */
+class WidgetDateQT extends WidgetPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQueryType() {
+    return 'date';
+  }
+
+}
diff --git a/tests/src/Functional/ProcessorIntegrationTest.php b/tests/src/Functional/ProcessorIntegrationTest.php
index 0027fe2..7afe74c 100644
--- a/tests/src/Functional/ProcessorIntegrationTest.php
+++ b/tests/src/Functional/ProcessorIntegrationTest.php
@@ -201,6 +201,96 @@ public function testBooleanProcessorIntegration() {
     $this->assertFacetLabel('Øn');
   }
 
+  /**
+   * Tests the for configuration of granularity processor.
+   */
+  public function testNumericGranularity() {
+    $field_name = 'field_integer';
+    $field_storage = FieldStorageConfig::create([
+      'field_name' => $field_name,
+      'entity_type' => 'entity_test_mulrev_changed',
+      'type' => 'integer',
+    ]);
+    $field_storage->save();
+    $field = FieldConfig::create([
+      'field_storage' => $field_storage,
+      'bundle' => 'item',
+    ]);
+    $field->save();
+    $field = FieldConfig::create([
+      'field_storage' => $field_storage,
+      'bundle' => 'article',
+    ]);
+    $field->save();
+
+    $index = $this->getIndex();
+
+    // Index the taxonomy and entity reference fields.
+    $integerField = new Field($index, $field_name);
+    $integerField->setType('integer');
+    $integerField->setPropertyPath($field_name);
+    $integerField->setDatasourceId('entity:entity_test_mulrev_changed');
+    $integerField->setLabel('IntegerField');
+    $index->addField($integerField);
+
+    $index->save();
+    $this->indexItems($this->indexId);
+
+    $entity_test_storage = \Drupal::entityTypeManager()
+      ->getStorage('entity_test_mulrev_changed');
+
+    foreach ([30, 35, 40, 100] as $val) {
+      $entity_test_storage->create([
+        'name' => 'foo bar baz',
+        'body' => 'test test int',
+        'type' => 'item',
+        'keywords' => ['orange'],
+        'category' => 'item_category',
+        $field_name => $val,
+      ])->save();
+    }
+
+    $this->indexItems($this->indexId);
+
+    $facet_id = "integer";
+
+    // Create facet.
+    $this->editForm = 'admin/config/search/facets/' . $facet_id . '/edit';
+    $this->createFacet("Integer", $facet_id, $field_name);
+
+    // Check values.
+    $this->drupalGet('search-api-test-fulltext');
+    $this->assertFacetLabel('100');
+    $this->assertFacetLabel('30');
+    $this->assertFacetLabel('35');
+    $this->assertFacetLabel('40');
+
+    $form = [
+      'facet_settings[granularity_item][status]' => TRUE,
+    ];
+    $this->drupalPostForm($this->editForm, $form, 'Save');
+
+    // Check values.
+    $this->drupalGet('search-api-test-fulltext');
+    $this->assertFacetLabel('30 (1)');
+    $this->assertFacetLabel('35');
+    $this->assertFacetLabel('40');
+    $this->assertFacetLabel('100');
+
+    $form = [
+      'facet_settings[granularity_item][status]' => TRUE,
+      'facet_settings[granularity_item][settings][granularity]' => 10,
+    ];
+    $this->drupalPostForm($this->editForm, $form, 'Save');
+
+    // Check values.
+    $this->drupalGet('search-api-test-fulltext');
+    $this->assertFacetLabel('30 (2)');
+    $this->assertEmpty($this->findFacetLink('35'));
+    $this->assertFacetLabel('40');
+    $this->assertFacetLabel('100');
+  }
+
   /**
    * Tests the for sorting processors in the frontend with a 'keywords' facet.
    */
diff --git a/tests/src/Kernel/Entity/FacetFacetSourceTest.php b/tests/src/Kernel/Entity/FacetFacetSourceTest.php
index d3a1a9d..9d6e81e 100644
--- a/tests/src/Kernel/Entity/FacetFacetSourceTest.php
+++ b/tests/src/Kernel/Entity/FacetFacetSourceTest.php
@@ -178,7 +178,7 @@ public function testQueryTypeJugglingInvalidProcessor() {
    */
   public function testQueryTypeJugglingInvalidCombo() {
     $entity = new Facet([], 'facets_facet');
-    $entity->setWidget('numericgranular');
+    $entity->setWidget('widget_date_qt');
     $entity->setFacetSourceId('search_api:views_page__search_api_test_view__page_1');
     $entity->setFieldIdentifier('name');
     $processor = [
diff --git a/tests/src/Unit/Plugin/query_type/SearchApiGranularTest.php b/tests/src/Unit/Plugin/query_type/SearchApiGranularTest.php
index b9194f0..717b3e5 100644
--- a/tests/src/Unit/Plugin/query_type/SearchApiGranularTest.php
+++ b/tests/src/Unit/Plugin/query_type/SearchApiGranularTest.php
@@ -2,9 +2,12 @@
 
 namespace Drupal\Tests\facets\Unit\Plugin\query_type;
 
+use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\facets\Entity\Facet;
 use Drupal\facets\FacetInterface;
+use Drupal\facets\Plugin\facets\processor\GranularItemProcessor;
 use Drupal\facets\Plugin\facets\query_type\SearchApiGranular;
+use Drupal\facets\Processor\ProcessorPluginManager;
 use Drupal\search_api\Backend\BackendInterface;
 use Drupal\search_api\IndexInterface;
 use Drupal\facets\Result\ResultInterface;
@@ -12,6 +15,7 @@
 use Drupal\search_api\Plugin\views\query\SearchApiQuery;
 use Drupal\search_api\ServerInterface;
 use Drupal\Tests\UnitTestCase;
+use Prophecy\Argument;
 
 /**
  * Unit test for granular query type.
@@ -20,6 +24,32 @@
  */
 class SearchApiGranularTest extends UnitTestCase {
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    $processor_id = 'granularity_item';
+    $processor_definitions = [
+      $processor_id => [
+        'id' => $processor_id,
+        'class' => GranularItemProcessor::class,
+      ],
+    ];
+
+    $granularityProcessor = new GranularItemProcessor([], 'granularity_item', []);
+
+    $processor_manager = $this->prophesize(ProcessorPluginManager::class);
+    $processor_manager->getDefinitions()->willReturn($processor_definitions);
+    $processor_manager->createInstance('granularity_item', Argument::any())
+      ->willReturn($granularityProcessor);
+
+    $container = new ContainerBuilder();
+    $container->set('plugin.manager.facets.processor', $processor_manager->reveal());
+    \Drupal::setContainer($container);
+  }
+
   /**
    * Tests string query type without executing the query with an "AND" operator.
    */
@@ -37,14 +67,11 @@ public function testQueryTypeAnd() {
       ['query_operator' => 'AND', 'widget' => 'links'],
       'facets_facet'
     );
-    $facetReflection = new \ReflectionClass(Facet::class);
-    $widget = $this->getMockBuilder(WidgetPluginInterface::class)
-      ->disableOriginalConstructor()
-      ->getMock();
-    $widget->method('getConfiguration')->will($this->returnValue(['granularity' => 10]));
-    $widget_instance = $facetReflection->getProperty('widgetInstance');
-    $widget_instance->setAccessible(TRUE);
-    $widget_instance->setValue($facet, $widget);
+    $facet->addProcessor([
+      'processor_id' => 'granularity_item',
+      'weights' => [],
+      'settings' => ['granularity' => 10],
+    ]);
 
     // Results for the widget.
     $original_results = [
diff --git a/tests/src/Unit/Plugin/widget/NumericGranularWidgetTest.php b/tests/src/Unit/Plugin/widget/NumericGranularWidgetTest.php
deleted file mode 100644
index 03b4fe0..0000000
--- a/tests/src/Unit/Plugin/widget/NumericGranularWidgetTest.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-namespace Drupal\Tests\facets\Unit\Plugin\widget;
-
-use Drupal\facets\Plugin\facets\widget\NumericGranularWidget;
-
-/**
- * Unit test for widget.
- *
- * @group facets
- */
-class NumericGranularWidgetTest extends WidgetTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setUp() {
-    parent::setUp();
-    $this->widget = new NumericGranularWidget();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function testGetQueryType() {
-    $result = $this->widget->getQueryType($this->queryTypes);
-    $this->assertEquals('numeric', $result);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function testDefaultConfiguration() {
-    $default_config = $this->widget->defaultConfiguration();
-    $expected = [
-      'show_numbers' => FALSE,
-      'soft_limit' => 0,
-      'granularity' => 0,
-      'soft_limit_settings' => [
-        'show_less_label' => 'Show less',
-        'show_more_label' => 'Show more',
-      ],
-    ];
-    $this->assertEquals($expected, $default_config);
-  }
-
-}
