diff --git a/common/djangoapps/student/views/dashboard.py b/common/djangoapps/student/views/dashboard.py
index 38d4ef1fdad06d22eba37e26b0291056efc1dcda..96a57c693484aec361d400773a4a4d338a4b8109 100644
--- a/common/djangoapps/student/views/dashboard.py
+++ b/common/djangoapps/student/views/dashboard.py
@@ -47,6 +47,8 @@ from openedx.core.djangoapps.catalog.utils import (
     get_visible_sessions_for_entitlement
 )
 from openedx.core.djangoapps.credit.email_utils import get_credit_provider_attribute_values, make_providers_strings
+from openedx.core.djangoapps.plugins.plugin_contexts import get_plugins_view_context
+from openedx.core.djangoapps.plugins import constants as plugin_constants
 from openedx.core.djangoapps.programs.models import ProgramsApiConfig
 from openedx.core.djangoapps.programs.utils import ProgramDataExtender, ProgramProgressMeter
 from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
@@ -880,6 +882,13 @@ def student_dashboard(request):
         # TODO START: clean up as part of REVEM-199 (END)
     }
 
+    context_from_plugins = get_plugins_view_context(
+        plugin_constants.ProjectType.LMS,
+        plugin_constants.PluginContexts.VIEWS.STUDENT_DASHBOARD,
+        context
+    )
+    context.update(context_from_plugins)
+
     if ecommerce_service.is_enabled(request.user):
         context.update({
             'use_ecommerce_payment_flow': True,
diff --git a/openedx/core/djangoapps/plugins/README.rst b/openedx/core/djangoapps/plugins/README.rst
index 2013200231ed5b2055e8ff622738b194c4a26a2b..dfab6e0d267824f2f7294e947efdb34318c5140e 100644
--- a/openedx/core/djangoapps/plugins/README.rst
+++ b/openedx/core/djangoapps/plugins/README.rst
@@ -106,7 +106,7 @@ class::
 
     from django.apps import AppConfig
     from openedx.core.djangoapps.plugins.constants import (
-        ProjectType, SettingsType, PluginURLs, PluginSettings
+        ProjectType, SettingsType, PluginURLs, PluginSettings, PluginContexts
     )
     class MyAppConfig(AppConfig):
         name = u'full_python_path.my_app'
@@ -184,6 +184,19 @@ class::
                         PluginSignals.SENDER_PATH: u'full_path_to_sender_app.ModelZ',
                     }],
                 }
+            },
+
+            # Configuration setting for Plugin Contexts for this app.
+            PluginContexts.CONFIG: {
+
+                # Configure the Plugin Signals for each Project Type, as needed.
+                ProjectType.LMS: {
+
+                    # Key is the view that the app wishes to add context to and the value
+                    # is the function within the app that will return additional context
+                    # when called with the original context
+                    PluginContexts.VIEWS.STUDENT_DASHBOARD: u'my_app.context_api.get_dashboard_context'
+                }
             }
         }
 
@@ -217,6 +230,11 @@ OR use string constants when they cannot import from djangoapps.plugins::
                         u'sender_path': u'full_path_to_sender_app.ModelZ',
                     }],
                 }
+            },
+            u'context_config': {
+                u'lms.djangoapp': {
+                    'student_dashboard': u'my_app.context_api.get_dashboard_context'
+                }
             }
         }
 
diff --git a/openedx/core/djangoapps/plugins/constants.py b/openedx/core/djangoapps/plugins/constants.py
index 56949535dffe2cb41e11b7bb53ff2f850dd89c90..8683429ce86fa1218b342e23e7175a6ea9a2dd0a 100644
--- a/openedx/core/djangoapps/plugins/constants.py
+++ b/openedx/core/djangoapps/plugins/constants.py
@@ -76,3 +76,19 @@ class PluginSignals(object):
 
     RELATIVE_PATH = u'relative_path'
     DEFAULT_RELATIVE_PATH = u'signals'
+
+
+class PluginContextsViews(object):
+    STUDENT_DASHBOARD = u'student_dashboard'
+
+
+class PluginContexts(object):
+    """
+    The PluginContexts enum defines dictionary field names (and defaults)
+    that can be specified by a Plugin App in order to configure the
+    additional views it would like to add context into.
+    """
+    CONFIG = u"context_config"
+
+    VIEWS = PluginContextsViews
+
diff --git a/openedx/core/djangoapps/plugins/plugin_contexts.py b/openedx/core/djangoapps/plugins/plugin_contexts.py
new file mode 100644
index 0000000000000000000000000000000000000000..abf482c67cfdb7d3b3234dd328a7ac060e61cd44
--- /dev/null
+++ b/openedx/core/djangoapps/plugins/plugin_contexts.py
@@ -0,0 +1,35 @@
+from importlib import import_module
+
+from logging import getLogger
+from . import constants, registry
+
+log = getLogger(__name__)
+
+
+def get_plugins_view_context(project_type, view_name, existing_context={}):
+    """
+    Returns a dict of additonal view context. Will check if any plugin apps
+    have that view in their context_config, and if so will call their
+    selected function to get their context dicts.
+    """
+    aggregate_context = {}
+
+    for app_config in registry.get_app_configs(project_type):
+        context_function_path = _get_context_function(app_config, project_type, view_name)
+        if context_function_path:
+            module_path, _, name = context_function_path.rpartition('.')
+            context_function = getattr(import_module(module_path), name)
+            plugin_context = context_function(existing_context)
+
+            # NOTE: If two plugins have try to set the same context keys, the last one
+            # called will overwrite the others.
+            aggregate_context.update(plugin_context)
+
+    return aggregate_context
+
+
+def _get_context_function(app_config, project_type, view_name):
+    plugin_config = getattr(app_config, constants.PLUGIN_APP_CLASS_ATTRIBUTE_NAME, {})
+    context_config = plugin_config.get(constants.PluginContexts.CONFIG, {})
+    project_type_settings = context_config.get(project_type, {})
+    return project_type_settings.get(view_name)