diff --git a/js/checkbox-widget-3.js b/js/checkbox-widget-3.js
index e0c2d3e76596e70a8134855a475b06da7f9e8373..a9ead16b55015067ca749c02f2d019569134dfbf 100644
--- a/js/checkbox-widget-3.js
+++ b/js/checkbox-widget-3.js
@@ -20,7 +20,7 @@
       if ($checkboxWidgets.length > 0) {
         $checkboxWidgets.each(function (index, widget) {
           var $widget = $(widget);
-          var $widgetLinks = $widget.find('.facet-item > a', 'facet-item > span.drupal-masked-element');
+          var $widgetLinks = $widget.find('.facet-item > a, facet-item > span.drupal-masked-element');
           $widgetLinks.each(Drupal.facets.updateCheckbox);
         });
       }
@@ -37,7 +37,7 @@
     if ($checkboxWidgets.length > 0) {
       $checkboxWidgets.each(function (index, widget) {
         var $widget = $(widget);
-        var $widgetLinks = $widget.find('.facet-item > a', 'facet-item > span.drupal-masked-element');
+        var $widgetLinks = $widget.find('.facet-item > a, facet-item > span.drupal-masked-element');
 
         // Add correct CSS selector for the widget. The Facets JS API will
         // register handlers on that element.
diff --git a/js/checkbox-widget.js b/js/checkbox-widget.js
index 5b3d36beed953adba004c2bb7321c96f679abc37..ccc0d44093ed1b9c1bd54fdb4e22567dfb003d12 100644
--- a/js/checkbox-widget.js
+++ b/js/checkbox-widget.js
@@ -20,7 +20,7 @@
       if ($checkboxWidgets.length > 0) {
         $checkboxWidgets.each(function (index, widget) {
           var $widget = $(widget);
-          var $widgetLinks = $widget.find('.facet-item > a', 'facet-item > span.drupal-masked-element');
+          var $widgetLinks = $widget.find('.facet-item > a, .facet-item > span.drupal-masked-element');
           $widgetLinks.each(Drupal.facets.updateCheckbox);
         });
       }
@@ -37,7 +37,7 @@
     if ($checkboxWidgets.length > 0) {
       $checkboxWidgets.each(function (index, widget) {
         var $widget = $(widget);
-        var $widgetLinks = $widget.find('.facet-item > a', 'facet-item > span.drupal-masked-element');
+        var $widgetLinks = $widget.find('.facet-item > a, .facet-item > span.drupal-masked-element');
 
         // Add correct CSS selector for the widget. The Facets JS API will
         // register handlers on that element.
@@ -79,7 +79,19 @@
       var $widget = $(this).closest('.js-facets-widget');
 
       Drupal.facets.disableFacet($widget);
-      $widget.trigger('facets_filter', [ href ]);
+      if (!href) {
+        var checked = $(this).is(':checked');
+        if (checked) {
+          $link.addClass('is-active');
+        }
+        else {
+          $link.removeClass('is-active');
+        }
+        $link.trigger('click');
+      }
+      else {
+        $widget.trigger('facets_filter', [ href ]);
+      }
     });
 
     if (active) {
diff --git a/js/dropdown-widget.js b/js/dropdown-widget.js
new file mode 100644
index 0000000000000000000000000000000000000000..e7f94cde9e0762223feb55721c6e805f4e36a65f
--- /dev/null
+++ b/js/dropdown-widget.js
@@ -0,0 +1,125 @@
+/**
+ * @file
+ * Transforms links into a dropdown list.
+ */
+
+(function ($, Drupal, once) {
+
+  'use strict';
+
+  Drupal.facets = Drupal.facets || {};
+  Drupal.behaviors.facetsDropdownWidget = {
+    attach: function (context, settings) {
+      Drupal.facets.makeDropdown(context, settings);
+    }
+  };
+
+  /**
+   * Turns all facet links into a dropdown with options for every link.
+   *
+   * @param {object} context
+   *   Context.
+   * @param {object} settings
+   *   Settings.
+   */
+  Drupal.facets.makeDropdown = function (context, settings) {
+    // Find all dropdown facet links and turn them into an option.
+    $(once('facets-dropdown-transform', '.js-facets-dropdown-links')).each(function () {
+      var $ul = $(this);
+      var $links = $ul.find('.facet-item a, .facet-item span.drupal-masked-element');
+      var $dropdown = $('<select></select>');
+      // Preserve all attributes of the list.
+      $ul.each(function () {
+        $.each(this.attributes,function (idx, elem) {
+            $dropdown.attr(elem.name, elem.value);
+        });
+      });
+      // Remove the class which we are using for .once().
+      $dropdown.removeClass('js-facets-dropdown-links');
+
+      $dropdown.addClass('facets-dropdown');
+      $dropdown.addClass('js-facets-widget');
+      $dropdown.addClass('js-facets-dropdown');
+
+      var id = $(this).data('drupal-facet-id');
+      // Add aria-labelledby attribute to reference label.
+      $dropdown.attr('aria-labelledby', "facet_" + id + "_label");
+      var default_option_label = settings.facets.dropdown_widget[id]['facet-default-option-label'];
+
+      // Add empty text option first.
+      var $default_option = $('<option></option>')
+        .attr('value', '')
+        .text(default_option_label);
+      $dropdown.append($default_option);
+
+      $ul.prepend('<li class="default-option"><a href="' + window.location.href.split('?')[0] + '">' + Drupal.checkPlain(default_option_label) + '</a></li>');
+
+      var has_active = false;
+      $links.each(function () {
+        var $link = $(this);
+        var active = $link.hasClass('is-active');
+        if ($link.attr('href')){
+          var $option = $('<option></option>')
+            .attr('value', $link.attr('href'))
+            .data($link.data());
+        }
+        else {
+          var $option = $('<option></option>')
+            .attr('value', $link.data('drupalFacetItemValue'))
+            .data($link.data());
+          // take all data-x attributes from the link and add them to the option
+
+          $.each($link[0].attributes, function () {
+            if (this.name.startsWith('data-')) {
+              $option.attr(this.name, this.value);
+            }
+          });
+          $option.addClass('drupal-masked-element');
+        }
+        if (active) {
+          has_active = true;
+          // Set empty text value to this link to unselect facet.
+          $default_option.attr('value', $link.attr('href'));
+          $ul.find('.default-option a, .default-option span').attr("href", $link.attr('href'));
+          $option.attr('selected', 'selected');
+          $link.find('.js-facet-deactivate').remove();
+        }
+        $option.text(function () {
+          // Add hierarchy indicator in case hierarchy is enabled.
+          var $parents = $link.parent('li.facet-item').parents('li.facet-item');
+          var prefix = '';
+          for (var i = 0; i < $parents.length; i++) {
+            prefix += '-';
+          }
+          return prefix + ' ' + $link.text().trim();
+        });
+        $dropdown.append($option);
+      });
+
+      // Go to the selected option when it's clicked.
+      $dropdown.on('change.facets', function () {
+        var anchor = $($ul).find("[data-drupal-facet-item-id='" + $(this).find(':selected').data('drupalFacetItemId') + "']");
+        var $linkElement = (anchor.length > 0) ? $(anchor) : $ul.find('.default-option a');
+
+        if ($linkElement.hasClass('drupal-masked-element')) {
+          $linkElement.trigger('click');
+        }
+        else {
+          var url = $linkElement.attr('href');
+
+          $(this).trigger('facets_filter', [ url ]);
+        }
+      });
+
+      // Append empty text option.
+      if (!has_active) {
+        $default_option.attr('selected', 'selected');
+      }
+
+      // Replace links with dropdown.
+      $ul.after($dropdown).hide();
+      Drupal.attachBehaviors($dropdown.parent()[0], Drupal.settings);
+    });
+  };
+
+})(jQuery, Drupal, once);
diff --git a/link_obfuscation.api.php b/link_obfuscation.api.php
new file mode 100644
index 0000000000000000000000000000000000000000..9df6a755c9484f94d4444cf2679258e94f9a41f2
--- /dev/null
+++ b/link_obfuscation.api.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Api documentation for link_obfuscation module.
+ */
+
+/**
+ * Alter results from $build['content']['#links'] for custom blocks.
+ *
+ * Here, we assign to the $items variable a reference to where the links for
+ * the language dropdown are stored. This is done so that we can modify the
+ * links directly.
+ */
+function hook_preprocess_block_items_alter($build, &$items) {
+  if (isset($build['content']['#links'])) {
+    $items = [];
+    foreach ($build['content']['#links'] as $key => &$link) {
+      $items[$key] = &$link;
+    }
+  }
+}
\ No newline at end of file
diff --git a/link_obfuscation.links.menu.yml b/link_obfuscation.links.menu.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0f9b11c6093a7b574b6df5a3aa8871e138a8db46
--- /dev/null
+++ b/link_obfuscation.links.menu.yml
@@ -0,0 +1,5 @@
+link_obfuscation.settings:
+  title: 'Link obfuscation settings'
+  route_name: link_obfuscation.settings
+  parent: system.admin_config_search
+  weight: 140
\ No newline at end of file
diff --git a/link_obfuscation.module b/link_obfuscation.module
old mode 100644
new mode 100755
index a2232eb0f7e3df5479f96c24430ace8449ba9f49..e283eba096c6223ad747ba95e1df2a9d1ca262cc
--- a/link_obfuscation.module
+++ b/link_obfuscation.module
@@ -5,6 +5,44 @@
  * Contains link_obfuscation.module.
  */
 
+use Drupal\Core\Block\BlockPluginInterface;
+use Drupal\link_obfuscation\BlockObfuscationHelper;
+
+/**
+ * Implements hook_block_view_alter().
+ */
+function link_obfuscation_block_view_alter(array &$build, BlockPluginInterface $block) {
+  $build['#pre_render'][] = [
+    BlockObfuscationHelper::class,
+    'addObfuscationCacheContext',
+  ];
+
+  $build['#pre_render'][] = [
+    BlockObfuscationHelper::class,
+    'obfuscateMenuBlocks',
+  ];
+
+  $build['#pre_render'][] = [
+    BlockObfuscationHelper::class,
+    'obfuscateLanguageSwitcher',
+  ];
+
+  $build['#pre_render'][] = [
+    BlockObfuscationHelper::class,
+    'obfuscateBlockContent',
+  ];
+}
+
+/**
+ * Implements hook_views_post_render().
+ */
+function link_obfuscation_views_post_render($view, array &$output, $cache) {
+  $output['#post_render'][] = [
+    BlockObfuscationHelper::class,
+    'obfuscateView',
+  ];
+}
+
 /**
  * Implements hook_page_attachments_alter().
  */
@@ -24,9 +62,10 @@ function link_obfuscation_library_info_alter(&$libraries, $extension) {
     $replacements = [
       'js/link-widget.js' => $newPath . '/link-widget.js',
       'js/checkbox-widget.js' => $newPath . '/checkbox-widget.js',
+      'js/dropdown-widget.js' => $newPath . '/dropdown-widget.js',
     ];
 
-    foreach (['link-widget', 'checkbox-widget'] as $widget) {
+    foreach (['link-widget', 'checkbox-widget', 'dropdown-widget'] as $widget) {
       $libraryName = 'drupal.facets.' . $widget;
       if (isset($libraries[$libraryName])) {
         $new_js = [];
@@ -43,3 +82,4 @@ function link_obfuscation_library_info_alter(&$libraries, $extension) {
     }
   }
 }
+
diff --git a/link_obfuscation.routing.yml b/link_obfuscation.routing.yml
old mode 100644
new mode 100755
index ef21877a5eb2318fbff5f2055b2b919560da8b67..988b56577a8a03fb04b8cb400b831a1fd2eb6c82
--- a/link_obfuscation.routing.yml
+++ b/link_obfuscation.routing.yml
@@ -5,3 +5,11 @@ link_obfuscation.url:
   requirements:
     # Allow all access.
     _access: 'TRUE'
+
+link_obfuscation.settings:
+  path: '/admin/config/link-obfuscation/settings'
+  defaults:
+    _form: '\Drupal\link_obfuscation\Form\SettingsForm'
+    _title: 'Link obfuscation settings'
+  requirements:
+    _permission: 'administer site configuration'
\ No newline at end of file
diff --git a/src/BlockObfuscationHelper.php b/src/BlockObfuscationHelper.php
new file mode 100644
index 0000000000000000000000000000000000000000..8ae25f7b9440b718159e0b3b96ffc587c15a9ccf
--- /dev/null
+++ b/src/BlockObfuscationHelper.php
@@ -0,0 +1,273 @@
+<?php
+
+namespace Drupal\link_obfuscation;
+
+use Drupal\Core\Security\TrustedCallbackInterface;
+use Drupal\Core\Url;
+
+/**
+ * Helper static class for block obfuscation.
+ */
+class BlockObfuscationHelper implements TrustedCallbackInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function trustedCallbacks() {
+    return [
+      'obfuscateMenuBlocks',
+      'addObfuscationCacheContext',
+      'obfuscateLanguageSwitcher',
+      'obfuscateBlockContent',
+      'obfuscateView',
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function obfuscateMenuBlocks(array $build): array {
+    $config = \Drupal::configFactory()->get('link_obfuscation.settings');
+
+    $blockIds = $config->get('menu_block_ids');
+    if (empty($blockIds)) {
+      return $build;
+    }
+
+    $blockIds = array_filter(explode("\r\n", $blockIds));
+
+    if (empty($build['#id']) || !in_array($build['#id'], $blockIds)) {
+      return $build;
+    }
+
+    if (empty($build['content']['#items'])) {
+      return $build;
+    }
+
+    $items = &$build['content']['#items'];
+    static::markItemsForObfuscation($items);
+
+    return $build;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function addObfuscationCacheContext(array $build): array {
+    if (empty($build['content']['#items'])) {
+      return $build;
+    }
+
+    $items = &$build['content']['#items'];
+
+    if (static::differentObfuscationStatus($items)) {
+      $build['#cache']['contexts'][] = 'url.path.is_front';
+      $build['#cache']['contexts'][] = 'languages:language_interface';
+    }
+
+    return $build;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function obfuscateLanguageSwitcher(array $build): array {
+    $config = \Drupal::configFactory()->get('link_obfuscation.settings');
+
+    $blockIds = $config->get('language_switcher_block_ids');
+    if (empty($blockIds)) {
+      return $build;
+    }
+
+    $blockIds = explode("\r\n", $blockIds);
+    if (empty($build['#id']) || !in_array($build['#id'], $blockIds)) {
+      return $build;
+    }
+
+    /** @var \Drupal\Core\Path\PathMatcher $pathMatcher */
+    $pathMatcher = \Drupal::service('path.matcher');
+    $isFrontPage = $pathMatcher->isFrontPage();
+
+    /** @var \Drupal\Core\Language\LanguageManager $languageManager */
+    $languageManager = \Drupal::languageManager();
+    $isDefaultLanguage = $languageManager->getCurrentLanguage()->isDefault();
+
+    $obfuscate = FALSE;
+
+    $obfuscateFrontDefaultLanguage = $config->get('obfuscate_language_switcher_on_front_page_default_language');
+    $obfuscateFrontTranslationsLanguage = $config->get('obfuscate_language_switcher_on_front_page_not_default_language');
+    $obfuscateAllPages = $config->get('obfuscate_language_switcher_on_all_pages');
+
+    if ($obfuscateFrontDefaultLanguage && $isFrontPage && $isDefaultLanguage) {
+      $obfuscate = TRUE;
+    }
+
+    if ($obfuscateFrontTranslationsLanguage && $isFrontPage && !$isDefaultLanguage) {
+      $obfuscate = TRUE;
+    }
+
+    if ($obfuscateAllPages && !$isFrontPage) {
+      $obfuscate = TRUE;
+    }
+
+    $build['#cache']['contexts'][] = 'url.path.is_front';
+    $build['#cache']['contexts'][] = 'languages:language_interface';
+
+    if ($obfuscate) {
+      $items = &$build['content']['#links'];
+      \Drupal::moduleHandler()->invokeAll('preprocess_block_items_alter', [$build, &$items]);
+      static::markItemsForObfuscation($items);
+    }
+
+    return $build;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function obfuscateBlockContent(array $build) {
+    $config = \Drupal::configFactory()->get('link_obfuscation.settings');
+
+    $blockIds = $config->get('obfuscate_block_content_body_block_ids');
+    if (empty($blockIds)) {
+      return $build;
+    }
+
+    $blockIds = explode("\r\n", $blockIds);
+    if (empty($build['#id']) || !in_array($build['#id'], $blockIds)) {
+      return $build;
+    }
+
+    $build['#cache']['contexts'][] = 'url.path.is_front';
+
+    if (empty($build['content']['body'][0]['#text'])) {
+      return $build;
+    }
+
+    $obfuscateFront = $config->get('obfuscate_block_content_body_front');
+    $obfuscateAllPages = $config->get('obfuscate_block_content_body_all_pages');
+
+    if (empty($obfuscateFront) && empty($obfuscateAllPages)) {
+      return $build;
+    }
+
+    /** @var \Drupal\Core\Path\PathMatcher $pathMatcher */
+    $pathMatcher = \Drupal::service('path.matcher');
+    $isFrontPage = $pathMatcher->isFrontPage();
+
+    if ($obfuscateFront && !$isFrontPage || $obfuscateAllPages && $isFrontPage) {
+      return $build;
+    }
+
+    /** @var \Drupal\link_obfuscation\Service\ObfuscateLinkService $obfuscateService */
+    $obfuscateService = \Drupal::service('link_obfuscation.service');
+    $obfuscateContent = $obfuscateService->obfuscateHtml($build['content']['body'][0]['#text']);
+
+    $build['content']['body'][0]['#text'] = $obfuscateContent;
+    return $build;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function obfuscateView($output, array $element) {
+    $config = \Drupal::configFactory()->get('link_obfuscation.settings');
+    $viewLines = $config->get('obfuscate_views_view_ids');
+    if (empty($viewLines)) {
+      return $output;
+    }
+    $viewLines = explode("\r\n", $viewLines);
+    $viewLines = array_map(fn($blockId) => explode('|', $blockId), $viewLines);
+
+    $viewIds = array_map(fn($viewLine) => $viewLine[0], $viewLines);
+
+    if (empty($element['#view']->id()) || !in_array($element['#view']->id(), $viewIds)) {
+      return $output;
+    }
+
+    $viewLines = array_filter($viewLines, fn($viewLine) => $viewLine[0] == $element['#view']->id() && $viewLine[1] == $element['#view']->current_display);
+    $viewLines = array_values($viewLines);
+    $obfuscateService = \Drupal::service('link_obfuscation.service');
+    foreach ($viewLines as $viewLine) {
+
+      $viewDisplayId = $viewLine[1];
+      $linkContainer = $viewLine[2];
+
+      if (empty($viewDisplayId) || empty($linkContainer)) {
+        continue;
+      }
+
+      if (empty($element['#view']->current_display) || $element['#view']->current_display != $viewDisplayId) {
+        continue;
+      }
+      $htmlContent = $obfuscateService->obfuscateHtml($output, $linkContainer);
+
+      if (strcmp($htmlContent, $output) == 0) {
+        continue;
+      }
+      $output = $htmlContent;
+    }
+
+    return $output;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static function differentObfuscationStatus(array $items): bool {
+    foreach ($items as $item) {
+      if (!is_array($item) || empty($item['url'])) {
+        continue;
+      }
+
+      $url = $item['url'];
+      if (!$url instanceof Url) {
+        continue;
+      }
+
+      $obfuscateOnEnFront = $url->getOption('obfuscate_on_front_page');
+      $obfuscateOnTranslationFront = $url->getOption('obfuscate_on_translation_front_page');
+      $obfuscateOnEnAllPages = $url->getOption('obfuscate_on_all_pages');
+      $obfuscateOnTranslationAllPages = $url->getOption('obfuscate_on_all_translation_pages');
+
+      $values = [
+        $obfuscateOnEnFront,
+        $obfuscateOnTranslationFront,
+        $obfuscateOnEnAllPages,
+        $obfuscateOnTranslationAllPages,
+      ];
+
+      if (count(array_unique($values)) != 1) {
+        return TRUE;
+      }
+
+      if (!empty($item['below'])) {
+        $differentStatusBelow = static::differentObfuscationStatus($item['below']);
+        if ($differentStatusBelow) {
+          return TRUE;
+        }
+      }
+    }
+
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static function markItemsForObfuscation(array &$items) {
+    foreach ($items as &$item) {
+      /** @var \Drupal\Core\Url $url */
+      $url = $item['url'];
+      $url->setOption('force_obfuscate', TRUE);
+      if (empty($url->getOption('query'))) {
+        $url->setOption('query', \Drupal::request()->query->all());
+      }
+      if (!empty($item['below'])) {
+        static::markItemsForObfuscation($item['below']);
+      }
+    }
+
+  }
+
+}
diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..e492a51c7e511e808706d04645bb3e483314b7bd
--- /dev/null
+++ b/src/Form/SettingsForm.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace Drupal\link_obfuscation\Form;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Obfuscation settings form.
+ */
+class SettingsForm extends ConfigFormBase {
+
+  /**
+   * Drupal\Core\Entity\EntityTypeManagerInterface definition.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity_type.manager'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(EntityTypeManagerInterface $entityTypeManager) {
+    $this->entityTypeManager = $entityTypeManager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEditableConfigNames() {
+    return [
+      'link_obfuscation.settings',
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'link_obfuscation.settings';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $config = $this->config('link_obfuscation.settings');
+
+    $form['menu_block_ids'] = [
+      '#type' => 'textarea',
+      '#rows' => 6,
+      '#title' => $this->t('Menu block ids to obfuscate'),
+      '#default_value' => $config->get('menu_block_ids'),
+    ];
+
+    $form['separator_0'] = [
+      '#type' => 'html_tag',
+      '#tag' => 'hr',
+    ];
+
+    $form['obfuscate_language_switcher_on_front_page_default_language'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Obfuscate language switcher on front page on default language'),
+      '#default_value' => $config->get('obfuscate_language_switcher_on_front_default_page'),
+    ];
+
+    $form['obfuscate_language_switcher_on_front_page_not_default_language'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Obfuscate language switcher on front page on all translations but the default language'),
+      '#default_value' => $config->get('obfuscate_language_switcher_on_front_page_not_default_language'),
+    ];
+
+    $form['obfuscate_language_switcher_on_all_pages'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Obfuscate language switcher on pages'),
+      '#default_value' => $config->get('obfuscate_language_switcher_on_all_pages'),
+    ];
+
+    $form['language_switcher_block_ids'] = [
+      '#type' => 'textarea',
+      '#rows' => 3,
+      '#title' => $this->t('Language switcher block id(s) to obfuscate'),
+      '#default_value' => $config->get('language_switcher_block_ids'),
+    ];
+
+    $form['separator_1'] = [
+      '#type' => 'html_tag',
+      '#tag' => 'hr',
+    ];
+
+    $form['obfuscate_block_content_body_block_ids'] = [
+      '#type' => 'textarea',
+      '#rows' => 3,
+      '#title' => $this->t('Block content ids to obfuscate'),
+      '#description' => $this->t('Only obfuscate links from the body field.'),
+      '#default_value' => $config->get('obfuscate_block_content_body_block_ids'),
+    ];
+
+    $form['obfuscate_block_content_body_front'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Obfuscate block content body on front page'),
+      '#default_value' => $config->get('obfuscate_block_content_body_front'),
+    ];
+
+    $form['obfuscate_block_content_body_all_pages'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Obfuscate block content body on all pages (except the front page)'),
+      '#default_value' => $config->get('obfuscate_block_content_body_all_pages'),
+    ];
+
+    $form['separator_2'] = [
+      '#type' => 'html_tag',
+      '#tag' => 'hr',
+    ];
+
+    $form['obfuscate_views_view_ids'] = [
+      '#type' => 'textarea',
+      '#rows' => 3,
+      '#title' => $this->t('View block ids to obfuscate'),
+      '#description' => $this->t('Obfuscate links from the view. The format should be view_id|display_id|container, for example
+        solr_search_views|global_search|pagination'),
+      '#default_value' => $config->get('obfuscate_views_view_ids'),
+    ];
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    parent::submitForm($form, $form_state);
+
+    $this->config('link_obfuscation.settings')
+      ->set('menu_block_ids', $form_state->getValue('menu_block_ids'))
+      ->set('language_switcher_block_ids', $form_state->getValue('language_switcher_block_ids'))
+      ->set('obfuscate_language_switcher_on_front_page_default_language', $form_state->getValue('obfuscate_language_switcher_on_front_page_default_language'))
+      ->set('obfuscate_language_switcher_on_front_page_not_default_language', $form_state->getValue('obfuscate_language_switcher_on_front_page_not_default_language'))
+      ->set('obfuscate_language_switcher_on_all_pages', $form_state->getValue('obfuscate_language_switcher_on_all_pages'))
+      ->set('obfuscate_block_content_body_block_ids', $form_state->getValue('obfuscate_block_content_body_block_ids'))
+      ->set('obfuscate_block_content_body_front', $form_state->getValue('obfuscate_block_content_body_front'))
+      ->set('obfuscate_block_content_body_all_pages', $form_state->getValue('obfuscate_block_content_body_all_pages'))
+      ->set('obfuscate_views_view_ids', $form_state->getValue('obfuscate_views_view_ids'))
+      ->save();
+  }
+
+}
diff --git a/src/Plugin/facets/processor/ObfuscateLinkProcessor.php b/src/Plugin/facets/processor/ObfuscateLinkProcessor.php
index a9e8a20d4b5d646a9f041aff0a2d0404b31336ff..97e1f10b7a2174e9f62f8272243765a82b4d4df5 100644
--- a/src/Plugin/facets/processor/ObfuscateLinkProcessor.php
+++ b/src/Plugin/facets/processor/ObfuscateLinkProcessor.php
@@ -94,21 +94,13 @@ class ObfuscateLinkProcessor extends ProcessorPluginBase implements BuildProcess
    * {@inheritdoc}
    */
   public function supportsFacet(FacetInterface $facet) {
-    $data_definition = $facet->getDataDefinition();
-    if ($data_definition->getDataType() === 'entity_reference') {
-      return TRUE;
-    }
-    if (!($data_definition instanceof ComplexDataDefinitionInterface)) {
+    $dataDefinition = $facet->getDataDefinition();
+    // Here we can add unsupported data types when we discover them and decide we won't support them
+    $unsupportedDataTypes = [];
+    if (array_search($dataDefinition->getDataType(), $unsupportedDataTypes) !== FALSE) {
       return FALSE;
     }
-
-    $property_definitions = $data_definition->getPropertyDefinitions();
-    foreach ($property_definitions as $definition) {
-      if ($definition instanceof DataReferenceDefinitionInterface) {
-        return TRUE;
-      }
-    }
-    return FALSE;
+    return TRUE;
   }
 
-}
+}
\ No newline at end of file
diff --git a/src/Service/ObfuscateLinkService.php b/src/Service/ObfuscateLinkService.php
old mode 100644
new mode 100755
index 3f3b2033d131f3a1786f06f185be7cf77ec68ba1..696ee26c157de89ad443754c65cba0d4d49c0f58
--- a/src/Service/ObfuscateLinkService.php
+++ b/src/Service/ObfuscateLinkService.php
@@ -2,8 +2,10 @@
 
 namespace Drupal\link_obfuscation\Service;
 
+use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Url;
 use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\node\NodeInterface;
 use Masterminds\HTML5;
 
 /**
@@ -77,65 +79,69 @@ class ObfuscateLinkService {
   /**
    * Obfuscate html.
    */
-  public function obfuscateHtml(string $htmlText) {
+  public function obfuscateHtml(string $htmlText, ?string $class = NULL) {
     $html5 = new HTML5();
-
-    $htmlText = str_replace('<a', '<span', $htmlText);
-    $htmlText = str_replace('</a>', '</span>', $htmlText);
-
+    libxml_use_internal_errors(TRUE);
     $domDocument = $html5->loadHTML($htmlText);
-
-    foreach ($domDocument->getElementsByTagName('span') as $domLink) {
-      $href = $domLink->getAttribute('href');
-      if (empty($href)) {
-        continue;
+    libxml_clear_errors();
+
+    $xpath = new \DOMXPath($domDocument);
+    $xpath->registerNamespace('x', 'http://www.w3.org/1999/xhtml');
+    $changed = FALSE;
+    $query = !empty($class)
+      ? '//x:*[contains(concat(" ", normalize-space(@class), " "), " ' . $class . ' ")]//x:a'
+      : '//x:a';
+    foreach ($xpath->query($query) as $domLink) {
+      $changed = TRUE;
+      $span = $domDocument->createElement('span');
+      foreach ($domLink->attributes as $attribute) {
+        $span->setAttribute($attribute->name, $attribute->value);
       }
 
-      $url = NULL;
-      try {
-        $url = Url::fromUserInput($href);
-      }
-      catch (\Exception $e) {
-        // Ignore.
+      while ($domLink->childNodes->length > 0) {
+        $span->appendChild($domLink->childNodes->item(0));
       }
 
-      if (empty($url)) {
+      $domLink->parentNode->replaceChild($span, $domLink);
+
+      $href = $span->getAttribute('href');
+      if (!empty($href)) {
+        $url = NULL;
         try {
-          $url = Url::fromUri($href);
+          $url = Url::fromUserInput($href);
         }
         catch (\Exception $e) {
-          // Ignore.
+          try {
+            $url = Url::fromUri($href);
+          }
+          catch (\Exception $e) {
+            // Ignore.
+          }
         }
-      }
 
-      if (empty($url)) {
-        continue;
-      }
+        if (!empty($url)) {
+          $attributes = static::getObfuscateAttributesForUrl($url);
+          foreach ($attributes as $name => $value) {
+            $span->setAttribute($name, $value);
+          }
+        }
 
-      $obfuscateAttributes = static::getObfuscateAttributesForUrl($url);
-      foreach ($obfuscateAttributes as $obfuscateAttributeName => $obfuscateAttribute) {
-        $domLink->setAttribute($obfuscateAttributeName, $obfuscateAttribute);
-      }
+        if ($span->hasAttribute('target')) {
+          $span->setAttribute('data-target', $span->getAttribute('target'));
+          $span->removeAttribute('target');
+        }
 
-      if ($domLink->getAttribute('target')) {
-        $domLink->setAttribute('data-target', $domLink->getAttribute('target'));
-        $domLink->removeAttribute('target');
+        $span->removeAttribute('rel');
+        $span->removeAttribute('hreflang');
+        $classes = trim($span->getAttribute('class') . ' drupal-masked-element');
+        $span->setAttribute('class', $classes);
+        $span->removeAttribute('href');
       }
-
-      $domLink->removeAttribute('rel');
-      $domLink->removeAttribute('hreflang');
-
-      $classes = $domLink->getAttribute('class');
-      $classes .= ' drupal-masked-element';
-      $classes = trim($classes);
-
-      $domLink->setAttribute('class', $classes);
-      $domLink->removeAttribute('href');
     }
-
-    $obfuscatedContent = $domDocument->saveHTML();
-
-    return $obfuscatedContent;
+    if (!$changed) {
+      return $htmlText;
+    }
+    return $domDocument->saveHTML();
   }
 
 }