diff --git a/odl_video/middleware.py b/odl_video/middleware.py
new file mode 100644
index 000000000..3abe850c2
--- /dev/null
+++ b/odl_video/middleware.py
@@ -0,0 +1,17 @@
+"""Custom middleware for the odl_video project"""
+
+
+class RobotsTagMiddleware:
+ """Add an X-Robots-Tag header to every response so search engines are
+ told not to index any page, regardless of which template (if any)
+ rendered it. This covers views that don't extend base.html, such as
+ the Django admin and DRF browsable API (see mitodl/hq#12798).
+ """
+
+ def __init__(self, get_response):
+ self.get_response = get_response
+
+ def __call__(self, request):
+ response = self.get_response(request)
+ response["X-Robots-Tag"] = "noindex, nofollow"
+ return response
diff --git a/odl_video/middleware_test.py b/odl_video/middleware_test.py
new file mode 100644
index 000000000..9a23b68b5
--- /dev/null
+++ b/odl_video/middleware_test.py
@@ -0,0 +1,9 @@
+"""Tests for odl_video.middleware"""
+
+
+def test_admin_login_has_noindex_header(client):
+ """The X-Robots-Tag header should be present even on pages that don't
+ extend base.html, such as the Django admin (see mitodl/hq#12798)
+ """
+ response = client.get("/admin/login/")
+ assert response["X-Robots-Tag"] == "noindex, nofollow"
diff --git a/odl_video/settings.py b/odl_video/settings.py
index 0b44b4657..6c7944349 100644
--- a/odl_video/settings.py
+++ b/odl_video/settings.py
@@ -101,6 +101,7 @@
"hijack.middleware.HijackUserMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
+ "odl_video.middleware.RobotsTagMiddleware",
]
# enable the nplusone profiler only in debug mode
diff --git a/ui/templates/base.html b/ui/templates/base.html
index 76f30ca11..bb22a7562 100644
--- a/ui/templates/base.html
+++ b/ui/templates/base.html
@@ -6,6 +6,7 @@
{% load hijack %}
+