diff --git a/metatag.module b/metatag.module
index 6d86ffe..79a6e68 100644
--- a/metatag.module
+++ b/metatag.module
@@ -5,10 +5,12 @@
  * Contains metatag.module.
  */
 
+use Drupal\views\Views;
 use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Language\Language;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Url;
 
@@ -28,7 +30,8 @@ function metatag_help($route_name, RouteMatchInterface $route_match) {
       $output .= '</dl>';
 
       return $output;
-      break;
+
+    break;
   }
 }
 
@@ -206,6 +209,37 @@ function metatag_get_route_entity() {
 }
 
 /**
+ * Returns the display for the view from the current route.
+ *
+ * @return \Drupal\views\Plugin\views\display\DisplayPluginBase|null
+ *   The Display entity for the current view
+ */
+function metatag_get_route_view() {
+  // Get the route name.
+  $route_match = \Drupal::routeMatch();
+  $route_name = $route_match->getRouteName();
+
+  // Check if the route name is generated by the view.
+  if (strpos($route_name, 'view.') !== FALSE) {
+    // Get basic info about the view.
+    $params = $route_match->getParameters();
+    $view_id = $params->get('view_id');
+    $display_id = $params->get('display_id');
+    // If view_id or display_id are not set something is wrong.
+    if (!$view_id || !$display_id) {
+      return NULL;
+    }
+    // Get the view display object for current view and return it.
+    $view = Views::getView($view_id);
+    $view->setDisplay($display_id);
+    $display = $view->getDisplay();
+    return $display;
+  }
+
+  return NULL;
+}
+
+/**
  * Implements template_preprocess_html().
  */
 function metatag_preprocess_html(&$variables) {
@@ -235,7 +269,7 @@ function metatag_preprocess_html(&$variables) {
         $variables['head_title']['title'] = html_entity_decode($attachment[0]['#attributes']['content'], ENT_QUOTES);
         // Original:
         // $variables['head_title_array']['title'] = $attachment[0]['#attributes']['content'];
-        // $variables['head_title'] = implode(' | ', $variables['head_title_array']);
+        // $variables['head_title'] = implode(' | ', $variables['head_title_array']);.
         break;
       }
     }
@@ -265,6 +299,28 @@ function metatag_get_tags_from_route() {
     }
   }
 
+  // Check if the Views integration is enabled and find settings for that.
+  // @TODO: Might be a good idea to allow modules to hook into this process.
+  if (\Drupal::moduleHandler()->moduleExists('metatag_views')) {
+    // Get the view display from route.
+    $display = metatag_get_route_view();
+    if ($display) {
+      // And get the list of extenders for this display.
+      $extenders = $display->getExtenders();
+      if (!isset($extenders['metatag_display_extender'])) {
+        // If the id of our plugin is not in the list something is wrong.
+        return;
+      }
+      // Retrieve the settings of our plugins using method from metatag views module.
+      $tags = $extenders['metatag_display_extender']->getMetatags();
+      // Account for our future lanuage handling.
+      $tags = !empty($tags) ? $tags[Language::LANGCODE_NOT_SPECIFIED] : array();
+      $metatags = array_merge($metatags, $tags);
+      // Pass the view as the entity.
+      $entity = $display->view;
+    }
+  }
+
   return $metatag_manager->generateElements($metatags, $entity);
 }
 
diff --git a/metatag.services.yml b/metatag.services.yml
index b13dfc3..b152163 100644
--- a/metatag.services.yml
+++ b/metatag.services.yml
@@ -13,15 +13,12 @@ services:
 
   metatag.manager:
     class: Drupal\metatag\MetatagManager
