diff --git a/scrollama.info.yml b/scrollama.info.yml
index 3ee12eb..4b37039 100644
--- a/scrollama.info.yml
+++ b/scrollama.info.yml
@@ -3,4 +3,4 @@ type: module
 description: Enable scrollama and quick use via data-attributes
 package: Scrollama
 configure: scrollama.settings_form
-core_version_requirement: ^10.1 || ^11
+core_version_requirement: ^10.1 || ^11 || ^12
diff --git a/scrollama.module b/scrollama.module
index 18f2223..788eda5 100644
--- a/scrollama.module
+++ b/scrollama.module
@@ -5,46 +5,21 @@
  * Primary module hooks for scrollama module.
  */
 
-use Drupal\Core\Url;
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\scrollama\Hook\ScrollamaHooks;
 
 /**
  * Implements hook_help().
  */
+#[LegacyHook]
 function scrollama_help($route_name) {
-  switch ($route_name) {
-    case 'help.page.scrollama':
-      $output = '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('Loads <a href="https://github.com/russellgoldenberg/scrollama">scrollama.js</a> library and provides a simple data-attributes-based API for triggering animations via css classes.') . '</p>';
-      $output .= '<p>' . t('<strong>Important!</strong> The library needs to be enabled either by attaching it ("scrollama/scrollama") or by loading it globally using the <a href=":settings">module configuration</a> (defaults to false)', ['@settings' => Url::fromRoute('scrollama.settings_form')->toString()]) . '</p>';
-      $output .= '<h3>' . t('Usage') . '</h3>';
-      $output .= '<p>' . t('Add <code>data-scroll-init="my-class"</code> to an element to add the class when entering the screen. You can add multiple classes separating them by at least a space, e.g. <code>data-scroll-init="my-class another-class"</code>') . '</p>';
-      $output .= '<p>' . t('Add <code>data-scroll-exit="my-class"</code> to trigger a class on exit and <code>data-scroll-delay="1"</code> to add a delay') . '</p>';
-      $output .= '<p>' . t('Example:') . '</p>';
-      $output .= '<p><code>&lt;div data-scroll-enter="fade-in" data-scroll-exit="fade-out" data-scroll-delay="2"&gt;My code&lt;/div\&gt;</code></p>';
-      $output .= '<p>' . t('The previous element will fade in when entering scroll point, fade out when exiting and  the animation will have a delay of 2 seconds') . '</p>';
-
-      return $output;
-  }
+  return \Drupal::service(ScrollamaHooks::class)->help($route_name);
 }
 
 /**
  * Implements hook_page_attachments().
  */
+#[LegacyHook]
 function scrollama_page_attachments(array &$attachments) {
-  $settings = \Drupal::config('scrollama.settings');
-  $enable_globally = $settings->get('enable_globally');
-  $enable_css = $settings->get('enable_css');
-
-  if (!empty($enable_globally) && (bool) $enable_globally === TRUE) {
-    $attachments['#attached']['library'][] = 'scrollama/scrollama';
-  };
-
-  if (!empty($enable_css) && (bool) $enable_css === TRUE) {
-    $attachments['#attached']['library'][] = 'scrollama/scrollama-css';
-  };
-
-  $attachments['#attached']['drupalSettings']['scrollama']['offset'] = $settings->get('offset');
-  $attachments['#attached']['drupalSettings']['scrollama']['debug'] = $settings->get('debug');
-  $attachments['#attached']['drupalSettings']['scrollama']['order'] = $settings->get('order');
-  $attachments['#attached']['drupalSettings']['scrollama']['once'] = $settings->get('once');
+  \Drupal::service(ScrollamaHooks::class)->pageAttachments($attachments);
 }
