diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py
index 3ba94315d7..7b511e0f9b 100644
--- a/InvenTree/InvenTree/settings.py
+++ b/InvenTree/InvenTree/settings.py
@@ -18,6 +18,7 @@ import random
 import string
 import shutil
 import sys
+import pathlib
 from datetime import datetime
 
 import moneyed
@@ -675,3 +676,7 @@ for plugin in inventree_plugins.load_integration_plugins():
 
         INTEGRATION_PLUGIN_SETTING[plugin_name] = plugin_setting
         INTEGRATION_PLUGIN_SETTINGS.update(plugin_setting)
+
+    if plugin.mixin_enabled('app'):
+        plugin_path = '.'.join(pathlib.Path(plugin.path).relative_to(BASE_DIR).parts)
+        INSTALLED_APPS += [plugin_path]
diff --git a/InvenTree/plugins/integration.py b/InvenTree/plugins/integration.py
index 194c974939..a8e8a6d352 100644
--- a/InvenTree/plugins/integration.py
+++ b/InvenTree/plugins/integration.py
@@ -163,6 +163,25 @@ class NavigationMixin:
         does this plugin define navigation elements
         """
         return bool(self.navigation)
+
+
+class AppMixin:
+    """Mixin that enables full django app functions for a plugin"""
+    class Meta:
+        """meta options for this mixin"""
+        MIXIN_NAME = 'App registration'
+
+    def __init__(self):
+        super().__init__()
+        self.add_mixin('app', 'has_app', __class__)
+
+    @property
+    def has_app(self):
+        """
+        this plugin is always an app with this plugin
+        """
+        return True
+
 # endregion