-    arguments: ['@plugin.manager.metatag.group', '@plugin.manager.metatag.tag', '@metatag.token', '@logger.factory']
-
-# These will be reactivated once Console finishes refactoring the generators.
-# @see https://www.drupal.org/node/2786795
-#  metatag_generate_group:
-#    class: Drupal\metatag\Command\GenerateGroupCommand
-#    tags:
-#      - { name: console.command }
-#  metatag_generate_tag:
-#    class: Drupal\metatag\Command\GenerateTagCommand
-#    tags:
-#      - { name: console.command }
+    arguments: ['@plugin.manager.metatag.group', '@plugin.manager.metatag.tag', '@metatag.token', '@logger.factory', '@entity_type.manager']
+  metatag_generate_group:
+    class: Drupal\metatag\Command\GenerateGroupCommand
+    tags:
+      - { name: console.command }
+  metatag_generate_tag:
+    class: Drupal\metatag\Command\GenerateTagCommand
+    tags:
+      - { name: console.command }
diff --git a/metatag_views/metatag_views.info.yml b/metatag_views/metatag_views.info.yml
new file mode 100644
index 0000000..398ff2a
--- /dev/null
+++ b/metatag_views/metatag_views.info.yml
@@ -0,0 +1,8 @@
+name: 'Metatag: Views'
+type: module
+description: Provides views integration for metatags.
+core: 8.x
+package: SEO
+dependencies:
+  - metatag
+  - views
diff --git a/metatag_views/metatag_views.install b/metatag_views/metatag_views.install
new file mode 100644
index 0000000..5d57f86
--- /dev/null
+++ b/metatag_views/metatag_views.install
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * Implements hook_install().
+ */
+function metatag_views_install() {
+  // Enable metatag_display_extender plugin.
+  $config = \Drupal::service('config.factory')->getEditable('views.settings');
+  $display_extenders = $config->get('display_extenders') ?: array();
+  $display_extenders[] = 'metatag_display_extender';
+  $config->set('display_extenders', $display_extenders);
+  $config->save();
+}
+
+/**
+ * Implements hook_uninstall().
+ */
+function metatag_views_uninstall() {
+  // Disable metatag_display_extender plugin.
+  $config = \Drupal::service('config.factory')->getEditable('views.settings');
+  $display_extenders = $config->get('display_extenders') ?: array();
+
+  $key = array_search('metatag_display_extender', $display_extenders);
+  if ($key !== FALSE) {
+    unset($display_extenders[$key]);
+    $config->set('display_extenders', $display_extenders);
+    $config->save();
+  }
+}
\ No newline at end of file
diff --git a/metatag_views/metatag_views.links.action.yml b/metatag_views/metatag_views.links.action.yml
new file mode 100644
index 0000000..6e76a4f
--- /dev/null
+++ b/metatag_views/metatag_views.links.action.yml
@@ -0,0 +1,5 @@
+metatag_views.metatags.add:
+  route_name: 'metatag_views.metatags.add'
+  title: 'Add views meta tags'
+  appears_on:
+    - metatag_views.metatags.list
diff --git a/metatag_views/metatag_views.links.task.yml b/metatag_views/metatag_views.links.task.yml
new file mode 100644
index 0000000..7261c9a
--- /dev/null
+++ b/metatag_views/metatag_views.links.task.yml
@@ -0,0 +1,9 @@
+metatag_views.defaults:
+  title: 'Defaults'
+  route_name: entity.metatag_defaults.collection
+  base_route: entity.metatag_defaults.collection
+  weight: 0
+metatag_views.tab_views:
+  title: 'Views'
+  route_name: metatag_views.metatags.list
+  base_route: entity.metatag_defaults.collection
\ No newline at end of file
diff --git a/metatag_views/metatag_views.routing.yml b/metatag_views/metatag_views.routing.yml
new file mode 100644
index 0000000..f0b8342
--- /dev/null
+++ b/metatag_views/metatag_views.routing.yml
@@ -0,0 +1,39 @@
+metatag_views.metatags.list:
+  path: 'admin/config/search/metatag/views'
+  defaults:
+    _controller: '\Drupal\metatag_views\Controller\MetatagViewsController::listViews'
+    _title: 'Views metatags'
+  requirements:
+    _permission: 'administer meta tags'
+  options:
+    _admin_route: TRUE
+
+metatag_views.metatags.edit:
+  path: 'admin/config/search/metatag/views/{view_id}/{display_id}/edit'
+  defaults:
+    _form: '\Drupal\metatag_views\Form\MetatagViewsEditForm'
+    _title: 'Edit metatags for a view'
+  requirements:
+    _permission: 'administer meta tags'
+  options:
+    _admin_route: TRUE
+
+metatag_views.metatags.revert:
+  path: 'admin/config/search/metatag/views/{view_id}/{display_id}/revert'
+  defaults:
+    _form: '\Drupal\metatag_views\Form\MetatagViewsRevertForm'
+    _title: 'Revert metatags for a view'
+  requirements:
+    _permission: 'administer meta tags'
+  options:
+    _admin_route: TRUE
+
+metatag_views.metatags.add:
+  path: 'admin/config/search/metatag/views/add'
+  defaults:
+    _form: '\Drupal\metatag_views\Form\MetatagViewsAddForm'
+    _title: 'Add metatags for a view'
+  requirements:
+    _permission: 'administer meta tags'
+  options:
+    _admin_route: TRUE
diff --git a/metatag_views/src/Controller/MetatagViewsController.php b/metatag_views/src/Controller/MetatagViewsController.php
new file mode 100644
index 0000000..eeb43b6
--- /dev/null
+++ b/metatag_views/src/Controller/MetatagViewsController.php
@@ -0,0 +1,196 @@
+<?php
+
+namespace Drupal\metatag_views\Controller;
+
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Url;
+use Drupal\metatag\MetatagManagerInterface;
+use Drupal\metatag_views\Plugin\views\display_extender\MetatagDisplayExtender;
+use Drupal\views\Plugin\views\display\DisplayPluginInterface;
+use Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase;
+use Drupal\views\ViewEntityInterface;
+use Drupal\views\ViewExecutable;
+use Drupal\views\Views;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Class MetatagViewsController
+ * @package Drupal\metatag_views\Controller
+ */
+class MetatagViewsController extends ControllerBase {
+
+  /** @var EntityStorageInterface  */
+  protected $viewStorage;
+
+  /** @var MetatagManagerInterface  */
+  protected $metatagManager;
+
+  /** @var array  associative array of labels */
+  protected $viewLabels;
+
+  public function __construct(EntityStorageInterface $viewStorage,
+                              MetatagManagerInterface $metatagManager) {
+    $this->viewStorage = $viewStorage;
+    $this->metatagManager = $metatagManager;
+
+    // Generate the labels for views and displays.
+    $this->labels = $this->getViewsAndDisplaysLabels();
+  }
+
+  /**
+   * @inheritDoc
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity_type.manager')->getStorage('view'),
+      $container->get('metatag.manager')
+    );
+  }
+
+  /**
+   * Main controller function. Generates the renderable array for views
+   * metatags UI.
+   *
+   * @return array
+   */
+  public function listViews() {
+    // Get metatags for all of the views / displays that have them set.
+    $metataged_views = $this->metatagManager->getMetatagedViews();
+    $elements = [];
+
+    $elements['header'] = [
+      '#markup' => '<p>' . t("To view a list of displays with meta tags set up, click on a view name. To view a summary of meta tags configuration for a particular display, click on the display name. If you need to set metatags for a specific view, choose Add views meta tags. Reverting the meta tags removes the specific configuration and falls back to defaults.") . '</p>',
+    ];
+
+    // Iterate over the values and build the whole UI.
+    // 1. Top level is a collapsible fieldset with a view name (details)
+    // 2. Inside each fieldset we have 2 columns -> Display and Operations.
+    //    Display contains point 3.
+    //    Operations contain edit and revert
+    // 3. In each display there is a table that has 2 columns: tag name and tag
+    //    value.
+    foreach($metataged_views as $view_id => $displays) {
+      $elements[$view_id] = [
+        '#type' => 'details',
+        '#title' => $this->t($this->viewLabels[$view_id]['#label']),
+        'details' => $this->buildViewDetails($view_id, $displays),
+      ];
+    }
+
+    return $elements;
+  }
+
+  /**
+   * Builds the second "level" of the UI - table with display fieldset and operations.
+   *
+   * @param $view_id
+   * @param $displays
+   * @return array
+   */
+  protected function buildViewDetails($view_id, $displays) {
+    $element = [
+      '#type' => 'table',
+      '#collapsible' => TRUE,
+      '#header' => [ $this->t('Display'), $this->t('Operations') ]
+    ];
+
+    foreach($displays as $display_id => $metatags) {
+      $metatags = array_filter($metatags);
+
+      $element[$display_id]['details'] = [
+        '#type' => 'details',
+        '#title' => $this->viewLabels[$view_id][$display_id],
+      ];
+
+      $params = [ 'view_id' => $view_id, 'display_id' => $display_id ];
+
+      // Generate the operations.
+      $element[$display_id]['ops'] = [
+        '#type' => 'operations',
+        '#links' => [
+          'edit' => [
+            'title' => t('Edit'),
+            'url' => Url::fromRoute('metatag_views.metatags.edit', $params),
+          ],
+          'revert' => [
+            'title' => t('Revert'),
+            'url' => Url::fromRoute('metatag_views.metatags.revert', $params),
+          ],
+        ],
+      ];
+
+      // Build the rows for each of the metatag types.
+      $element[$display_id]['details']['table'] = $this->buildDisplayDetailsTable($metatags);
+    }
+
+    return $element;
+  }
+
+  /**
+   * Build the table with metatags values summary.
+   *
+   * @param $tags
+   * @return array
+   */
+  protected function buildDisplayDetailsTable($tags) {
+    $element = [
+      '#type' => 'table',
+    ];
+
+    $i = 0;
+    foreach($tags as $tag_name => $tag_value) {
+      // This is for the case where we have a subarray.
+      $tag_value = $this->prepareTagValue($tag_value);
+      if(!$tag_value) { continue; }
+
+      $element[$i]['tag_name'] = [
+        '#type' => 'markup',
+        '#markup' => $tag_name,
+      ];
+
+      $element[$i]['tag_value'] = [
+        '#type' => 'markup',
+        '#markup' => $tag_value,
+      ];
+      $i++;
+    }
+
+    return $element;
+  }
+
+  /**
+   * Massage the tag value. Returns an imploded string for metatags that
+   * are nested (ex. robots).
+   *
+   * @param $value
+   * @return string
+   */
+  protected function prepareTagValue($value) {
+    if(is_array($value)) {
+      $value = implode(', ', array_filter($value));
+    }
+
+    return $value;
+  }
+
+  /**
+   * Gets label values for the views and their displays.
+   */
+  protected function getViewsAndDisplaysLabels() {
+    /** @var ViewEntityInterface[] $views */
+    $views = $this->viewStorage->loadByProperties(['status' => 1]);
+
+    $labels = [];
+
+    foreach($views as $view_id => $view) {
+      $displays = $view->get('display');
+      $labels[$view_id]['#label'] = $view->get('label');
+      foreach(array_keys($displays) as $display_id) {
+        $labels[$view_id][$display_id] = $displays[$display_id]['display_title'];
+      }
+    }
+
+    $this->viewLabels = $labels;
+  }
+}
\ No newline at end of file
diff --git a/metatag_views/src/Form/MetatagViewsAddForm.php b/metatag_views/src/Form/MetatagViewsAddForm.php
new file mode 100644
index 0000000..fc25bea
--- /dev/null
+++ b/metatag_views/src/Form/MetatagViewsAddForm.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace Drupal\metatag_views\Form;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\metatag\MetatagManagerInterface;
+use Drupal\metatag_views\MetatagViewsValuesCleanerTrait;
+use Drupal\views\ViewEntityInterface;
+use Drupal\views\Views;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Class MetatagViewsAddForm.
+ *
+ * @package Drupal\metatag_views\Form
+ */
+class MetatagViewsAddForm extends FormBase {
+  use MetatagViewsOptionsSubmitTrait;
+  use MetatagViewsValuesCleanerTrait;
+  /**
+   * Drupal\metatag\MetatagManager definition.
+   *
+   * @var \Drupal\metatag\MetatagManagerInterface
+   */
+  protected $metatagManager;
+
+  /**
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $viewsManager;
+
+
+  public function __construct(
+    MetatagManagerInterface $metatag_manager,
+    EntityTypeManagerInterface $entity_manager
+  ) {
+    $this->metatagManager = $metatag_manager;
+    $this->viewsManager = $entity_manager->getStorage('view');
+  }
+
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('metatag.manager'),
+      $container->get('entity_type.manager')
+    );
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'metatag_views_add_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    // Get views list as options.
+    $in_use = $this->metatagManager->getMetatagedViews();
+    $opts = Views::getViewsAsOptions(FALSE, 'enabled', NULL, TRUE, TRUE);
+    // Get only the views that do not have the metatags set yet.
+    $filtered = $this->filterViewList($in_use, $opts);
+
+    // Build/inject the Metatag form. Use defaults.
+    $metatags = $this->metatagManager->getDefaultMetatags();
+
+    $form['metatags'] = $this->metatagManager->form( $metatags, $form, [ 'view' ] );
+    $form['metatags']['#title'] = t('Metatags');
+    $form['metatags']['#type'] = 'fieldset';
+
+    // Need to create that AFTER the $form['metatags'] as the whole form
+    // is passed to the $metatagManager->form() which causes duplicated field.
+    $form['view'] = [
+      '#type' => 'select',
+      '#options' => $filtered,
+      '#title' => t('Choose a view'),
+      '#weight' => -100,
+    ];
+
+    $form['submit'] = array(
+        '#type' => 'submit',
+        '#value' => t('Submit'),
+    );
+
+    return $form;
+  }
+
+  /**
+   * Filters the options array to unset the views that already have metatag
+   * display extender configured.
+   *
+   * @param $used
+   *  Views to exclude
+   * @param $all
+   *  Views to exclude from
+   * @return mixed
+   *  An associative array of views and display ids.
+   */
+  protected function filterViewList($used, $all) {
+    foreach ($used as $view_id => $displays) {
+      foreach(array_keys($displays) as $display_id) {
+        $id = $view_id . ':' . $display_id;
+        if(isset($all[$view_id][$id])) {
+          unset($all[$view_id][$id]);
+        }
+      }
+      if(empty($all[$view_id])) {
+        unset($all[$view_id]);
+      }
+    }
+    return $all;
+  }
+
+  /**
+    * {@inheritdoc}
+    */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    parent::validateForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    // Get the values
+    $metatags = $form_state->getValues();
+    $view_option = $form_state->getValue('view');
+    // Remove the unnecessary entry from values.
+    unset($metatags['view']);
+
+    list($view_id, $display_id) = explode(':', $view_option);
+
+    /** @var ViewEntityInterface $view */
+    $view = $this->viewsManager->load($view_id);
+
+    // Clear the unneeded elements.
+    $metatags = $this->clearMetatagViewsDisallowedValues($metatags);
+
+    // Save the display extender options and the view itself.
+    $this->setMetatagDisplayExtenderValues($view, $display_id, $metatags);
+
+    // Redirect back to the views list.
+    $form_state->setRedirect($this->redirectRoute);
+
+    $display = $view->getDisplay($display_id);
+
+    $params = [
+      '@view' => $view->get('label'),
+      '@display' => $display['display_title']
+    ];
+
+    drupal_set_message($this->t('Metatags for @view : @display have been added.', $params));
+  }
+}
diff --git a/metatag_views/src/Form/MetatagViewsEditForm.php b/metatag_views/src/Form/MetatagViewsEditForm.php
new file mode 100644
index 0000000..ab61a40
--- /dev/null
+++ b/metatag_views/src/Form/MetatagViewsEditForm.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace Drupal\metatag_views\Form;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\metatag\MetatagManagerInterface;
+use Drupal\metatag_views\MetatagViewsValuesCleanerTrait;
+use Drupal\views\ViewEntityInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Class MetatagViewsEditForm.
+ *
+ * @package Drupal\metatag_views\Form
+ */
+class MetatagViewsEditForm extends FormBase {
+  use MetatagViewsOptionsSubmitTrait;
+  use MetatagViewsValuesCleanerTrait;
+
+  /**
+   * Drupal\metatag\MetatagManager definition.
+   *
+   * @var \Drupal\metatag\MetatagManager
+   */
+  protected $metatagManager;
+
+  /**
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $viewsManager;
+
+  /**
+   * Array of display settings as returned from getDisplay of ViewEntityInterface
+   *
+   * @var  array
+   */
+  protected $display;
+
+  /**
+   * View entity object
+   *
+   * @var  ViewEntityInterface
+   */
+  protected $view;
+
+  public function __construct(
+    MetatagManagerInterface $metatag_manager,
+    EntityTypeManagerInterface $entity_manager
+  ) {
+    $this->metatagManager = $metatag_manager;
+    $this->viewsManager = $entity_manager->getStorage('view');
+  }
+
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('metatag.manager'),
+      $container->get('entity_type.manager')
+    );
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'metatag_views_edit_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    // Get the parameters from request.
+    $view_id = \Drupal::request()->get('view_id');
+    $display_id = \Drupal::request()->get('display_id');
+
+    $metatags = [];
+
+    /** @var ViewEntityInterface $view */
+    $this->view = $this->viewsManager->load($view_id);
+    // Array representing the display settings.
+    $this->display = $this->view->getDisplay($display_id);
+
+    // Get metatags from the view entity.
+    $metatags = $this->metatagManager->tagsFromViewDisplay($this->view, $display_id);
+
+    $form['metatags'] = $this->metatagManager->form( $metatags, $form, ['view'] );
+    $form['metatags']['#title'] = t('Metatags');
+    $form['metatags']['#type'] = 'fieldset';
+
+    $form['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Submit'),
+    );
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    parent::validateForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    // Get the values.
+    $metatags = $form_state->getValues();
+
+    // Clear the unneeded elements.
+    $metatags = $this->clearMetatagViewsDisallowedValues($metatags);
+
+    // Save the display extender options and the view itself.
+    $this->setMetatagDisplayExtenderValues($this->view, $this->display['id'], $metatags);
+
+    // Redirect back to the views list.
+    $form_state->setRedirect($this->redirectRoute);
+
+    $params = [
+      '@view' => $this->view->get('label'),
+      '@display' => $this->display['display_title']
+    ];
+
+    drupal_set_message($this->t('Metatags for @view : @display have been updated.', $params));
+  }
+
+}
diff --git a/metatag_views/src/Form/MetatagViewsOptionsSubmitTrait.php b/metatag_views/src/Form/MetatagViewsOptionsSubmitTrait.php
new file mode 100644
index 0000000..4defeb8
--- /dev/null
+++ b/metatag_views/src/Form/MetatagViewsOptionsSubmitTrait.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Drupal\metatag_views\Form;
+
+use Drupal\views\ViewEntityInterface;
+
+
+trait MetatagViewsOptionsSubmitTrait {
+  // Default route to redirect after the form submission.
+  protected $redirectRoute = 'metatag_views.metatags.list';
+
+  /**
+   * Sets the metatag display extender options. Unsets if NULL
+   *
+   * @param ViewEntityInterface $view
+   *  View object to act upon.
+   * @param $display_id
+   *  Display id to set / reset.
+   * @param array|null $values
+   *  Values to set. Unsets the values if NULL given.
+   */
+  public function setMetatagDisplayExtenderValues(ViewEntityInterface $view, $display_id, $values = NULL) {
+    /** @var array $displays An array of displays */
+    $displays = $view->get('display');
+    // Set proper values for the display extender.
+    $element = is_null($values) ? [] : [ 'metatags' => $values ];
+    $displays[$display_id]['display_options']['display_extenders']['metatag_display_extender'] = $element;
+
+    // Set the displays back to the view
+    $view->set('display', $displays);
+    // Save the views.
+    $view->save();
+  }
+}
\ No newline at end of file
diff --git a/metatag_views/src/Form/MetatagViewsRevertForm.php b/metatag_views/src/Form/MetatagViewsRevertForm.php
new file mode 100644
index 0000000..5f1ba6b
--- /dev/null
+++ b/metatag_views/src/Form/MetatagViewsRevertForm.php
@@ -0,0 +1,115 @@
+<?php
+
+namespace Drupal\metatag_views\Form;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\ConfirmFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
+use Drupal\views\ViewEntityInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Defines a confirmation form for deleting mymodule data.
+ */
+class MetatagViewsRevertForm extends ConfirmFormBase {
+  use MetatagViewsOptionsSubmitTrait;
+  /**
+   * Entity manager for views entities.
+   *
+   * @var EntityTypeManagerInterface
+   */
+  protected $viewsManager;
+
+  protected $view;
+  protected $display;
+
+  public function __construct(
+    EntityTypeManagerInterface $entity_manager
+  ) {
+    $this->viewsManager = $entity_manager->getStorage('view');
+  }
+
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'metatag_views_revert_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQuestion() {
+    return $this->t('Do you want to revert metatags for @view_name : @display_name?',
+      [ '@view_name' => $this->view->label(),
+        '@display_name' => $this->display['display_title']
+      ]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCancelUrl() {
+    return new Url('metatag_views.metatags.list');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDescription() {
+    return $this->t('This reverts the override metatags for a selected view. This action cannot be undone.');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfirmText() {
+    return $this->t('Revert');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCancelText() {
+    return $this->t('Forget it');
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @param int $id
+   *   (optional) The ID of the item to be deleted.
+   */
+  public function buildForm(array $form, FormStateInterface $form_state, $view_id = NULL, $display_id = NUL) {
+    /** @var ViewEntityInterface view */
+    $this->view = $this->viewsManager->load($view_id);
+    /** @var array display */
+    $this->display = $this->view->getDisplay($display_id);
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    // Call set function in a reset mode (explicitly set the third argument to NULL).
+    $this->setMetatagDisplayExtenderValues($this->view, $this->display['id'], NULL);
+
+    // Redirect back to the views list.
+    $form_state->setRedirect($this->redirectRoute);
+
+    drupal_set_message($this->t('Reverted metatags for @view_name : @display_name',
+      [ '@view_name' => $this->view->label(),
+        '@display_name' => $this->display['display_title']
+      ]));
+  }
+
+}
diff --git a/metatag_views/src/MetatagViewsValuesCleanerTrait.php b/metatag_views/src/MetatagViewsValuesCleanerTrait.php
new file mode 100644
index 0000000..fe35b64
--- /dev/null
+++ b/metatag_views/src/MetatagViewsValuesCleanerTrait.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Drupal\metatag_views;
+
+use Drupal\views\ViewEntityInterface;
+
+
+trait MetatagViewsValuesCleanerTrait {
+  /**
+   * Clears the metatag form state values from illegal elements.
+   *
+   * @param array $metatags
+   *  Array of values to submit.
+   *
+   * @return array
+   *  Filtered metatg array.
+   */
+  public function clearMetatagViewsDisallowedValues($metatags) {
+    // Get all legal tags.
+    $tags = $this->metatagManager->sortedTags();
+
+    // Return only common elements.
+    $metatags = array_intersect_key($metatags, $tags);
+
+    return $metatags;
+  }
+}
\ No newline at end of file
diff --git a/metatag_views/src/Plugin/views/display_extender/MetatagDisplayExtender.php b/metatag_views/src/Plugin/views/display_extender/MetatagDisplayExtender.php
new file mode 100644
index 0000000..6aaffcd
--- /dev/null
+++ b/metatag_views/src/Plugin/views/display_extender/MetatagDisplayExtender.php
@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\metatag_views\Plugin\views\display_extender\MetatagDisplayExtender.
+ */
+
+namespace Drupal\metatag_views\Plugin\views\display_extender;
+
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\metatag\MetatagManagerInterface;
+use Drupal\metatag_views\MetatagViewsValuesCleanerTrait;
+use Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Metatag display extender plugin.
+ *
+ * @ingroup views_display_extender_plugins
+ *
+ * @ViewsDisplayExtender(
+ *   id = "metatag_display_extender",
+ *   title = @Translation("Metatag display extender"),
+ *   help = @Translation("Metatag settings for this view."),
+ *   no_ui = FALSE
+ * )
+ */
+class MetatagDisplayExtender extends DisplayExtenderPluginBase {
+  use MetatagViewsValuesCleanerTrait;
+  /** @var  MetatagManagerInterface */
+  protected $metatagManager;
+
+  /**
+   * Provide a form to edit options for this plugin.
+   */
+  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+
+    if ($form_state->get('section') == 'metatags') {
+      $form['#title'] .= t('The meta tags for this display');
+      $metatags = $this->getMetatags();
+      $metatags = !empty($metatags) ? $metatags[LanguageInterface::LANGCODE_NOT_SPECIFIED] : array();
+
+      // Build/inject the Metatag form.
+      $this->metatagManager = \Drupal::service('metatag.manager');
+      $form['metatags'] = $this->metatagManager->form( $metatags, $form, [ 'view' ] );
+    }
+  }
+
+  /**
+   * Validate the options form.
+   */
+  public function validateOptionsForm(&$form, FormStateInterface $form_state) {
+  }
+
+  /**
+   * Handle any special handling on the validate form.
+   */
+  public function submitOptionsForm(&$form, FormStateInterface $form_state) {
+    if ($form_state->get('section') == 'metatags') {
+      $metatags = $form_state->getValues();
+      // Remove the unnecessary elements from values array.
+      $metatags = $this->clearMetatagViewsDisallowedValues($metatags);
+      $this->options['metatags'] = $metatags;
+    }
+  }
+
+  /**
+   * Set up any variables on the view prior to execution.
+   */
+  public function preExecute() {
+  }
+
+  /**
+   * Inject anything into the query that the display_extender handler needs.
+   */
+  public function query() {
+  }
+
+  /**
+   * Provide the default summary for options in the views UI.
+   *
+   * This output is returned as an array.
+   */
+  public function optionsSummary(&$categories, &$options) {
+    $categories['metatags'] = array(
+      'title' => t('Meta tags'),
+      'column' => 'second',
+    );
+    $options['metatags'] = array(
+      'category' => 'metatags',
+      'title' => t('Meta tags'),
+      'value' => $this->hasMetatags() ? t('Overridden') : t('Using defaults'),
+    );
+  }
+
+  /**
+   * Static member function to list which sections are defaultable
+   * and what items each section contains.
+   */
+  public function defaultableSections(&$sections, $section = NULL) {
+  }
+
+  /**
+   * Identify whether or not the current display has custom meta tags defined.
+   */
+  protected function hasMetatags() {
+    $metatags = $this->getMetatags();
+    return !empty($metatags[LanguageInterface::LANGCODE_NOT_SPECIFIED]);
+
+  }
+
+  /**
+   * Get the Metatag configuration for this display.
+   *
+   * @return array
+   *   The meta tag values, keys by language (default LanguageInterface::LANGCODE_NOT_SPECIFIED).
+   */
+  public function getMetatags() {
+    $metatags = $this->options['metatags'];
+
+    // Leave some possibility for future versions to support translation.
+    if (empty($metatags)) {
+      $metatags = array(LanguageInterface::LANGCODE_NOT_SPECIFIED => array());
+    }
+    if (!isset($metatags[LanguageInterface::LANGCODE_NOT_SPECIFIED])) {
+      $metatags = array(LanguageInterface::LANGCODE_NOT_SPECIFIED => $metatags);
+    }
+
+    return $metatags;
+  }
+
+  public function setMetatags($metatags) {
+    $this->options['metatags'] = $metatags;
+  }
+}
diff --git a/src/MetatagManager.php b/src/MetatagManager.php
index fd74f85..28d2fb6 100644
--- a/src/MetatagManager.php
+++ b/src/MetatagManager.php
@@ -4,9 +4,11 @@ namespace Drupal\metatag;
 
 use Drupal\Component\Render\PlainTextOutput;
 use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Logger\LoggerChannelFactoryInterface;
-use Drupal\field\Entity\FieldConfig;
+use Drupal\views\ViewEntityInterface;
+use Drupal\views\ViewExecutable;
 
 /**
  * Class MetatagManager.
@@ -17,6 +19,8 @@ class MetatagManager implements MetatagManagerInterface {
 
   protected $groupPluginManager;
   protected $tagPluginManager;
+  protected $defaultMetatagsManager;
+  protected $viewStorage;
 
   protected $tokenService;
 
@@ -34,13 +38,17 @@ class MetatagManager implements MetatagManagerInterface {
    * @param MetatagTagPluginManager $tagPluginManager
    * @param MetatagToken $token
    * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $channelFactory
+   * @param EntityTypeManagerInterface $entityTypeManager
    */
   public function __construct(MetatagGroupPluginManager $groupPluginManager,
                               MetatagTagPluginManager $tagPluginManager,
                               MetatagToken $token,
-                              LoggerChannelFactoryInterface $channelFactory) {
+                              LoggerChannelFactoryInterface $channelFactory,
+                              EntityTypeManagerInterface $entityTypeManager) {
     $this->groupPluginManager = $groupPluginManager;
     $this->tagPluginManager = $tagPluginManager;
+    $this->defaultMetatagsManager = $entityTypeManager->getStorage('metatag_defaults');
+    $this->viewStorage = $entityTypeManager->getStorage('view');
     $this->tokenService = $token;
     $this->logger = $channelFactory->get('metatag');
   }
@@ -63,6 +71,53 @@ class MetatagManager implements MetatagManagerInterface {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function tagsFromViewDisplay(ViewEntityInterface $view, $display_id = NULL) {
+    $tags = [];
+
+    if (is_null($display_id)) {
+      $displays = $view->get('display');
+      foreach (array_keys($displays) as $display_id) {
+        $metatags = $this->tagsFromViewDisplay($view, $display_id);
+        if (!empty($metatags)) {
+          $tags[$display_id] = $metatags;
+        }
+      }
+      return $tags;
+    }
+
+    $display = $view->getDisplay($display_id);
+    $tags = isset($display['display_options']['display_extenders']['metatag_display_extender']['metatags']) ? $display['display_options']['display_extenders']['metatag_display_extender']['metatags'] : NULL;
+
+    return $tags;
+  }
+
+  /**
+   * This returns metatag values for each view id and display id.
+   *
+   * @return array - associative array of metatags keyed by display id
+   */
+  public function getMetatagedViews() {
+    /** @var ViewEntityInterface[] $views */
+    $views = $this->viewStorage->loadByProperties(['status' => 1]);
+
+    $metataged_views = [];
+
+    // Iterate over views and get metatags for each of them creating array
+    // where the values are not empty.
+    foreach ($views as $view_id => $view) {
+      $tags = $this->tagsFromViewDisplay($view);
+      if (empty($tags)) {
+        continue;
+      }
+      $metataged_views[$view_id] = $tags;
+    }
+
+    return $metataged_views;
+  }
+
+  /**
    * Gets the group plugin definitions.
    *
    * @return array
@@ -246,15 +301,97 @@ class MetatagManager implements MetatagManagerInterface {
     foreach ($entity->{$field_name} as $item) {
       // Get serialized value and break it into an array of tags with values.
       $serialized_value = $item->get('value')->getValue();
-      // if (!empty($serialized_value)) {
+      // If (!empty($serialized_value)) {.
       $tags += unserialize($serialized_value);
-      // }
+      // }.
     }
 
     return $tags;
   }
 
   /**
+   *
+   */
+  public function getDefaultMetatags(ContentEntityInterface $entity = NULL) {
+    // Get general global metatags.
+    $metatags = $this->getGlobalMetatags();
+    // If that is empty something went wrong.
+    if (!$metatags) {
+      return;
+    }
+
+    // Check if this is a special page.
+    $special_metatags = $this->getSpecialMetatags();
+
+    // Merge with all globals defaults.
+    if ($special_metatags) {
+      $metatags->set('tags', array_merge($metatags->get('tags'), $special_metatags->get('tags')));
+    }
+    // Next check if there is this page is an entity that has meta tags.
+    // @TODO: Think about using other defaults - ex. views. Maybe utilize plugins?
+    else {
+      if (is_null($entity)) {
+        $entity = metatag_get_route_entity();
+      }
+
+      if (!empty($entity)) {
+        // Get default metatags for a given entity.
+        $entity_defaults = $this->getEntityDefaultMetatags($entity);
+        if ($entity_defaults != NULL) {
+          $metatags->set('tags', array_merge($metatags->get('tags'), $entity_defaults));
+        }
+      }
+    }
+
+    return $metatags->get('tags');
+  }
+
+  /**
+   *
+   */
+  public function getGlobalMetatags() {
+    return $this->defaultMetatagsManager->load('global');
+  }
+
+  /**
+   *
+   */
+  public function getSpecialMetatags() {
+    if (\Drupal::service('path.matcher')->isFrontPage()) {
+      return $this->defaultMetatagsManager->load('front');
+    }
+    elseif (\Drupal::service('current_route_match')->getRouteName() == 'system.403') {
+      return $this->defaultMetatagsManager->load('403');
+    }
+    elseif (\Drupal::service('current_route_match')->getRouteName() == 'system.404') {
+      return $this->defaultMetatagsManager->load('404');
+    }
+
+    return;
+  }
+
+  /**
+   *
+   */
+  public function getEntityDefaultMetatags(ContentEntityInterface $entity) {
+    $entity_metatags = $this->defaultMetatagsManager->load($entity->getEntityTypeId());
+    $metatags = [];
+    if ($entity_metatags != NULL) {
+      // Merge with global defaults.
+      $metatags = array_merge($metatags, $entity_metatags->get('tags'));
+    }
+
+    // Finally, check if we should apply bundle overrides.
+    $bundle_metatags = $this->defaultMetatagsManager->load($entity->getEntityTypeId() . '__' . $entity->bundle());
+    if ($bundle_metatags != NULL) {
+      // Merge with existing defaults.
+      $metatags = array_merge($metatags, $bundle_metatags->get('tags'));
+    }
+
+    return $metatags;
+  }
+
+  /**
    * Generate the elements that go in the attached array in
    * hook_page_attachments.
    *
@@ -262,12 +399,37 @@ class MetatagManager implements MetatagManagerInterface {
    *   The array of tags as plugin_id => value.
    * @param object $entity
    *   Optional entity object to use for token replacements.
+   *
    * @return array
    *   Render array with tag elements.
    */
   public function generateElements($tags, $entity = NULL) {
     $metatag_tags = $this->tagPluginManager->getDefinitions();
     $elements = [];
+    $tags = $this->generateRawElements($tags, $entity);
+
+    foreach ($tags as $name => $tag) {
+      if (!empty($tag)) {
+        $elements['#attached']['html_head'][] = [
+          $tag,
+          $name,
+        ];
+      }
+
+    }
+
+    return $elements;
+
+  }
+
+  /**
+   * Generate Raw Elements.
+   */
+  public function generateRawElements($tags, $entity = NULL) {
+
+    $metatag_tags = $this->tagPluginManager->getDefinitions();
+
+    $rawTags = [];
 
     // Each element of the $values array is a tag with the tag plugin name
     // as the key.
@@ -280,7 +442,15 @@ class MetatagManager implements MetatagManagerInterface {
         // Render any tokens in the value.
         $token_replacements = [];
         if ($entity) {
-          $token_replacements = [$entity->getEntityTypeId() => $entity];
+          // Check if our entity is a view and react appropriately.
+          // @TODO: Probably this needs a better way of discovering the context
+          // @TODO: This should be an EntityConfigInterface actually...
+          if ($entity instanceof ViewExecutable) {
+            $token_replacements = ['view' => $entity];
+          }
+          else {
+            $token_replacements = [$entity->getEntityTypeId() => $entity];
+          }
         }
 
         // Set the value as sometimes the data needs massaging, such as when
@@ -303,15 +473,13 @@ class MetatagManager implements MetatagManagerInterface {
         $output = $tag->output();
 
         if (!empty($output)) {
-          $elements['#attached']['html_head'][] = [
-            $output,
-            $tag_name
-          ];
+          $rawTags[$tag_name] = $output;
         }
+
       }
     }
 
-    return $elements;
+    return $rawTags;
   }
 
   /**
@@ -320,7 +488,7 @@ class MetatagManager implements MetatagManagerInterface {
    * @return array
    */
   protected function fieldTypes() {
-    //@TODO: Either get this dynamically from field plugins or forget it and just hardcode metatag where this is called.
+    // @TODO: Either get this dynamically from field plugins or forget it and just hardcode metatag where this is called.
     return ['metatag'];
   }
 
diff --git a/src/MetatagManagerInterface.php b/src/MetatagManagerInterface.php
index 03aaa2f..ea429f5 100644
--- a/src/MetatagManagerInterface.php
+++ b/src/MetatagManagerInterface.php
@@ -3,6 +3,7 @@
 namespace Drupal\metatag;
 
 use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\views\ViewEntityInterface;
 
 /**
  * Class MetatagManager.
@@ -23,6 +24,20 @@ interface MetatagManagerInterface {
   public function tagsFromEntity(ContentEntityInterface $entity);
 
   /**
+   * Extracts all tags of a given view.
+   *
+   * @param \Drupal\views\ViewEntityInterface $view
+   *   The view to extract metatags from.
+   * @param string|null $display_id
+   *   The id of the display to extract metatags from.
+   *
+   * @return array
+   *   Array of metatags for a given display id of a view. Array is keyed by
+   *   display_id when null is passed.
+   */
+  public function tagsFromViewDisplay(ViewEntityInterface $view, $display_id = NULL);
+
+  /**
    * Returns an array of group plugin information sorted by weight.
    *
    * @return array
