diff --git a/commerce_stock_notifications.module b/commerce_stock_notifications.module
index 926c6c1..99b44cf 100644
--- a/commerce_stock_notifications.module
+++ b/commerce_stock_notifications.module
@@ -7,7 +7,6 @@
 
 use Drupal\commerce_product\Entity\ProductVariationInterface;
 use Drupal\commerce_stock_notifications\Form\AdminConfigForm;
-use Drupal\commerce_stock_notifications\Form\NotificationForm;
 
 /**
  * Implements hook_form_alter().
@@ -28,8 +27,15 @@ function commerce_stock_notifications_form_alter(&$form, &$form_state, $form_id)
       $selected_variation = $product->getDefaultVariation();
     }
     // Check if in stock.
-    if (commerce_stock_notifications_check_stock($selected_variation)) {
-      $form['commerce_stock_notifications'] = \Drupal::service('form_builder')->getForm(NotificationForm::class, $selected_variation);
+    if (!commerce_stock_notifications_check_stock($selected_variation)) {
+      $inline_form_manager = \Drupal::getContainer()->get('plugin.manager.commerce_inline_form');
+      $inline_form = $inline_form_manager->createInstance('commerce_stock_notifications', [
+        'variation_id' => $selected_variation->id(),
+      ]);
+      $form['commerce_stock_notifications'] = [
+        '#parents' => ['commerce_stock_notifications'],
+      ];
+      $form['commerce_stock_notifications'] = $inline_form->buildInlineForm($form['commerce_stock_notifications'], $form_state);
       $form['actions']['submit']['#value'] = t('Out of stock');
       $form['actions']['submit']['#disabled'] = TRUE;
     }
diff --git a/src/Form/NotificationForm.php b/src/Form/NotificationForm.php
deleted file mode 100644
index d09bb13..0000000
--- a/src/Form/NotificationForm.php
+++ /dev/null
@@ -1,129 +0,0 @@
-<?php
-
-namespace Drupal\commerce_stock_notifications\Form;
-
-use Drupal\Core\Datetime\DrupalDateTime;
-use Drupal\Core\Form\FormBase;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Class NotificationForm.
- *
- * @package Drupal\commerce_stock_notifications\Form
- */
-class NotificationForm extends FormBase {
-
-  use StringTranslationTrait;
-
-  /**
-   * Current variation.
-   *
-   * @var \Drupal\commerce_product\Entity\ProductVariation
-   */
-  protected $selectedVariation = NULL;
-
-  /**
-   * Email validator.
-   *
-   * @var \Drupal\Component\Utility\EmailValidatorInterface
-   */
-  protected $emailValidator;
-
-  /**
-   * Entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  public static function create(ContainerInterface $container) {
-    $form = parent::create($container);
-    $form->messenger = $container->get('messenger');
-    $form->configFactory = $container->get('config.factory');
-    $form->emailValidator = $container->get('email.validator');
-    $form->entityTypeManager = $container->get('entity_type.manager');
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormId() {
-    return 'commerce_stock_notifications_notification_form';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state, $selectedVariation = NULL) {
-    $this->selectedVariation = $selectedVariation;
-    $config = $this->configFactory->get('commerce_stock_notifications.config')->getRawData();
-
-    return [
-      'commerce_stock_notifications' => [
-        '#type' => 'fieldset',
-        '#title' => $config['oos_message'] ?? $this->t('Please notify me when this product is back in stock.'),
-        'notify_email' => [
-          '#type' => 'textfield',
-          '#title' => $this->t('E-Mail'),
-          '#required' => TRUE,
-          '#default_value' => $this->currentUser()->getEmail(),
-        ],
-        'notify_submit' => [
-          '#type' => 'submit',
-          '#value' => $this->t('Notify me'),
-        ],
-      ],
-    ];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validateForm(array &$form, FormStateInterface $form_state) {
-    parent::validateForm($form, $form_state);
-    // Check if user is logged in.
-    if ($this->currentUser()->isAnonymous()) {
-      $form_state->setError($form, $this->t('You must be authenticated to do that.'));
-    }
-    // Check if e-mail is valid.
-    $email = $form_state->getValue('notify_email');
-    if (!$this->emailValidator->isValid($email)) {
-      $form_state->setErrorByName('notify_email', $this->t('Invalid e-mail'));
-    }
-    // Check if already subscribed.
-    $notificationCount = $this->entityTypeManager
-      ->getStorage('commerce_stock_notification')
-      ->getQuery()
-      ->condition('email', $email)
-      ->condition('product_id', $this->selectedVariation->id())
-      ->condition('sent_time', NULL, 'IS')
-      ->count();
-
-    if ($notificationCount->execute() > 0) {
-      $duplicateMessage = AdminConfigForm::getValuesFromConfig()['duplicate_message'];
-      $form_state->setErrorByName('notify_email', $duplicateMessage);
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, FormStateInterface $form_state) {
-    $this->entityTypeManager
-      ->getStorage('commerce_stock_notification')
-      ->create([
-        'user_id' => $this->currentUser()->id(),
-        'product_id' => $this->selectedVariation->id(),
-        'submit_time' => (new DrupalDateTime())->getTimestamp(),
-        'email' => $form_state->getValue('notify_email'),
-      ])
-      ->save();
-
-    $this->messenger->addStatus(AdminConfigForm::getValuesFromConfig()['success_message']);
-  }
-
-}
diff --git a/src/Plugin/Commerce/InlineForm/Notification.php b/src/Plugin/Commerce/InlineForm/Notification.php
new file mode 100644
index 0000000..45471f4
--- /dev/null
+++ b/src/Plugin/Commerce/InlineForm/Notification.php
@@ -0,0 +1,224 @@
+<?php
+
+namespace Drupal\commerce_stock_notifications\Plugin\Commerce\InlineForm;
+
+use Drupal\commerce\Plugin\Commerce\InlineForm\InlineFormBase;
+use Drupal\commerce_stock_notifications\Form\AdminConfigForm;
+use Drupal\Component\Datetime\TimeInterface;
+use Drupal\Component\Utility\EmailValidatorInterface;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Session\AccountProxyInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides an inline form for back in-stock notification.
+ *
+ * @CommerceInlineForm(
+ *   id = "commerce_stock_notifications",
+ *   label = @Translation("Back in-stock notification"),
+ * )
+ */
+class Notification extends InlineFormBase {
+
+  /**
+   * The config.
+   *
+   * @var \Drupal\Core\Config\Config
+   */
+  protected $config;
+
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountProxyInterface
+   */
+  protected $currentUser;
+
+  /**
+   * The e-mail validator.
+   *
+   * @var \Drupal\Component\Utility\EmailValidatorInterface
+   */
+  protected $emailValidator;
+
+  /**
+   * Entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The time service.
+   *
+   * @var \Drupal\Component\Datetime\TimeInterface
+   */
+  protected $time;
+
+  /**
+   * Constructs a new Notification object.
+   *
+   * @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\Config\ConfigFactoryInterface $config_factory
+   *   The config factory.
+   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
+   *   The current user.
+   * @param \Drupal\Component\Utility\EmailValidatorInterface $email_validator
+   *   The e-mail validator.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   * @param \Drupal\Component\Datetime\TimeInterface $time
+   *   The time service.
+   */
+  public function __construct(array $configuration, string $plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory, AccountProxyInterface $current_user, EmailValidatorInterface $email_validator, EntityTypeManagerInterface $entity_type_manager, TimeInterface $time) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+    $this->config = $config_factory->get('commerce_stock_notifications.config');
+    $this->currentUser = $current_user;
+    $this->emailValidator = $email_validator;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->time = $time;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('config.factory'),
+      $container->get('current_user'),
+      $container->get('email.validator'),
+      $container->get('entity_type.manager'),
+      $container->get('datetime.time')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return [
+      // The variation_id is passed via configuration to avoid serializing the
+      // variation.
+      'variation_id' => '',
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function requiredConfiguration() {
+    return ['variation_id'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildInlineForm(array $inline_form, FormStateInterface $form_state) {
+    $inline_form = parent::buildInlineForm($inline_form, $form_state);
+
+    /** @var \Drupal\commerce_product\Entity\ProductVariationInterface|null $variation */
+    $variation = $this->entityTypeManager->getStorage('commerce_product_variation')->load($this->configuration['variation_id']);
+    if (!$variation) {
+      throw new \RuntimeException('Invalid variation_id given to the commerce_stock_notifications inline form.');
+    }
+
+    $inline_form['notification'] = [
+      '#type' => 'fieldset',
+      '#title' => $this->config->get('oos_message') ?? $this->t('Please notify me when this product is back in stock.'),
+      'notify_email' => [
+        '#type' => 'textfield',
+        '#title' => $this->t('E-Mail'),
+        '#required' => TRUE,
+        '#default_value' => $this->currentUser->getEmail(),
+      ],
+      'notify_submit' => [
+        '#type' => 'submit',
+        '#value' => $this->t('Notify me'),
+        '#limit_validation_errors' => [
+          $inline_form['#parents'],
+        ],
+        '#submit' => [
+          [get_called_class(), 'preventParentSubmit'],
+        ],
+      ],
+    ];
+
+    return $inline_form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateInlineForm(array &$inline_form, FormStateInterface $form_state) {
+    parent::validateInlineForm($inline_form, $form_state);
+
+    $notify_email_parents = array_merge($inline_form['#parents'], ['notification', 'notify_email']);
+    $notify_email = $form_state->getValue($notify_email_parents);
+    $notify_email_path = implode('][', $notify_email_parents);
+    $variation_id = $this->configuration['variation_id'];
+
+    // Check if user is logged in.
+    if ($this->currentUser->isAnonymous()) {
+      $form_state->setErrorByName($notify_email_path, $this->t('You must be authenticated to do that. Please <a href="@register_url" target="_blank">register</a> or <a href="@login_url" target="_blank">log in</a>!', ['@register_url' => '/user/register','@login_url' => '/user/login']));
+    }
+
+    // Check if e-mail is valid.
+    if (!$this->emailValidator->isValid($notify_email)) {
+      $form_state->setErrorByName($notify_email_path, $this->t('Invalid e-mail'));
+    }
+
+    // Check if already subscribed.
+    $notification_count_query = $this->entityTypeManager
+      ->getStorage('commerce_stock_notification')
+      ->getQuery()
+      ->condition('email', $notify_email)
+      ->condition('product_id', $variation_id)
+      ->condition('sent_time', NULL, 'IS')
+      ->count();
+
+    if ($notification_count_query->execute() > 0) {
+      $duplicate_message = AdminConfigForm::getValuesFromConfig()['duplicate_message'];
+      $form_state->setErrorByName($notify_email_path, $duplicate_message);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitInlineForm(array &$inline_form, FormStateInterface $form_state) {
+    parent::submitInlineForm($inline_form, $form_state);
+
+    $notify_email_parents = array_merge($inline_form['#parents'], ['notification', 'notify_email']);
+    $variation_id = $this->configuration['variation_id'];
+
+    $this->entityTypeManager
+      ->getStorage('commerce_stock_notification')
+      ->create([
+        'user_id' => $this->currentUser->id(),
+        'product_id' => $variation_id,
+        'submit_time' => $this->time->getRequestTime(),
+        'email' => $form_state->getValue($notify_email_parents),
+      ])
+      ->save();
+
+    $this->messenger()->addStatus(AdminConfigForm::getValuesFromConfig()['success_message']);
+  }
+
+  /**
+   * Empty submit callback to prevent add to cart submit handler to be called.
+   */
+  public static function preventParentSubmit(array $form, FormStateInterface $form_state) {
+  }
+
+}
