diff --git a/tour/config/schema/tour.schema.yml b/tour/config/schema/tour.schema.yml
new file mode 100644
index 0000000..3975fb4
--- /dev/null
+++ b/tour/config/schema/tour.schema.yml
@@ -0,0 +1,60 @@
+# Schema for the configuration files of the Tour module.
+
+tour.tour.*:
+  type: mapping
+  label: 'Tour settings'
+  mapping:
+    id:
+      type: string
+      label: 'ID'
+    label:
+      type: label
+      label: 'Label'
+    langcode:
+      type: string
+      label: 'Language'
+    paths:
+      type: sequence
+      label: 'Path settings'
+      sequence:
+        - type: path
+          label: 'Path'
+    tips:
+      type: sequence
+      label: 'Tips'
+      sequence:
+        - type: tour.tip.[plugin]
+          label: 'Tour tip'
+
+tour.tip:
+  type: mapping
+  label: 'Tour tip'
+  mapping:
+    id:
+      type: string
+      label: 'ID'
+    plugin:
+      type: string
+      label: 'Plugin'
+    label:
+      type: label
+      label: 'Label'
+    weight:
+      type: integer
+      label: 'Weight'
+    attributes:
+      type: sequence
+      label: 'Attributes'
+      sequence:
+        - type: string
+          label: 'Attribute'
+
+tour.tip.text:
+  type: tour.tip
+  label: 'Textual tour tip'
+  mapping:
+    body:
+      type: text
+      label: 'Body'
+
+
diff --git "a/core/modules/tour/css/tour-rtl.css" b/tour/css/tour-rtl.css
index 5e19f7b..cef3d00 100644
--- "a/core/modules/tour/css/tour-rtl.css"
+++ b/tour/css/tour-rtl.css
@@ -3,7 +3,7 @@
  * RTL styling for tour module.
  */
 