diff --git a/scrollama.services.yml b/scrollama.services.yml
new file mode 100644
index 0000000..0d6847c
--- /dev/null
+++ b/scrollama.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\scrollama\Hook\ScrollamaHooks:
+    class: Drupal\scrollama\Hook\ScrollamaHooks
+    autowire: true
diff --git a/src/Hook/ScrollamaHooks.php b/src/Hook/ScrollamaHooks.php
new file mode 100644
index 0000000..1a4a7f1
--- /dev/null
+++ b/src/Hook/ScrollamaHooks.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Drupal\scrollama\Hook;
+
+use Drupal\Core\Url;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
+/**
+ * Hook implementations for scrollama.
+ */
+class ScrollamaHooks {
+  use StringTranslationTrait;
+
+  /**
+   * Implements hook_help().
+   */
+  #[Hook('help')]
+  public function help($route_name) {
+    switch ($route_name) {
+      case 'help.page.scrollama':
+        $output = '<h3>' . $this->t('About') . '</h3>';
+        $output .= '<p>' . $this->t('Loads <a href="https://github.com/russellgoldenberg/scrollama">scrollama.js</a> library and provides a simple data-attributes-based API for triggering animations via css classes.') . '</p>';
+        $output .= '<p>' . $this->t('<strong>Important!</strong> The library needs to be enabled either by attaching it ("scrollama/scrollama") or by loading it globally using the <a href=":settings">module configuration</a> (defaults to false)', [
+          '@settings' => Url::fromRoute('scrollama.settings_form')->toString(),
+        ]) . '</p>';
+        $output .= '<h3>' . $this->t('Usage') . '</h3>';
+        $output .= '<p>' . $this->t('Add <code>data-scroll-init="my-class"</code> to an element to add the class when entering the screen. You can add multiple classes separating them by at least a space, e.g. <code>data-scroll-init="my-class another-class"</code>') . '</p>';
+        $output .= '<p>' . $this->t('Add <code>data-scroll-exit="my-class"</code> to trigger a class on exit and <code>data-scroll-delay="1"</code> to add a delay') . '</p>';
+        $output .= '<p>' . $this->t('Example:') . '</p>';
+        $output .= '<p><code>&lt;div data-scroll-enter="fade-in" data-scroll-exit="fade-out" data-scroll-delay="2"&gt;My code&lt;/div\&gt;</code></p>';
+        $output .= '<p>' . $this->t('The previous element will fade in when entering scroll point, fade out when exiting and  the animation will have a delay of 2 seconds') . '</p>';
+        return $output;
+    }
+  }
+
+  /**
+   * Implements hook_page_attachments().
+   */
+  #[Hook('page_attachments')]
+  public static function pageAttachments(array &$attachments) {
+    $settings = \Drupal::config('scrollama.settings');
+    $enable_globally = $settings->get('enable_globally');
+    $enable_css = $settings->get('enable_css');
+    if (!empty($enable_globally) && (bool) $enable_globally === TRUE) {
+      $attachments['#attached']['library'][] = 'scrollama/scrollama';
+    }
+    if (!empty($enable_css) && (bool) $enable_css === TRUE) {
+      $attachments['#attached']['library'][] = 'scrollama/scrollama-css';
+    }
+    $attachments['#attached']['drupalSettings']['scrollama']['offset'] = $settings->get('offset');
+    $attachments['#attached']['drupalSettings']['scrollama']['debug'] = $settings->get('debug');
+    $attachments['#attached']['drupalSettings']['scrollama']['order'] = $settings->get('order');
+    $attachments['#attached']['drupalSettings']['scrollama']['once'] = $settings->get('once');
+  }
+
+}
diff --git a/tests/src/FunctionalJavascript/ScrollamaLibraryIsAvailableTest.php b/tests/src/FunctionalJavascript/ScrollamaLibraryIsAvailableTest.php
index 14c73d6..d0d8b1d 100644
--- a/tests/src/FunctionalJavascript/ScrollamaLibraryIsAvailableTest.php
+++ b/tests/src/FunctionalJavascript/ScrollamaLibraryIsAvailableTest.php
@@ -2,11 +2,13 @@
 
 namespace Drupal\Tests\scrollama\FunctionalJavascript;
 
+use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
 
 /**
  * Functional tests for the Scrollama Drupal module.
  */
+#[RunTestsInSeparateProcesses]
 class ScrollamaLibraryIsAvailableTest extends WebDriverTestBase {
 
   /**
