diff --git a/src/Form/PageVariantAddForm.php b/src/Form/PageVariantAddForm.php
index 7f692ab..804730d 100644
--- a/src/Form/PageVariantAddForm.php
+++ b/src/Form/PageVariantAddForm.php
@@ -24,6 +24,17 @@ class PageVariantAddForm extends PageVariantFormBase {
   /**
    * {@inheritdoc}
    */
+  protected function getVariantPlugin() {
+    $variant_plugin = parent::getVariantPlugin();
+    // Before showing the add form, we need to set the Panels storage
+    // information so that it knows to give the user the IPE as an option.
+    $this->setPanelsStorage($variant_plugin);
+    return $variant_plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function save(array $form, FormStateInterface $form_state) {
     parent::save($form, $form_state);
     $form_state->setRedirectUrl($this->getEntity()->toUrl('edit-form'));
diff --git a/src/Form/PageVariantFormBase.php b/src/Form/PageVariantFormBase.php
index 09961a8..27a338b 100644
--- a/src/Form/PageVariantFormBase.php
+++ b/src/Form/PageVariantFormBase.php
@@ -7,10 +7,12 @@
 
 namespace Drupal\page_manager\Form;
 
+use Drupal\Core\Display\VariantInterface;
 use Drupal\Core\Entity\EntityForm;
 use Drupal\Core\Entity\Query\QueryFactory;
 use Drupal\Core\Form\FormState;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -156,6 +158,8 @@ abstract class PageVariantFormBase extends EntityForm {
     // Allow the variant to submit the form.
     $variant_plugin_values = (new FormState())->setValues($form_state->getValue('variant_settings'));
     $this->getVariantPlugin()->submitConfigurationForm($form, $variant_plugin_values);
+    // Make sure the Panels storage is set correctly before saving.
+    $this->setPanelsStorage($this->getVariantPlugin());
     // Update the original form values.
     $form_state->setValue('variant_settings', $variant_plugin_values->getValues());
 
@@ -163,6 +167,17 @@ abstract class PageVariantFormBase extends EntityForm {
   }
 
   /**
+   * Set Panels storage information on the variant, if it's a Panels variant.
+   *
+   * @param \Drupal\Core\Display\VariantInterface $variant_plugin
+   */
+  protected function setPanelsStorage(VariantInterface $variant_plugin) {
+    if ($variant_plugin instanceof PanelsDisplayVariant) {
+      $variant_plugin->setStorage('page_manager', $this->entity->id());
+    }
+  }
+
+  /**
    * Gets the variant plugin for this page variant entity.
    *
    * @return \Drupal\Core\Display\VariantInterface
diff --git a/src/Plugin/PanelsStorage/PageManagerPanelsStorage.php b/src/Plugin/PanelsStorage/PageManagerPanelsStorage.php
new file mode 100644
index 0000000..7402d5a
--- /dev/null
+++ b/src/Plugin/PanelsStorage/PageManagerPanelsStorage.php
@@ -0,0 +1,121 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\page_manager\PageManagerPanelsStorage
+ */
+
+namespace Drupal\page_manager\Plugin\PanelsStorage;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant;
+use Drupal\panels\Storage\PanelsStorageBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * A Panels storage service that stores Panels displays in Page Manager.
+ *
+ * @PanelsStorage("page_manager")
+ */
+class PageManagerPanelsStorage extends PanelsStorageBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs a PageManagerPanelsStorage.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * Load a page variant entity.
+   *
+   * @param string $id
+   *   The page variant entity's id.
+   *
+   * @return \Drupal\page_manager\PageVariantInterface
+   */
+  protected function loadPageVariant($id) {
+    return $this->entityTypeManager->getStorage('page_variant')->load($id);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save(PanelsDisplayVariant $panels_display) {
+    $id = $panels_display->getStorageId();
+    if ($id && ($page_variant = $this->loadPageVariant($id))) {
+      $variant_plugin = $page_variant->getVariantPlugin();
+      if (!($variant_plugin instanceof PanelsDisplayVariant)) {
+        throw new \Exception("Page variant doesn't use a Panels display variant");
+      }
+      $variant_plugin->setConfiguration($panels_display->getConfiguration());
+      $page_variant->save();
+    }
+    else {
+      throw new \Exception("Couldn't find page variant to store Panels display");
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load($id) {
+    if ($page_variant = $this->loadPageVariant($id)) {
+      $panels_display = $page_variant->getVariantPlugin();
+
+      // If this page variant doesn't have a Panels display on it, then we treat
+      // it the same as if there was no such page variant.
+      if (!($panels_display instanceof PanelsDisplayVariant)) {
+        return NULL;
+      }
+
+      // Pass down the contexts because the display has no other way to get them
+      // from the variant.
+      $panels_display->setContexts($page_variant->getContexts());
+
+      return $panels_display;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access($id, $op, AccountInterface $account) {
+    if ($page_variant = $this->loadPageVariant($id)) {
+      return $page_variant->access($op, $account, TRUE);
+    }
+
+    return AccessResult::forbidden();
+  }
+
+}
diff --git a/tests/src/Unit/PanelsStorageTest.php b/tests/src/Unit/PanelsStorageTest.php
new file mode 100644
index 0000000..d59a3e1
--- /dev/null
+++ b/tests/src/Unit/PanelsStorageTest.php
@@ -0,0 +1,179 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\page_manager\Unit\PanelStorageTest.
+ */
+
+namespace Drupal\Tests\page_manager\Unit;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\page_manager\PageVariantInterface;
+use Drupal\page_manager\Plugin\PanelsStorage\PageManagerPanelsStorage;
+use Drupal\page_manager\Plugin\DisplayVariant\HttpStatusCodeDisplayVariant;
+use Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests the PageManagerPanelsStorage service.
+ *
+ * @coversDefaultClass \Drupal\page_manager\Plugin\PanelsStorage\PageManagerPanelsStorage
+ *
+ * @group PageManager
+ */
+class PanelsStorageTest extends UnitTestCase {
+
+  /**
+   * @var \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant|\Prophecy\Prophecy\ProphecyInterface
+   */
+  protected $panelsDisplay;
+
+  /**
+   * @var \Drupal\page_manager\PageVariantInterface|\Prophecy\Prophecy\ProphecyInterface
+   */
+  protected $pageVariant;
+
+  /**
+   * @var \Drupal\page_manager\PageVariantInterface|\Prophecy\Prophecy\ProphecyInterface
+   */
+  protected $pageVariantNotPanels;
+
+  /**
+   * @var \Drupal\Core\Entity\EntityStorageInterface|\Prophecy\Prophecy\ProphecyInterface
+   */
+  protected $storage;
+
+  /**
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\Prophecy\Prophecy\ProphecyInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->panelsDisplay = $this->prophesize(PanelsDisplayVariant::class);
+
+    $this->pageVariant = $this->prophesize(PageVariantInterface::class);
+    $this->pageVariant->getVariantPlugin()->willReturn($this->panelsDisplay->reveal());
+
+    $this->pageVariantNotPanels = $this->prophesize(PageVariantInterface::class);
+    $this->pageVariantNotPanels->getContexts()->shouldNotBeCalled();
+
+    $non_panels_variant = $this->prophesize(HttpStatusCodeDisplayVariant::class);
+    $this->pageVariantNotPanels->getVariantPlugin()->willReturn($non_panels_variant->reveal());
+
+    $this->storage = $this->prophesize(EntityStorageInterface::class);
+
+    $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
+    $this->entityTypeManager->getStorage('page_variant')->willReturn($this->storage->reveal());
+  }
+
+  /**
+   * @covers ::load
+   */
+  public function testLoad() {
+    // Make sure that the contexts are passed down (or not).
+    $this->pageVariant->getContexts()->willReturn([]);
+    $this->panelsDisplay->setContexts([])->shouldBeCalledTimes(1);
+
+    $this->storage->load('id_exists')->willReturn($this->pageVariant->reveal());
+    $this->storage->load('doesnt_exist')->willReturn(NULL);
+    $this->storage->load('not_a_panel')->willReturn($this->pageVariantNotPanels->reveal());
+
+    $panels_storage = new PageManagerPanelsStorage([], '', [], $this->entityTypeManager->reveal());
+
+    // Test the success condition.
+    $this->assertSame($this->panelsDisplay->reveal(), $panels_storage->load('id_exists'));
+
+    // Should be NULL if it doesn't exist.
+    $this->assertNull($panels_storage->load('doesnt_exist'));
+
+    // Should also be NULL if it's not a PanelsDisplayVariant.
+    $this->assertNull($panels_storage->load('not_a_panel'));
+  }
+
+  /**
+   * @covers ::save
+   */
+  public function testSaveSuccessful() {
+    $test_config = ['my_config' => '123'];
+    $this->panelsDisplay->setConfiguration($test_config)->shouldBeCalledTimes(1);
+    $this->pageVariant->save()->shouldBeCalledTimes(1);
+
+    $this->storage->load('id_exists')->willReturn($this->pageVariant->reveal());
+
+    $panels_display = $this->prophesize(PanelsDisplayVariant::class);
+    $panels_display->getStorageId()->willReturn('id_exists');
+    $panels_display->getConfiguration()->willReturn($test_config);
+
+    $panels_storage = new PageManagerPanelsStorage([], '', [], $this->entityTypeManager->reveal());
+    $panels_storage->save($panels_display->reveal());
+  }
+
+  /**
+   * @covers ::save
+   *
+   * @expectedException \Exception
+   * @expectedExceptionMessage Couldn't find page variant to store Panels display
+   */
+  public function testSaveDoesntExist() {
+    $this->panelsDisplay->setConfiguration()->shouldNotBeCalled();
+    $this->pageVariant->save()->shouldNotBeCalled();
+
+    $this->storage->load('doesnt_exist')->willReturn(NULL);
+
+    $panels_display = $this->prophesize(PanelsDisplayVariant::class);
+    $panels_display->getStorageId()->willReturn('doesnt_exist');
+    $panels_display->getConfiguration()->shouldNotBeCalled();
+
+    $panels_storage = new PageManagerPanelsStorage([], '', [], $this->entityTypeManager->reveal());
+    $panels_storage->save($panels_display->reveal());
+  }
+
+  /**
+   * @covers ::save
+   *
+   * @expectedException \Exception
+   * @expectedExceptionMessage Page variant doesn't use a Panels display variant
+   */
+  public function testSaveNotPanels() {
+    $this->storage->load('not_a_panel')->willReturn($this->pageVariantNotPanels->reveal());
+
+    $this->panelsDisplay->setConfiguration()->shouldNotBeCalled();
+    $this->pageVariant->save()->shouldNotBeCalled();
+
+    $panels_display = $this->prophesize(PanelsDisplayVariant::class);
+    $panels_display->getStorageId()->willReturn('not_a_panel');
+    $panels_display->getConfiguration()->shouldNotBeCalled();
+
+    $panels_storage = new PageManagerPanelsStorage([], '', [], $this->entityTypeManager->reveal());
+    $panels_storage->save($panels_display->reveal());
+  }
+
+  /**
+   * @covers ::access
+   */
+  public function testAccess() {
+    $this->storage->load('id_exists')->willReturn($this->pageVariant->reveal());
+    $this->storage->load('doesnt_exist')->willReturn(NULL);
+
+    $account = $this->prophesize(AccountInterface::class);
+
+    $this->pageVariant->access('read', $account->reveal(), TRUE)->willReturn(AccessResult::allowed());
+
+    $panels_storage = new PageManagerPanelsStorage([], '', [], $this->entityTypeManager->reveal());
+
+    // Test the access condition.
+    $this->assertEquals(AccessResult::allowed(), $panels_storage->access('id_exists', 'read', $account->reveal()));
+
+    // Should be forbidden if it doesn't exist.
+    $this->assertEquals(AccessResult::forbidden(), $panels_storage->access('doesnt_exist', 'read', $account->reveal()));
+  }
+
+}