-.js .toolbar .bar .tour-toolbar-tab.tab {
+.js .toolbar .tour-toolbar-tab.tab {
   float: left;
 }
 
diff --git "a/core/modules/tour/css/tour.css" b/tour/css/tour.css
index 9f71ccb..53dd50f 100644
--- "a/core/modules/tour/css/tour.css"
+++ b/tour/css/tour.css
@@ -4,23 +4,29 @@
  */
 
 /* Tab appearance. */
-.js .toolbar .bar .tour-toolbar-tab.tab {
+.js .toolbar .tour-toolbar-tab.tab {
   float: right; /* LTR */
 }
-.js .toolbar .bar .tour-toolbar-tab button {
+.js .toolbar .tour-toolbar-tab button {
   padding-bottom: 1em;
   padding-top: 1em;
   color: #fff;
   font-weight: bold;
+  cursor: pointer;
 }
-.js .toolbar .bar .tour-toolbar-tab button.active {
+.js .toolbar .tour-toolbar-tab button.active {
   background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%);
   background-image: linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%);
 }
+.js .tour-toolbar-tab button:focus {
+  outline: thin dotted;
+}
 
 /* Joyride tips should always be on top of everything else. */
 .joyride-tip-guide {
   z-index: 999;
+  width: auto;
+  height: auto;
 }
 
 /* Override placement of the tour progress indicator. */
@@ -31,6 +37,11 @@
 }
 
 /* @todo Remove once http://drupal.org/node/1916690 is resolved. */
-.js .toolbar .bar .tour-toolbar-tab.tab.element-hidden {
+.js .toolbar .tour-toolbar-tab.tab.element-hidden {
   display: none;
 }
+
+.YouTube {
+	width:400px;
+	height:225px;
+}
\ No newline at end of file
diff --git "a/core/modules/tour/js/tour.js" b/tour/js/tour.js
index d8885be..fde4f58 100644
--- "a/core/modules/tour/js/tour.js"
+++ b/tour/js/tour.js
@@ -14,7 +14,7 @@ Drupal.behaviors.tour = {
   attach: function (context) {
     $('body').once('tour', function (index, element) {
       var model = new Drupal.tour.models.StateModel();
-      var view = new Drupal.tour.views.ToggleTourView({
+      new Drupal.tour.views.ToggleTourView({
         el: $(context).find('#toolbar-tab-tour'),
         model: model
       });
@@ -102,7 +102,7 @@ Drupal.tour.views.ToggleTourView = Backbone.View.extend({
     var isActive = this.model.get('isActive');
     this.$el.find('button')
       .toggleClass('active', isActive)
-      .attr('aria-pressed', isActive);
+      .prop('aria-pressed', isActive);
     return this;
   },
 
@@ -177,10 +177,12 @@ Drupal.tour.views.ToggleTourView = Backbone.View.extend({
         var $this = $(this);
         var itemId = $this.attr('data-id');
         var itemClass = $this.attr('data-class');
-        if ($document.find('#' + itemId + ', .' + itemClass).length === 0) {
-          removals = true;
-          $this.remove();
+        if ((itemId && $document.find('#' + itemId).length) ||
+           (itemClass && $document.find('.' + itemClass).length)){
+          return;
         }
+        removals = true;
+        $this.remove();
       });
 
     // If there were removals, we'll have to do some clean-up.
@@ -201,4 +203,4 @@ Drupal.tour.views.ToggleTourView = Backbone.View.extend({
 
 });
 
-})(jQuery, Backbone, Drupal, document);
\ No newline at end of file
+})(jQuery, Backbone, Drupal, document);
diff --git a/tour/lib/Drupal/tour/Annotation/Tip.php b/tour/lib/Drupal/tour/Annotation/Tip.php
new file mode 100644
index 0000000..2351095
--- /dev/null
+++ b/tour/lib/Drupal/tour/Annotation/Tip.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tour\Annotation\Tip.
+ */
+
+namespace Drupal\tour\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+
+/**
+ * Defines a Tip annotation object.
+ *
+ * @Annotation
+ */
+class Tip extends Plugin {
+
+  /**
+   * The plugin ID.
+   *
+   * @var string
+   */
+  public $id;
+  
+  /**
+   * The title of the plugin.
+   *
+   * @var \Drupal\Core\Annotation\Translation
+   *
+   * @ingroup plugin_translatable
+   */
+  public $title;
+  
+  
+
+  
+
+}
diff --git "a/core/modules/tour/lib/Drupal/tour/Plugin/Core/Entity/Tour.php" b/tour/lib/Drupal/tour/Plugin/Core/Entity/Tour.php
index 549c3fa..2d36c71 100644
--- "a/core/modules/tour/lib/Drupal/tour/Plugin/Core/Entity/Tour.php"
+++ b/tour/lib/Drupal/tour/Plugin/Core/Entity/Tour.php
@@ -8,41 +8,50 @@
 namespace Drupal\tour\Plugin\Core\Entity;
 
 use Drupal\Core\Config\Entity\ConfigEntityBase;
-use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Annotation\Translation;
 use Drupal\tour\TipsBag;
+use Drupal\tour\TourInterface;
 
 /**
  * Defines the configured tour entity.
  *
- * @Plugin(
+ * @EntityType(
  *   id = "tour",
  *   label = @Translation("Tour"),
  *   module = "tour",
- *   controller_class = "Drupal\Core\Config\Entity\ConfigStorageController",
+ *   controllers = {
+ *     "storage" = "Drupal\Core\Config\Entity\ConfigStorageController",
+ *     "render" = "Drupal\tour\TourRenderController"
+ *   },
  *   config_prefix = "tour.tour",
  *   entity_keys = {
  *     "id" = "id",
  *     "label" = "label",
- *     "uuid" = "uuid",
+ *     "uuid" = "uuid"
  *   }
  * )
  */
-class Tour extends ConfigEntityBase {
+class Tour extends ConfigEntityBase implements TourInterface {
 
   /**
    * The name (plugin ID) of the tour.
    *
    * @var string
-   *   Unique identifier for this tour.
    */
   public $id;
 
   /**
+   * The module which this tour is assigned to.
+   *
+   * @var string
+   */
+  public $module;
+
+  /**
    * The label of the tour.
    *
    * @var string
-   *   A human readable name for this tour.
    */
   public $label;
 
@@ -73,59 +82,41 @@ class Tour extends ConfigEntityBase {
   public function __construct(array $values, $entity_type) {
     parent::__construct($values, $entity_type);
 
-    $this->tipsBag = new TipsBag(drupal_container()->get('plugin.manager.tour'), $this->tips);
+    $this->tipsBag = new TipsBag(drupal_container()->get('plugin.manager.tour.tip'), $this->tips);
   }
 
   /**
-   * Returns the ID of tour.
-   *
-   * @return string
-   *   The ID of the tour.
-   */
-  public function getId() {
-    return $this->id;
-  }
-
-  /**
-   * Returns label of tour.
-   *
-   * @return string
-   *   The label of the tour.
-   */
-  public function getLabel() {
-    return $this->label;
-  }
-
-  /**
-   * The paths that this tour will appear on.
-   *
-   * @return array
-   *   Returns array of paths for the tour.
+   * {@inheritdoc}
    */
   public function getPaths() {
     return $this->paths;
   }
 
   /**
-   * Returns tip plugin.
-   *
-   * @return string
-   *   The identifier of the tip.
+   * {@inheritdoc}
    */
   public function getTip($id) {
     return $this->tipsBag->get($id);
   }
 
   /**
-   * Returns a list of tips.
-   *
-   * @return array
-   *   A list of tips.
+   * {@inheritdoc}
    */
-  public function getTipList() {
-    if (!empty($this->tips)) {
-      return array_keys($this->tips);
+  public function getTips() {
+    $tips = array();
+    foreach ($this->tips as $id => $tip) {
+      $tips[$id] = $this->getTip($id);
     }
+    uasort($tips, function ($a, $b) {
+      if ($a->get('weight') == $b->get('weight')) {
+        return 0;
+      }
+      return ($a->get('weight') < $a->get('weight')) ? -1 : 1;
+    });
+
+   \Drupal::service('module_handler')->alter('tour_tips', $tips, $this);
+    return $tips;
+
   }
 
   /**
@@ -134,8 +125,6 @@ class Tour extends ConfigEntityBase {
   public function getExportProperties() {
     $properties = parent::getExportProperties();
     $names = array(
-      'id',
-      'label',
       'paths',
       'tips',
     );
@@ -144,4 +133,5 @@ class Tour extends ConfigEntityBase {
     }
     return $properties;
   }
+
 }
diff --git a/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginImageLocal.php b/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginImageLocal.php
new file mode 100644
index 0000000..76d34b8
--- /dev/null
+++ b/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginImageLocal.php
@@ -0,0 +1,153 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tour_test\Plugin\tour\tip\TipPluginImageLocal.
+ */
+
+namespace Drupal\tour\Plugin\tour\tip;
+
+use Drupal\tour\Annotation\Tip;
+use Drupal\tour\TipPluginBase;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Displays an image as a tip.
+ *
+ * @Tip(id = "imagelocal",
+ *		title = @Translation("Image-local")
+ * )
+ */
+class TipPluginImageLocal extends TipPluginBase {
+
+  /**
+   * The url which is used for the image in this Tip.
+   *
+   * @var string
+   *   A url used for the image.
+   */
+  protected $imagelocal;
+
+  /**
+   * The alt text which is used for the image in this Tip.
+   *
+   * @var string
+   *   Alt text used for the image.
+   */
+  protected $alt;
+    
+    
+ /**
+   * Returns a ID that is guaranteed uniqueness.
+   *
+   * @return string
+   *   A unique id to be used to generate aria attributes.
+   */
+  public function getAriaId() {
+    static $id;
+    if (!isset($id)) {
+      $id = drupal_html_id($this->get('id'));
+    }
+    return $id;
+  } 
+    
+  /**
+   * Overrides \Drupal\tour\TipPluginBase::getAttributes().
+   */
+  public function getAttributes() {
+    $attributes = parent::getAttributes();
+    $attributes['data-aria-describedby'] = 'tour-tip-' . $this->getAriaId() . '-contents';
+    $attributes['data-aria-labelledby'] = 'tour-tip-' . $this->getAriaId() . '-label';
+    if ($location = $this->get('location')) {
+      $attributes['data-options'] = 'tipLocation:' . $location;
+    }
+    return $attributes;
+  }
+
+  /**
+   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::export();
+   */
+  public function export() {
+    $properties = parent::export();
+    $names = array(
+      'imagelocal',
+	  'alt',
+      'location',
+    );	
+	
+    foreach ($names as $name) {
+      $properties[$name] = $this->get($name);
+    }
+    return $properties;
+  }
+
+  
+   public function arrayToStringNum($tmp){
+	$glop = (string)$tmp[0];
+	return $glop;
+   }
+   
+   public function stringNumToArray($tmp){
+	$glop = array((int)$tmp);
+	return $glop;
+   }
+  
+  
+  /**
+   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::optionsForm().
+   */
+  public function optionsForm() {
+    $form = parent::optionsForm();
+    $form['location'] = array(
+      '#type' => 'select',
+      '#title' => t('Location'),
+      '#options' => array(
+        'top' => t('Top'),
+        'bottom' => t('Bottom'),
+        'left' => t('Left'),
+        'right' => t('Right'),
+      ),
+      '#default_value' => $this->get('location'),
+    );
+	
+	// Use the #managed_file FAPI element to upload an image file.
+	$form['imagelocal'] = array(
+	'#title' => t('Local Computer Image'),
+	'#type' => 'managed_file',
+	'#description' => t('The uploaded image will be displayed on this page using the image style choosen below.'),
+	'#default_value' => $this->get('imagelocal'),
+	'#upload_location' => 'public://images/',
+	'#required' => TRUE,
+	);
+	
+	/*
+	$form['image2'] = array(
+		'#type' => 'hidden',
+		'#value' => $this->arrayToStringNum($this->get('imagelocal')),
+	);
+	*/
+	
+	$form['alt'] = array(
+      '#type' => 'textfield',
+	  '#size' => 80,
+      '#title' => t('Alt Text'),
+      '#required' => FALSE,
+      '#default_value' => $this->get('alt'),
+	  '#description' => t('The alt text which is used for the image in this Tip'),
+    );
+    return $form;
+  }
+   
+  /**
+   * Overrides \Drupal\tour\Plugin\tour\tour\TipPluginInterface::getOutput().
+   */
+  public function getOutput() {
+	global $base_url;
+	$file = file_load($this->get('imagelocal'));
+    $output = '<h2 class="tour-tip-label" id="tour-tip-' . $this->get('ariaId') . '-label">' . check_plain($this->get('label')) . '</h2>';
+    $output .= '<p class="tour-tip-image" id="tour-tip-' . $this->get('ariaId') . '-contents">' . theme('image', array('uri' => $base_url . '/sites/default/files/images/' . $file->filename, 'alt' => $this->get('alt'))) . '</p>';
+    return array('#markup' => $output);
+  }
+
+}
+
diff --git a/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginImageURL.php b/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginImageURL.php
new file mode 100644
index 0000000..7c35a3b
--- /dev/null
+++ b/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginImageURL.php
@@ -0,0 +1,144 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tour\Plugin\tour\tip\TipPluginImageURL.
+ */
+
+namespace Drupal\tour\Plugin\tour\tip;
+
+use Drupal\tour\Annotation\Tip;
+use Drupal\tour\TipPluginBase;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Displays an image as a tip.
+ *
+ * @Tip(id = "imageURL",
+ *		title = @Translation("ImageURL")
+ * )
+ */
+class TipPluginImageURL extends TipPluginBase {
+
+  /**
+   * The url which is used for the image in this Tip.
+   *
+   * @var string
+   *   A url used for the image.
+   */
+  protected $imageURL;
+
+  /**
+   * The alt text which is used for the image in this Tip.
+   *
+   * @var string
+   *   Alt text used for the image.
+   */
+  protected $alt;
+    
+    
+ /**
+   * Returns a ID that is guaranteed uniqueness.
+   *
+   * @return string
+   *   A unique id to be used to generate aria attributes.
+   */
+  public function getAriaId() {
+    static $id;
+    if (!isset($id)) {
+      $id = drupal_html_id($this->get('id'));
+    }
+    return $id;
+  } 
+    
+  /**
+   * Overrides \Drupal\tour\TipPluginBase::getAttributes().
+   */
+  public function getAttributes() {
+    $attributes = parent::getAttributes();
+    $attributes['data-aria-describedby'] = 'tour-tip-' . $this->getAriaId() . '-contents';
+    $attributes['data-aria-labelledby'] = 'tour-tip-' . $this->getAriaId() . '-label';
+    if ($location = $this->get('location')) {
+      $attributes['data-options'] = 'tipLocation:' . $location;
+    }
+    return $attributes;
+  }
+
+  /**
+   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::export();
+   */
+  public function export() {
+    $properties = parent::export();
+    $names = array(
+      'imageURL',
+	  'alt',
+      'location',
+    );	
+	
+    foreach ($names as $name) {
+      $properties[$name] = $this->get($name);
+    }
+    return $properties;
+  }
+
+  
+   public function arrayToStringNum($tmp){
+	$glop = (string)$tmp[0];
+	return $glop;
+   }
+   
+   public function stringNumToArray($tmp){
+	$glop = array((int)$tmp);
+	return $glop;
+   }
+  
+  
+  /**
+   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::optionsForm().
+   */
+  public function optionsForm() {
+    $form = parent::optionsForm();
+    $form['location'] = array(
+      '#type' => 'select',
+      '#title' => t('Location'),
+      '#options' => array(
+        'top' => t('Top'),
+        'bottom' => t('Bottom'),
+        'left' => t('Left'),
+        'right' => t('Right'),
+      ),
+      '#default_value' => $this->get('location'),
+    );
+	
+	$form['imageURL'] = array(
+	  '#type' => 'textfield',
+	  '#size' => 80,
+      '#title' => t('Image URL'),
+      '#required' => TRUE,
+      '#default_value' => $this->get('imageURL'),
+	  '#description' => t('The URL which is used for the image in this Tip'),
+	);
+	
+	$form['alt'] = array(
+      '#type' => 'textfield',
+	  '#size' => 80,
+      '#title' => t('Alt Text'),
+      '#required' => FALSE,
+      '#default_value' => $this->get('alt'),
+	  '#description' => t('The alt text which is used for the image in this Tip'),
+    );
+    return $form;
+  }
+   
+  /**
+   * Overrides \Drupal\tour\Plugin\tour\tour\TipPluginInterface::getOutput().
+   */
+  public function getOutput() {
+	global $base_url;
+    $output = '<h2 class="tour-tip-label" id="tour-tip-' . $this->get('ariaId') . '-label">' . check_plain($this->get('label')) . '</h2>';
+    $output .= '<p class="tour-tip-image" id="tour-tip-' . $this->get('ariaId') . '-contents">' . theme('image', array('uri' => $this->get('imageURL'), 'alt' => $this->get('alt'))) . '</p>';
+    return array('#markup' => $output);
+  }
+
+}
+
diff --git "a/core/modules/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginText.php" b/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginText.php
index aebe888..9eb69bb 100644
--- "a/core/modules/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginText.php"
+++ b/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginText.php
@@ -2,22 +2,22 @@
 
 /**
  * @file
- * Contains \Drupal\tour\TipPluginText.
+ * Contains \Drupal\tour\Plugin\tour\tip\TipPluginText.
  */
 
 namespace Drupal\tour\Plugin\tour\tip;
 
-use Drupal\Core\Annotation\Plugin;
+use Drupal\tour\Annotation\Tip;
 use Drupal\tour\TipPluginBase;
+use Drupal\Core\Annotation\Translation;
 
 /**
  * Displays some text as a tip.
  *
- * @Plugin(
- *   id = "text",
- *   label = "Text",
- *   module = "tour"
+ * @Tip(id = "text", 
+ *      title = @Translation("Text")
  * )
+ *
  */
 class TipPluginText extends TipPluginBase {
 
@@ -25,7 +25,6 @@ class TipPluginText extends TipPluginBase {
    * The body text which is used for render of this Text Tip.
    *
    * @var string
-   *   A string of text used as the body.
    */
   protected $body;
 
@@ -33,7 +32,6 @@ class TipPluginText extends TipPluginBase {
    * The forced position of where the tip will be located.
    *
    * @var string
-   *   A string of left|right|top|bottom.
    */
   protected $location;
 
@@ -41,38 +39,18 @@ class TipPluginText extends TipPluginBase {
    * Returns a ID that is guaranteed uniqueness.
    *
    * @return string
-   *   A unique string.
+   *   A unique id to be used to generate aria attributes.
    */
   public function getAriaId() {
     static $id;
     if (!isset($id)) {
-      $id = drupal_html_id($this->getId());
+      $id = drupal_html_id($this->get('id'));
     }
     return $id;
   }
 
   /**
-   * Returns body of the text tip.
-   *
-   * @return string
-   *   The body of the text tip.
-   */
-  public function getBody() {
-    return $this->get('body');
-  }
-
-  /**
-   * Returns location of the text tip.
-   *
-   * @return string
-   *   The location (left|right|top|bottom) of the text tip.
-   */
-  public function getLocation() {
-    return $this->get('location');
-  }
-
-  /**
-   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::getAttributes();
+   * Overrides \Drupal\tour\TipPluginBase::getAttributes().
    */
   public function getAttributes() {
     $attributes = parent::getAttributes();
@@ -84,20 +62,12 @@ class TipPluginText extends TipPluginBase {
     return $attributes;
   }
 
-  /**
-   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::getOutput();
-   */
-  public function getOutput() {
-    $output = '<h2 class="tour-tip-label" id="tour-tip-' . $this->getAriaId() . '-label">' . check_plain($this->getLabel()) . '</h2>';
-    $output .= '<p class="tour-tip-body" id="tour-tip-' . $this->getAriaId() . '-contents">' . filter_xss_admin($this->getBody()) . '</p>';
-    return array('#markup' => $output);
-  }
 
   /**
-   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::getExportProperties().
+   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::export();
    */
-  public function getExportProperties() {
-    $properties = parent::getExportProperties();
+  public function export() {
+    $properties = parent::export();
     $names = array(
       'body',
       'location',
@@ -118,19 +88,31 @@ class TipPluginText extends TipPluginBase {
       '#title' => t('Location'),
       '#options' => array(
         'top' => t('Top'),
-        'bottom' => t('Button'),
+        'bottom' => t('Bottom'),
         'left' => t('Left'),
         'right' => t('Right'),
       ),
-      '#default_value' => $this->getLocation(),
+      '#default_value' => $this->get('location'),
     );
     $form['body'] = array(
       '#type' => 'textarea',
       '#title' => t('Body'),
       '#required' => TRUE,
-      '#default_value' => $this->getBody(),
+      '#default_value' => $this->get('body'),
     );
     return $form;
   }
 
+
+  /**
+   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::getOutput();
+   */
+  public function getOutput() {
+    $output = '<h2 class="tour-tip-label" id="tour-tip-' . $this->getAriaId() . '-label">' . check_plain($this->get('label')) . '</h2>';
+    $output .= '<p class="tour-tip-body" id="tour-tip-' . $this->getAriaId() . '-contents">' . filter_xss_admin($this->get('body')) . '</p>';
+    return array('#markup' => $output);
+  }
+  
+  
+
 }
diff --git a/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginYouTube.php b/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginYouTube.php
new file mode 100644
index 0000000..ec6c43a
--- /dev/null
+++ b/tour/lib/Drupal/tour/Plugin/tour/tip/TipPluginYouTube.php
@@ -0,0 +1,173 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tour\Plugin\tour\tip\TipPluginYouTube.
+ */
+
+namespace Drupal\tour\Plugin\tour\tip;
+
+use Drupal\tour\Annotation\Tip;
+use Drupal\tour\TipPluginBase;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Displays a Youtube Video as a tip.
+ *
+ * @Tip(id = "youtube",
+ *      title = @Translation("YouTube")
+ * )
+ */
+class TipPluginYouTube extends TipPluginBase {
+
+  /**
+   * The url which is used for the image in this Tip.
+   *
+   * @var string
+   *   A url used for the image.
+   */
+  protected $ytID;
+
+  /**
+   * The alt text which is used for the image in this Tip.
+   *
+   * @var string
+   *   A alt text used for the image.
+   */
+  protected $alt;
+
+ /**
+   * The width of video in this Tip.
+   *
+   * @var string
+   *   Width used for the video.
+   */
+  protected $width;
+  
+  
+  /**
+   * The height for the image in this Tip.
+   *
+   * @var string
+   *   Height used for the video.
+   */
+  
+  protected $height;
+  
+  
+   /**
+   * Returns a ID that is guaranteed uniqueness.
+   *
+   * @return string
+   *   A unique id to be used to generate aria attributes.
+   */
+  public function getAriaId() {
+    static $id;
+    if (!isset($id)) {
+      $id = drupal_html_id($this->get('id'));
+    }
+    return $id;
+  }
+ 
+ 
+ 
+ /**
+   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::export();
+   */
+  public function export() {
+    $properties = parent::export();
+    $names = array(
+      'ytID',
+	  'video',
+      'location',
+    );
+	
+    foreach ($names as $name) {
+		$properties[$name] = $this->get($name);
+    }
+    return $properties;
+  }
+
+  /**
+   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::optionsForm().
+   */
+  public function optionsForm() {
+    $form = parent::optionsForm();
+	
+    $form['location'] = array(
+      '#type' => 'select',
+      '#title' => t('Location'),
+      '#options' => array(
+        'top' => t('Top'),
+        'bottom' => t('Bottom'),
+        'left' => t('Left'),
+        'right' => t('Right'),
+      ),
+      '#default_value' => $this->get('location'),
+    );
+	
+	
+	$form['ytID'] = array(
+      '#type' => 'textfield',
+	  '#size' => 30,
+      '#title' => t('YouTube Video Identifier'),
+      '#required' => TRUE,
+      '#default_value' => $this->get('ytID'),
+	  '#description' => t('The YouTube Identifier for the<br /> video in this Tip. ie.( DeLT0g0t25Q )'),
+    );
+	
+	$form['video'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Video Details'),
+      '#collapsible' => TRUE,
+      '#collapsed' => FALSE,
+      '#tree' => TRUE,
+	  '#description' => t('Default dimensions have 1.78:1 Aspect Ratio, (16x9)'),
+    );
+
+	$form['video']['width'] = array(
+      '#type' => 'textfield',
+	  '#size' => 20,
+      '#title' => t('Video Width'),
+      '#required' => FALSE,
+      '#default_value' => $this->get('video')['width'],
+	  '#description' => t('The width for the video in this Tip'),
+    );
+
+	$form['video']['height'] = array(
+      '#type' => 'textfield',
+	  '#size' => 20,
+      '#title' => t('Video Height'),
+      '#required' => FALSE,
+      '#default_value' => $this->get('video')['height'],
+	  '#description' => t('The height for the video in this Tip'),
+    );
+
+	return $form;
+ }
+ 
+ /**
+   * Overrides \Drupal\tour\TipPluginBase::getAttributes().
+   */
+  public function getAttributes() {
+    $attributes = parent::getAttributes();
+    $attributes['data-aria-describedby'] = 'tour-tip-' . $this->getAriaId() . '-contents';
+    $attributes['data-aria-labelledby'] = 'tour-tip-' . $this->getAriaId() . '-label';
+    if ($location = $this->get('location')) {
+      $attributes['data-options'] = 'tipLocation:' . $location;
+    }
+    return $attributes;
+  }
+ 
+ 
+ /**
+   * Overrides \Drupal\tour\Plugin\tour\tour\TipPluginInterface::getOutput().
+   */
+  public function getOutput() {
+ 
+    $output = '<h2 class="tour-tip-label" id="tour-tip-' . $this->get('ariaId') . '-label">' . check_plain($this->get('label')) . '</h2>';
+    $output .= '<p class="tour-tip-youtube" id="tour-tip-' . $this->get('ariaId') . '-contents">' . '<iframe class="YouTube" style="width:' . $this->get('video')['width'] . 'px;height:' . $this->get('video')['height'] . 'px" frameborder="0" allowfullscreen="1" title="YouTube video player" width="100%" height="100%" src="http://www.youtube.com/embed/' . $this->get('ytID')  . '?wmode=transparent&enablejsapi=1&origin=http://localhost"></iframe></p>';
+    return array('#markup' => $output);
+  }
+
+}
diff --git "a/core/modules/tour/lib/Drupal/tour/Tests/TourPluginTest.php" b/tour/lib/Drupal/tour/Tests/TourPluginTest.php
index 8256eed..460e497 100644
--- "a/core/modules/tour/lib/Drupal/tour/Tests/TourPluginTest.php"
+++ b/tour/lib/Drupal/tour/Tests/TourPluginTest.php
@@ -24,7 +24,7 @@ class TourPluginTest extends DrupalUnitTestBase {
   /**
    * Stores the tour plugin manager.
    *
-   * @var \Drupal\tour\TourManager
+   * @var \Drupal\tour\TipPluginManager
    */
   protected $pluginManager;
 
@@ -40,7 +40,7 @@ class TourPluginTest extends DrupalUnitTestBase {
     parent::setUp();
 
     config_install_default_config('module', 'tour');
-    $this->pluginManager = $this->container->get('plugin.manager.tour');
+    $this->pluginManager = $this->container->get('plugin.manager.tour.tip');
   }
 
   /**
diff --git "a/core/modules/tour/lib/Drupal/tour/Tests/TourTest.php" b/tour/lib/Drupal/tour/Tests/TourTest.php
index 6e45d3f..d3c77da 100644
--- "a/core/modules/tour/lib/Drupal/tour/Tests/TourTest.php"
+++ b/tour/lib/Drupal/tour/Tests/TourTest.php
@@ -40,9 +40,10 @@ class TourTest extends WebTestBase {
    * Test tour functionality.
    */
   public function testTourFunctionality() {
-    // Navigate to tour-test-1 and verify the tour_test_1 tip is found.
+    // Navigate to tour-test-1 and verify the tour_test_1 tip is found with appropriate classes.
     $this->drupalGet('tour-test-1');
-    $elements = $this->xpath('//li[@data-id=:data_id and ./h2[contains(., :text)]]', array(
+    $elements = $this->xpath('//li[@data-id=:data_id and @class=:classes and ./h2[contains(., :text)]]', array(
+      ':classes' => 'tip-module-tour-test tip-type-text tip-tour-test-1 even last',
       ':data_id' => 'tour-test-1',
       ':text' => 'The first tip',
     ));
diff --git "a/core/modules/tour/lib/Drupal/tour/TipPluginBase.php" b/tour/lib/Drupal/tour/TipPluginBase.php
index e597400..e3a0b81 100644
--- "a/core/modules/tour/lib/Drupal/tour/TipPluginBase.php"
+++ b/tour/lib/Drupal/tour/TipPluginBase.php
@@ -8,7 +8,6 @@
 namespace Drupal\tour;
 
 use Drupal\Component\Plugin\PluginBase;
-use Drupal\Core\Plugin\Discovery\CacheDecorator;
 use Drupal\tour\TipPluginInterface;
 
 /**
@@ -20,7 +19,6 @@ abstract class TipPluginBase extends PluginBase implements TipPluginInterface {
    * The label which is used for render of this tip.
    *
    * @var string
-   *   The label of this tip.
    */
   protected $label;
 
@@ -28,7 +26,6 @@ abstract class TipPluginBase extends PluginBase implements TipPluginInterface {
    * Allows tips to take more priority that others.
    *
    * @var string
-   *   A number which pertains to ordering.
    */
   protected $weight;
 
@@ -36,57 +33,32 @@ abstract class TipPluginBase extends PluginBase implements TipPluginInterface {
    * The attributes that will be applied to the markup of this tip.
    *
    * @var array
-   *   An array of attributes.
    */
   protected $attributes;
 
   /**
-   * Overrides \Drupal\Component\Plugin\PluginBase::__construct().
-   */
-  public function __construct(array $configuration, $plugin_id, CacheDecorator $discovery) {
-    parent::__construct($configuration, $plugin_id, $discovery);
-
-    $this->definition = $this->discovery->getDefinition($plugin_id);
-    $this->module = $this->definition['module'];
-  }
-
-  /**
-   * Implements \Drupal\tour\Plugin\tour\tour\TourPluginInterface::getId().
-   */
-  public function getId() {
-    return $this->get('id');
-  }
-
-  /**
-   * Implements \Drupal\tour\Plugin\tour\tour\TourPluginInterface::getPlugin().
-   */
-  public function getPlugin() {
-    return $this->get('plugin');
-  }
-
-  /**
-   * Implements \Drupal\tour\Plugin\tour\tour\TourPluginInterface::getLabel().
+   * Implements \Drupal\tour\TipPluginInterface::getLabel().
    */
   public function getLabel() {
     return $this->get('label');
   }
 
   /**
-   * Implements \Drupal\tour\Plugin\tour\tour\TourPluginInterface::getWeight().
+   * Implements \Drupal\tour\TipPluginInterface::getWeight().
    */
   public function getWeight() {
     return $this->get('weight');
   }
 
   /**
-   * Implements \Drupal\tour\Plugin\tour\tour\TourPluginInterface::getAttributes().
+   * Implements \Drupal\tour\TipPluginInterface::getAttributes().
    */
   public function getAttributes() {
     return $this->get('attributes');
   }
 
   /**
-   * Implements \Drupal\tour\Plugin\tour\tour\TourPluginInterface::get().
+   * Implements \Drupal\tour\TipPluginInterface::get().
    */
   public function get($key) {
     if (!empty($this->configuration[$key])) {
@@ -95,16 +67,18 @@ abstract class TipPluginBase extends PluginBase implements TipPluginInterface {
   }
 
   /**
-   * Implements \Drupal\tour\Plugin\tour\tour\TourPluginInterface::set().
+   * Implements \Drupal\tour\TipPluginInterface::set().
    */
   public function set($key, $value) {
     $this->configuration[$key] = $value;
   }
-
+  
+  
+  
   /**
-   * Implements \Drupal\tour\Plugin\tour\tour\TourPluginInterface::getExportProperties().
+   * Implements \Drupal\tour\Plugin\tour\tour\TourPluginInterface::export().
    */
-  public function getExportProperties() {
+  public function export() {
     $names = array(
       'id',
       'plugin',
@@ -123,12 +97,12 @@ abstract class TipPluginBase extends PluginBase implements TipPluginInterface {
    */
   public function optionsForm() {
     $form = array();
-    $id = $this->getId();
+    $id = $this->get('id');
     $form['label'] = array(
       '#type' => 'textfield',
       '#title' => t('Label'),
       '#required' => TRUE,
-      '#default_value' => $this->getLabel(),
+      '#default_value' => $this->get('label'),
     );
     $form['id'] = array(
       '#type' => 'machine_name',
@@ -142,39 +116,123 @@ abstract class TipPluginBase extends PluginBase implements TipPluginInterface {
     );
     $form['plugin'] = array(
       '#type' => 'value',
-      '#value' => $this->getPlugin(),
+      '#value' => $this->get('plugin'),
     );
     $form['weight'] = array(
       '#type' => 'weight',
       '#title' => t('Weight'),
-      '#default_value' => $this->getWeight(),
+      '#default_value' => $this->get('weight'),
       '#attributes' => array(
         'class' => array('tip-order-weight'),
       ),
     );
+
     $attributes = $this->getAttributes();
     $form['attributes'] = array(
-      '#type' => 'fieldset', 
-      '#title' => t('Attributes'), 
-      '#collapsible' => TRUE, 
+      '#type' => 'fieldset',
+      '#title' => t('Attributes'),
+      '#collapsible' => TRUE,
       '#collapsed' => FALSE,
       '#tree' => TRUE,
     );
+
+    // Determine the type identifier of the tip.
+    if (!empty($attributes['data-id'])) {
+      $tip_type = 'data-id';
+    }
+    else if (!empty($attributes['data-class'])) {
+      $tip_type = 'data-class';
+    }
+    else {
+      $tip_type = 'modal';
+    }
+    $form['attributes']['selector_type'] = array(
+      '#type' => 'select',
+      '#title' => t('Selector type'),
+      '#description' => t('The type of selector this tip will target.'),
+      '#options' => array(
+        'data-id' => t('Data ID'),
+        'data-class' => t('Data Class'),
+        'modal' => t('Modal'),
+      ),
+      '#default_value' => $tip_type,
+      '#element_validate' => array(array($this, 'optionsFormValidate')),
+    );
     $form['attributes']['data-id'] = array(
       '#type' => 'textfield',
       '#title' => t('Data id'),
-      '#description' => t('Provide a id selector for this tip to be attached to on the specified tour page. If this and <em>Data class</em> field is not specified the tip will be a modal.'),
+      '#description' => t('Provide the ID of the page element.'),
       '#field_prefix' => '#',
       '#default_value' => !empty($attributes['data-id']) ? $attributes['data-id'] : '',
+      '#states' => array(
+        'visible' => array(
+          'select[name="attributes[selector_type]"]' => array('value' => 'data-id'),
+        ),
+        'enabled' => array(
+          'select[name="attributes[selector_type]"]' => array('value' => 'data-id'),
+        ),
+      ),
     );
     $form['attributes']['data-class'] = array(
       '#type' => 'textfield',
       '#title' => t('Data class'),
-      '#description' => t('Provide a class selector for this tip to be attached to on the specified tour page. If this and <em>Data id</em> field is not specified the tip will be a modal.'),
+      '#description' => t('Provide the Class of the page element.'),
       '#field_prefix' => '.',
       '#default_value' => !empty($attributes['data-class']) ? $attributes['data-class'] : '',
+      '#states' => array(
+        'visible' => array(
+          'select[name="attributes[selector_type]"]' => array('value' => 'data-class'),
+        ),
+        'enabled' => array(
+          'select[name="attributes[selector_type]"]' => array('value' => 'data-class'),
+        ),
+      ),
     );
     return $form;
   }
 
+  /**
+   * Validates the tip optionsForm().
+   *
+   * @param $element
+   *   The form element that has the validate attached.
+   *
+   * @param $form_state
+   *   The state of the form after submission.
+   *
+   * @param $form
+   *   The form array.
+   */
+  function optionsFormValidate($element, &$form_state, $form) {
+    $values = $form_state['values'];
+    $selector_type = $values['attributes']['selector_type'];
+    unset($form_state['values']['attributes']['selector_type']);
+
+    // If modal we need to ensure that there is no data-id or data-class specified.
+    if ($selector_type == 'modal') {
+      unset($form_state['values']['attributes']['data-id']);
+      unset($form_state['values']['attributes']['data-class']);
+    }
+
+    // If data-id was selected and no id provided.
+    if ($selector_type == 'data-id' && empty($values['attributes']['data-id'])) {
+      form_error($form['attributes']['data-id'], t('Please provide a data id.'));
+    }
+
+    // If data-class was selected and no class provided.
+    if ($selector_type == 'data-class' && empty($values['attributes']['data-class'])) {
+      form_error($form['attributes']['data-class'], t('Please provide a data class.'));
+    }
+
+    // Remove the data-class value if data-id is provided.
+    if ($selector_type == 'data-id') {
+      unset($form_state['values']['attributes']['data-class']);
+    }
+
+    // Remove the data-id value is data-class is provided.
+    if ($selector_type == 'data-class') {
+      unset($form_state['values']['attributes']['data-id']);
+    }
+  }
+
 }
diff --git "a/core/modules/tour/lib/Drupal/tour/TipPluginInterface.php" b/tour/lib/Drupal/tour/TipPluginInterface.php
index bfbe872..bb89866 100644
--- "a/core/modules/tour/lib/Drupal/tour/TipPluginInterface.php"
+++ b/tour/lib/Drupal/tour/TipPluginInterface.php
@@ -13,22 +13,6 @@ namespace Drupal\tour;
 interface TipPluginInterface {
 
   /**
-   * Returns id of the tip.
-   *
-   * @return string
-   *   The id of the tip.
-   */
-  public function getId();
-
-  /**
-   * Returns plugin of the tip.
-   *
-   * @return string
-   *   The plugin of the tip.
-   */
-  public function getPlugin();
-
-  /**
    * Returns label of the tip.
    *
    * @return string
@@ -82,20 +66,4 @@ interface TipPluginInterface {
    */
   public function getOutput();
 
-  /**
-   * Retrieves the exportable properties of the plugin.
-   *
-   * @return array
-   *   An array of exportable properties and their values.
-   */
-  public function getExportProperties();
-
-  /**
-   * Provides a form for creation of this type of tip.
-   *
-   * @return array
-   *   An renderable form.
-   */
-  public function optionsForm();
-
 }
diff --git a/tour/lib/Drupal/tour/TipPluginManager.php b/tour/lib/Drupal/tour/TipPluginManager.php
new file mode 100644
index 0000000..4fc8b99
--- /dev/null
+++ b/tour/lib/Drupal/tour/TipPluginManager.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tour\TipPluginManager.
+ */
+
+namespace Drupal\tour;
+
+use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Component\Plugin\Factory\DefaultFactory;
+use Drupal\Core\Plugin\Discovery\AlterDecorator;
+use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
+use Drupal\Core\Plugin\Discovery\CacheDecorator;
+use Drupal\Component\Plugin\Discovery\ProcessDecorator;
+
+/**
+ * Configurable tour manager.
+ */
+class TipPluginManager extends PluginManagerBase {
+
+  /**
+   * Overrides \Drupal\Component\Plugin\PluginManagerBase::__construct().
+   *
+   * @param \Traversable $namespaces
+   *   An object that implements \Traversable which contains the root paths
+   *   keyed by the corresponding namespace to look for plugin implementations,
+   */
+  public function __construct(\Traversable $namespaces) {
+    $annotation_namespaces = array('Drupal\tour\Annotation' => $namespaces['Drupal\tour']);
+    $this->discovery = new AnnotatedClassDiscovery('tour/tip', $namespaces, $annotation_namespaces, 'Drupal\tour\Annotation\Tip');
+    $this->discovery = new AlterDecorator($this->discovery, 'tour_tips_info');
+    $this->discovery = new CacheDecorator($this->discovery, 'tour');
+
+    $this->factory = new DefaultFactory($this->discovery);
+  }
+
+}
diff --git "a/core/modules/tour/lib/Drupal/tour/TipsBag.php" b/tour/lib/Drupal/tour/TipsBag.php
index 99c2ecf..52ef292 100644
--- "a/core/modules/tour/lib/Drupal/tour/TipsBag.php"
+++ b/tour/lib/Drupal/tour/TipsBag.php
@@ -16,6 +16,7 @@ use Drupal\Component\Utility\NestedArray;
  * A collection of tips.
  */
 class TipsBag extends PluginBag {
+
   /**
    * The initial configuration for each tip in the bag.
    *
@@ -70,10 +71,11 @@ class TipsBag extends PluginBag {
       if (isset($this->configurations[$instance_id])) {
         $configuration = NestedArray::mergeDeep($configuration, $this->configurations[$instance_id]);
       }
-      $this->pluginInstances[$instance_id] = $this->manager->createInstance($type, $configuration, $this);
+      $this->pluginInstances[$instance_id] = $this->manager->createInstance($type, $configuration);
     }
     else {
       throw new PluginException(format_string("Unknown tip plugin ID '@tip'.", array('@tip' => $instance_id)));
     }
   }
+
 }
diff --git "a/core/modules/tour/lib/Drupal/tour/TourBundle.php" "b/core/modules/tour/lib/Drupal/tour/TourBundle.php"
deleted file mode 100644
index 337a672..0000000
--- "a/core/modules/tour/lib/Drupal/tour/TourBundle.php"
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\tour\TourBundle.
- */
-
-namespace Drupal\tour;
-
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\HttpKernel\Bundle\Bundle;
-
-/**
- * Tour dependency injection container.
- */
-class TourBundle extends Bundle {
-
-  /**
-   * Overrides \Symfony\Component\HttpKernel\Bundle\Bundle::build().
-   */
-  public function build(ContainerBuilder $container) {
-    // Register the plugin manager for our plugin type with the dependency
-    // injection container.
-    $container->register('plugin.manager.tour', 'Drupal\tour\TourManager');
-  }
-}
diff --git a/tour/lib/Drupal/tour/TourInterface.php b/tour/lib/Drupal/tour/TourInterface.php
new file mode 100644
index 0000000..4678a7b
--- /dev/null
+++ b/tour/lib/Drupal/tour/TourInterface.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tour\Plugin\Core\Entity\TourInterface.
+ */
+
+namespace Drupal\tour;
+
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+
+/**
+ * Provides an interface defining a tour entity.
+ */
+interface TourInterface extends ConfigEntityInterface {
+
+  /**
+   * The paths that this tour will appear on.
+   *
+   * @return array
+   *   Returns array of paths for the tour.
+   */
+  public function getPaths();
+
+  /**
+   * Returns tip plugin.
+   *
+   * @param string $id
+   *   The identifier of the tip.
+   *
+   * @return \Drupal\tour\TipPluginInterface
+   *   The tip plugin.
+   */
+  public function getTip($id);
+
+  /**
+   * Returns the tips for this tour.
+   *
+   * @return array
+   *   An array of tip plugins.
+   */
+  public function getTips();
+
+}
diff --git "a/core/modules/tour/lib/Drupal/tour/TourManager.php" "b/core/modules/tour/lib/Drupal/tour/TourManager.php"
deleted file mode 100644
index ee44c9b..0000000
--- "a/core/modules/tour/lib/Drupal/tour/TourManager.php"
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\tour\TourManager.
- */
-
-namespace Drupal\tour;
-
-use Drupal\Component\Plugin\PluginManagerBase;
-use Drupal\Component\Plugin\Factory\DefaultFactory;
-use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
-use Drupal\Core\Plugin\Discovery\CacheDecorator;
-use Drupal\Component\Plugin\Discovery\ProcessDecorator;
-
-/**
- * Configurable tour manager.
- */
-class TourManager extends PluginManagerBase {
-
-  /**
-   * Overrides \Drupal\Component\Plugin\PluginManagerBase::__construct().
-   */
-  public function __construct() {
-    $this->discovery = new AnnotatedClassDiscovery('tour', 'tip');
-    $this->discovery = new ProcessDecorator($this->discovery, array($this, 'processDefinition'));
-    $this->discovery = new CacheDecorator($this->discovery, 'tour');
-    $this->factory = new DefaultFactory($this->discovery);
-  }
-
-  /**
-   * Overrides \Drupal\Component\Plugin\PluginManagerBase::createInstance().
-   *
-   * Pass the TipsBag to the plugin constructor.
-   */
-  public function createInstance($plugin_id, array $configuration = array(), TipsBag $bag = NULL) {
-    $plugin_class = DefaultFactory::getPluginClass($plugin_id, $this->discovery);
-    return new $plugin_class($configuration, $plugin_id, $this->discovery, $bag);
-  }
-
-  /**
-   * Overrides \Drupal\Component\Plugin\PluginManagerBase::processDefinition().
-   */
-  public function processDefinition(&$definition, $plugin_id) {
-    parent::processDefinition($definition, $plugin_id);
-
-    // @todo Remove this check once http://drupal.org/node/1780396 is resolved.
-    if (!module_exists($definition['module'])) {
-      $definition = NULL;
-      return;
-    }
-  }
-}
diff --git a/tour/lib/Drupal/tour/TourRenderController.php b/tour/lib/Drupal/tour/TourRenderController.php
new file mode 100644
index 0000000..ba96c49
--- /dev/null
+++ b/tour/lib/Drupal/tour/TourRenderController.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tour\TourRenderController.
+ */
+
+namespace Drupal\tour;
+
+use Drupal\Core\Entity\EntityRenderController;
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * Provides a Tour render controller.
+ */
+class TourRenderController extends EntityRenderController {
+
+  /**
+   * Overrides \Drupal\Core\Entity\EntityRenderController::viewMultiple().
+   */
+  public function viewMultiple(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
+    $build = array();
+    foreach ($entities as $entity_id => $entity) {
+      $tips = $entity->getTips();
+      $count = count($tips);
+      $list_items = array();
+	  $tipcount = 0;
+      foreach ($tips as $index => $tip) {
+	    $tipcount++;
+        if ($output = $tip->getOutput()) {
+          $attributes = array(
+            'class' => array(
+              'tip-module-' . drupal_clean_css_identifier($entity->get('module')),
+              'tip-type-' . drupal_clean_css_identifier($tip->get('plugin')),
+              'tip-' . drupal_clean_css_identifier($tip->get('id')),
+            ),
+          );
+          $list_items[] = array(
+            'output' => $output,
+            'counter' => array(
+              '#type' => 'container',
+              '#attributes' => array(
+                'class' => array(
+                  'tour-progress',
+                ),
+              ),
+              '#children' => t('!tour_item of !total', array('!tour_item' => $tipcount, '!total' => $count)),
+            ),
+            '#wrapper_attributes' => $tip->getAttributes() + $attributes,
+          );
+        }
+      }
+      // If there is at least one tour item, build the tour.
+      if ($list_items) {
+        end($list_items);
+        $key = key($list_items);
+        $list_items[$key]['#wrapper_attributes']['data-text'] = t('End tour');
+        $build[$entity_id] = array(
+          '#theme' => 'item_list',
+          '#items' => $list_items,
+          '#type' => 'ol',
+          '#attributes' => array(
+            'id' => 'tour',
+            'class' => array(
+              'element-hidden',
+            ),
+          ),
+        );
+      }
+    }
+    // If at least one tour was built, attach the tour library.
+    if ($build) {
+      $build['#attached']['library'][] = array('tour', 'tour');
+    }
+    return $build;
+  }
+
+}
diff --git a/tour/tests/tour_test/config/locale.config.it.tour.tour.tour-test.yml b/tour/tests/tour_test/config/locale.config.it.tour.tour.tour-test.yml
new file mode 100644
index 0000000..e36e435
--- /dev/null
+++ b/tour/tests/tour_test/config/locale.config.it.tour.tour.tour-test.yml
@@ -0,0 +1,5 @@
+label: Tour test italian
+tips:
+  tour-test-1:
+    label: La pioggia cade in spagna
+    body: Per lo più in pianura.
diff --git a/tour/tests/tour_test/config/schema/tour_test.schema.yml b/tour/tests/tour_test/config/schema/tour_test.schema.yml
new file mode 100644
index 0000000..a43cc26
--- /dev/null
+++ b/tour/tests/tour_test/config/schema/tour_test.schema.yml
@@ -0,0 +1,9 @@
+# Schema for the configuration files of the Tour Test module.
+
+tour.tip.image:
+  type: tour.tip
+  label: 'Image tour tip'
+  mapping:
+    url:
+      type: uri
+      label: 'Image URL'
diff --git "a/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-2-en.yml" "b/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-2-en.yml"
deleted file mode 100644
index 6816aa7..0000000
--- "a/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-2-en.yml"
+++ /dev/null
@@ -1,14 +0,0 @@
-id: tour-test-2-en
-label: Tour test english
-langcode: en
-paths:
-  - tour-test-2/*
-tips:
-  tour-test-2:
-    id: tour-test-2-en
-    plugin: text
-    label: The quick brown fox
-    body: Per lo più in pianura.
-    weight: "2"
-    attributes:
-      data-id: tour-test-2
diff --git a/tour/tests/tour_test/config/tour.tour.tour-test-2.yml b/tour/tests/tour_test/config/tour.tour.tour-test-2.yml
new file mode 100644
index 0000000..62e5ae8
--- /dev/null
+++ b/tour/tests/tour_test/config/tour.tour.tour-test-2.yml
@@ -0,0 +1,15 @@
+id: tour-test-2
+module: tour_test
+label: Tour test english
+langcode: en
+paths:
+  - tour-test-2/*
+tips:
+  tour-test-2:
+    id: tour-test-2
+    plugin: text
+    label: The quick brown fox
+    body: Per lo più in pianura.
+    weight: "2"
+    attributes:
+      data-id: tour-test-2
diff --git "a/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-en.yml" "b/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-en.yml"
deleted file mode 100644
index 5271213..0000000
--- "a/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-en.yml"
+++ /dev/null
@@ -1,22 +0,0 @@
-id: tour-test-en
-label: Tour test english
-langcode: en
-paths:
-  - tour-test-1
-tips:
-  tour-test-1:
-    id: tour-test-1-en
-    plugin: text
-    label: The first tip
-    body: Is always the best dressed.
-    weight: "1"
-    attributes:
-      data-id: tour-test-1
-  tour-test-3:
-    id: tour-test-3-en
-    plugin: image
-    label: The awesome image
-    url: http://local/image.png
-    weight: "1"
-    attributes:
-      data-id: tour-test-3
diff --git "a/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-it.yml" "b/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-it.yml"
deleted file mode 100644
index 86f0a25..0000000
--- "a/core/modules/tour/tests/tour_test/config/tour.tour.tour-test-it.yml"
+++ /dev/null
@@ -1,14 +0,0 @@
-id: tour-test-it
-label: Tour test italian
-langcode: it
-paths:
-  - tour-test-1
-tips:
-  tour-test-1-it:
-    id: tour-test-1-it
-    plugin: text
-    label: La pioggia cade in spagna
-    body: Per lo più in pianura.
-    weight: "1"
-    attributes:
-      data-id: tour-test-1
diff --git a/tour/tests/tour_test/config/tour.tour.tour-test.yml b/tour/tests/tour_test/config/tour.tour.tour-test.yml
new file mode 100644
index 0000000..86abd83
--- /dev/null
+++ b/tour/tests/tour_test/config/tour.tour.tour-test.yml
@@ -0,0 +1,23 @@
+id: tour-test
+module: tour_test
+label: Tour test english
+langcode: en
+paths:
+  - tour-test-1
+tips:
+  tour-test-1:
+    id: tour-test-1
+    plugin: text
+    label: The first tip
+    body: Is always the best dressed.
+    weight: "1"
+    attributes:
+      data-id: tour-test-1
+  tour-test-3:
+    id: tour-test-3
+    plugin: image
+    label: The awesome image
+    url: http://local/image.png
+    weight: "1"
+    attributes:
+      data-id: tour-test-3
diff --git a/tour/tests/tour_test/lib/Drupal/tour_test/Controller/TourTestController.php b/tour/tests/tour_test/lib/Drupal/tour_test/Controller/TourTestController.php
new file mode 100644
index 0000000..61882a9
--- /dev/null
+++ b/tour/tests/tour_test/lib/Drupal/tour_test/Controller/TourTestController.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\tour_test\Controller\TourTestController.
+ */
+
+namespace Drupal\tour_test\Controller;
+
+use Drupal\Core\ControllerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Controller routines for tour_test routes.
+ */
+class TourTestController implements ControllerInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static();
+  }
+
+  /**
+   * Outputs some content for testing tours.
+   */
+  public function tourTest1() {
+    return array(
+      'tip-1' => array(
+        '#type' => 'container',
+        '#attributes' => array(
+          'id' => 'tour-test-1',
+        ),
+        '#children' => t('Where does the rain in Spain fail?'),
+      ),
+      'tip-4' => array(
+        '#type' => 'container',
+        '#attributes' => array(
+          'id' => 'tour-test-4',
+        ),
+        '#children' => t('Tip created later?'),
+      ),
+    );
+  }
+
+  /**
+   * Outputs some content for testing tours.
+   */
+  public function tourTest2() {
+    return array(
+      '#type' => 'container',
+      '#attributes' => array(
+        'id' => 'tour-test-2',
+      ),
+      '#children' => t('Pangram example'),
+    );
+
+  }
+
+}
diff --git "a/core/modules/tour/tests/tour_test/lib/Drupal/tour_test/Plugin/tour/tip/TipPluginImage.php" b/tour/tests/tour_test/lib/Drupal/tour_test/Plugin/tour/tip/TipPluginImage.php
index e158b5c..b03ffbe 100644
--- "a/core/modules/tour/tests/tour_test/lib/Drupal/tour_test/Plugin/tour/tip/TipPluginImage.php"
+++ b/tour/tests/tour_test/lib/Drupal/tour_test/Plugin/tour/tip/TipPluginImage.php
@@ -7,17 +7,13 @@
 
 namespace Drupal\tour_test\Plugin\tour\tip;
 
-use Drupal\Core\Annotation\Plugin;
+use Drupal\tour\Annotation\Tip;
 use Drupal\tour\TipPluginBase;
 
 /**
  * Displays an image as a tip.
  *
- * @Plugin(
- *   id = "image",
- *   label = "Image",
- *   module = "tour_test"
- * )
+ * @Tip("image")
  */
 class TipPluginImage extends TipPluginBase {
 
@@ -38,67 +34,12 @@ class TipPluginImage extends TipPluginBase {
   protected $alt;
 
   /**
-   * Returns url of the image tip.
-   *
-   * @return string
-   *   The url of the image tip.
-   */
-  public function getUrl() {
-    return $this->get('url');
-  }
-
-  /**
-   * Returns alt text of the image tip.
-   *
-   * @return string
-   *   The alt text of the image tip.
-   */
-  public function getAlt() {
-    return $this->get('alt');
-  }
-
-  /**
    * Overrides \Drupal\tour\Plugin\tour\tour\TipPluginInterface::getOutput().
    */
   public function getOutput() {
-    $output = '<h2 class="tour-tip-label" id="tour-tip-' . $this->get('ariaId') . '-label">' . check_plain($this->getLabel()) . '</h2>';
-    $output .= '<p class="tour-tip-image" id="tour-tip-' . $this->get('ariaId') . '-contents">' . theme('image', array('uri' => $this->getUrl(), 'alt' => $this->getAlt())) . '</p>';
+    $output = '<h2 class="tour-tip-label" id="tour-tip-' . $this->get('ariaId') . '-label">' . check_plain($this->get('label')) . '</h2>';
+    $output .= '<p class="tour-tip-image" id="tour-tip-' . $this->get('ariaId') . '-contents">' . theme('image', array('uri' => $this->get('url'), 'alt' => $this->get('alt'))) . '</p>';
     return array('#markup' => $output);
   }
 
-  /**
-   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::getExportProperties().
-   */
-  public function getExportProperties() {
-    $properties = parent::getExportProperties();
-    $names = array(
-      'url',
-      'alt',
-    );
-    foreach ($names as $name) {
-      $properties[$name] = $this->get($name);
-    }
-    return $properties;
-  }
-
-  /**
-   * Overrides \Drupal\tour\Plugin\tour\tour\TourPluginBase::optionsForm().
-   */
-  public function optionsForm() {
-    $form = parent::optionsForm();
-    $form['url'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Url'),
-      '#required' => TRUE,
-      '#default_value' => $this->getUrl(),
-    );
-    $form['alt'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Alt'),
-      '#required' => TRUE,
-      '#default_value' => $this->getAlt(),
-    );
-    return $form;
-  }
-
 }
diff --git "a/core/modules/tour/tests/tour_test/tour_test.info" "b/core/modules/tour/tests/tour_test/tour_test.info"
deleted file mode 100644
index afc405d..0000000
--- "a/core/modules/tour/tests/tour_test/tour_test.info"
+++ /dev/null
@@ -1,7 +0,0 @@
-name = Tour module tests
-description = Tests module for tour module.
-package = Core
-version = VERSION
-core = 8.x
-hidden = TRUE
-dependencies[] = tour
diff --git a/tour/tests/tour_test/tour_test.info.yml b/tour/tests/tour_test/tour_test.info.yml
new file mode 100644
index 0000000..0617983
--- /dev/null
+++ b/tour/tests/tour_test/tour_test.info.yml
@@ -0,0 +1,9 @@
+name: Tour module tests
+type: module
+description: Tests module for tour module.
+package: Core
+version: VERSION
+core: 8.x
+hidden: TRUE
+dependencies:
+  - tour
diff --git "a/core/modules/tour/tests/tour_test/tour_test.module" b/tour/tests/tour_test/tour_test.module
index a2b7bda..493b878 100644
--- "a/core/modules/tour/tests/tour_test/tour_test.module"
+++ b/tour/tests/tour_test/tour_test.module
@@ -5,18 +5,18 @@
  * Provides tests for tour module
  */
 
+use Drupal\Core\Entity\EntityInterface;
+
 /**
  * Implements hook_menu().
  */
 function tour_test_menu() {
   $items['tour-test-1'] = array(
-    'page callback' => 'tour_test_1',
-    'access callback' => TRUE,
+    'route_name' => 'tour_test_1',
     'title' => 'Tour test 1'
   );
   $items['tour-test-2/subpath'] = array(
-    'page callback' => 'tour_test_2',
-    'access callback' => TRUE,
+    'route_name' => 'tour_test_2',
     'title' => 'Tour test 2'
   );
   return $items;
@@ -41,44 +41,9 @@ function tour_test_tour_presave($entity) {
 }
 
 /**
- * Page callback: output some content for testing tours.
- */
-function tour_test_1() {
-  return array(
-    'tip-1' => array(
-      '#type' => 'container',
-      '#attributes' => array(
-        'id' => 'tour-test-1',
-      ),
-      '#children' => t('Where does the rain in Spain fail?'),
-    ),
-    'tip-4' => array(
-      '#type' => 'container',
-      '#attributes' => array(
-        'id' => 'tour-test-4',
-      ),
-      '#children' => t('Tip created later?'),
-    ),
-  );
-}
-
-/**
- * Page callback: output some content for testing tours.
- */
-function tour_test_2() {
-  return array(
-    '#type' => 'container',
-    '#attributes' => array(
-      'id' => 'tour-test-2',
-    ),
-    '#children' => t('Pangram example'),
-  );
-}
-
-/**
- * Implements hook_tour_alter().
+ * Implements hook_tour_tips_alter().
  */
-function tour_test_tour_tips_alter(array &$tour_tips, $path) {
+function tour_test_tour_tips_alter(array &$tour_tips, EntityInterface $entity) {
   foreach ($tour_tips as $tour_tip) {
     if ($tour_tip->get('id') == 'tour-code-test-1') {
       $tour_tip->set('body', 'Altered by hook_tour_tips_alter');
diff --git a/tour/tests/tour_test/tour_test.routing.yml b/tour/tests/tour_test/tour_test.routing.yml
new file mode 100644
index 0000000..2cdad99
--- /dev/null
+++ b/tour/tests/tour_test/tour_test.routing.yml
@@ -0,0 +1,13 @@
+tour_test_1:
+  pattern : 'tour-test-1'
+  defaults:
+    _content: '\Drupal\tour_test\Controller\TourTestController::tourTest1'
+  requirements:
+    _access: 'TRUE'
+
+tour_test_2:
+  pattern : 'tour-test-2/subpath'
+  defaults:
+    _content: '\Drupal\tour_test\Controller\TourTestController::tourTest2'
+  requirements:
+    _access: 'TRUE'
diff --git "a/core/modules/tour/tour.api.php" b/tour/tour.api.php
index a3672b3..2bda3d6 100644
--- "a/core/modules/tour/tour.api.php"
+++ b/tour/tour.api.php
@@ -8,12 +8,12 @@
 /**
  * Allow modules to alter tour items before render.
  *
- * @param array $tour_items
+ * @param array $tour_tips
  *   Array of \Drupal\tour\TipPluginInterface items.
- * @param string $path
- *   The path for which the tour is valid.
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The tour which contains the $tour_tips.
  */
-function hook_tour_tips_alter(array &$tour_tips, $path) {
+function hook_tour_tips_alter(array &$tour_tips, Drupal\Core\Entity\EntityInterface $entity) {
   foreach ($tour_tips as $tour_tip) {
     if ($tour_tip->get('id') == 'tour-code-test-1') {
       $tour_tip->set('body', 'Altered by hook_tour_tips_alter');
@@ -22,6 +22,21 @@ function hook_tour_tips_alter(array &$tour_tips, $path) {
 }
 
 /**
+ * Allow modules to alter tip plugin definitions.
+ *
+ * @param array $info
+ *   The array of tip plugin definitions, keyed by plugin ID.
+ *
+ * @see \Drupal\tour\Annotation\Tip
+ */
+function hook_tour_tips_info_alter(&$info) {
+  // Swap out the class used for this tip plugin.
+  if (isset($info['text'])) {
+    $info['class'] = 'Drupal\mymodule\Plugin\tour\tip\MyCustomTipPlugin';
+  }
+}
+
+/**
  * Act on tour objects when loaded.
  *
  * @param array $entities
@@ -57,7 +72,7 @@ function hook_tour_presave($entity) {
  *   The tour object being inserted.
  */
 function hook_tour_insert($entity) {
-  drupal_container()->get('plugin.manager.tour')->clearCachedDefinitions();
+  drupal_container()->get('plugin.manager.tour.tip')->clearCachedDefinitions();
   cache('cache_tour')->deleteTags(array('tour_items'));
 }
 
@@ -68,6 +83,6 @@ function hook_tour_insert($entity) {
  *   The tour object being updated.
  */
 function hook_tour_update($entity) {
-  drupal_container()->get('plugin.manager.tour')->clearCachedDefinitions();
+  drupal_container()->get('plugin.manager.tour.tip')->clearCachedDefinitions();
   cache('cache_tour')->deleteTags(array('tour_items'));
 }
diff --git "a/core/modules/tour/tour.info" "b/core/modules/tour/tour.info"
deleted file mode 100644
index 341cb0d..0000000
--- "a/core/modules/tour/tour.info"
+++ /dev/null
@@ -1,5 +0,0 @@
-name = Tour
-description = Provides guided tours.
-package = Core
-version = VERSION
-core = 8.x
diff --git a/tour/tour.info.yml b/tour/tour.info.yml
new file mode 100644
index 0000000..b913162
--- /dev/null
+++ b/tour/tour.info.yml
@@ -0,0 +1,6 @@
+name: Tour
+type: module
+description: Provides guided tours.
+package: Core
+version: VERSION
+core: 8.x
diff --git "a/core/modules/tour/tour.module" b/tour/tour.module
index 7c1e1d6..fe9bc1a 100644
--- "a/core/modules/tour/tour.module"
+++ b/tour/tour.module
@@ -112,104 +112,35 @@ function tour_preprocess_page(&$variables) {
 
   // @todo replace this with http://drupal.org/node/1918768 once it is committed.
   $path = current_path();
-  $langcode = language(LANGUAGE_TYPE_CONTENT)->langcode;
   $tour_items = array();
   // Load all of the items and match on path.
-  $tour_ids = entity_query('tour')
-    ->condition('langcode', $langcode)
-    ->execute();
-  $tours = entity_load_multiple('tour', $tour_ids);
+  $tours = entity_load_multiple('tour');
 
   $path_alias = drupal_strtolower(drupal_container()->get('path.alias_manager')->getPathAlias($path));
-  foreach ($tours as $tour) {
-    // @todo replace this with an entity_query() that does path matching when
+  foreach ($tours as $tour_id => $tour) {
+    // @todo Replace this with an entity query that does path matching when
     // http://drupal.org/node/1918768 lands.
     $pages = implode("\n", $tour->getPaths());
-    if (drupal_match_path($path_alias, $pages) || (($path != $path_alias) && drupal_match_path($path, $pages))) {
-      foreach ($tour->getTipList() as $id) {
-        $tour_items[] = $tour->getTip($id);
-      }
+    if (!drupal_match_path($path_alias, $pages) && (($path == $path_alias) || drupal_match_path($path, $pages))) {
+      unset($tours[$tour_id]);
     }
   }
 
-  // Allow other modules to alter.
-  drupal_container()->get('module_handler')->alter('tour_tips', $tour_items, $path);
-
-  if (empty($tour_items)) {
-    return;
+  if ($tours) {
+    $variables['page']['help']['tour'] = entity_view_multiple($tours, 'full');
   }
-
-  // Sort by weight.
-  uasort($tour_items, function ($a, $b) {
-    if ($a->getWeight() == $b->getWeight()) {
-      return 0;
-    }
-    return ($a->getWeight() < $b->getWeight()) ? -1 : 1;
-  });
-
-  $index = 1;
-  $count = count($tour_items);
-  foreach ($tour_items as $tour_item) {
-    $list_items[] = array(
-      'output' => $tour_item->getOutput(),
-      'counter' => array(
-        '#type' => 'container',
-        '#attributes' => array(
-          'class' => array(
-            'tour-progress',
-          ),
-        ),
-        '#children' => t('!tour_item of !total', array('!tour_item' => $index, '!total' => $count)),
-      ),
-      '#wrapper_attributes' => $tour_item->getAttributes(),
-    );
-    $index++;
-  }
-
-  // Give the last tip the "End tour" button.
-  end($list_items);
-  $key = key($list_items);
-  $list_items[$key]['#wrapper_attributes']['data-text'] = t('End tour');
-
-  $variables['page']['help']['tour'] = array(
-    '#theme' => 'item_list',
-    '#items' => $list_items,
-    '#type' => 'ol',
-    '#attributes' => array(
-      'id' => 'tour',
-      'class' => array(
-        'element-hidden',
-      ),
-    ),
-    '#attached' => array(
-      'library' => array(
-        // We must also attach the jquery.joyride library here, because it only
-        // works within the window within which it is loaded. This means that if
-        // we want the Tour module to work inside the Overlay, we must ensure
-        // that jquery.joyride also is loaded there. (And since the Toolbar does
-        // not get loaded inside the Overlay, we cannot rely on it being loaded
-        // that way.)
-        // If this a non-overlay page, then Drupal's dependency checking will
-        // ensure this gets loaded only once.
-        array('tour', 'jquery.joyride'),
-        // Similarly, we must load tour's CSS, in order to style the tour tips
-        // in the desired way inside the Overlay.
-        array('tour', 'tour-styling'),
-      ),
-    ),
-  );
 }
 
 /**
  * Implements hook_tour_insert().
  */
 function tour_tour_insert($entity) {
-  drupal_container()->get('plugin.manager.tour')->clearCachedDefinitions();
+  drupal_container()->get('plugin.manager.tour.tip')->clearCachedDefinitions();
 }
 
 /**
  * Implements hook_tour_update().
  */
 function tour_tour_update($entity) {
-  drupal_container()->get('plugin.manager.tour')->clearCachedDefinitions();
+  drupal_container()->get('plugin.manager.tour.tip')->clearCachedDefinitions();
 }
diff --git a/tour/tour.services.yml b/tour/tour.services.yml
new file mode 100644
index 0000000..c4cf3fa
--- /dev/null
+++ b/tour/tour.services.yml
@@ -0,0 +1,4 @@
+services:
+  plugin.manager.tour.tip:
+    class: Drupal\tour\TipPluginManager
+    arguments: ['@container.namespaces']
