diff --git a/src/hub.html b/src/hub.html
index 45a849b2fc267bb1b35cdf84fe8be64be50852a7..1b840263256ffed825b44ecfb0e9bae8377d6598 100644
--- a/src/hub.html
+++ b/src/hub.html
@@ -10,9 +10,6 @@
     <link rel="shortcut icon" type="image/png" href="/favicon.ico">
     <title>Get together | Hubs by Mozilla</title>
     <link href="https://fonts.googleapis.com/css?family=Zilla+Slab:300,300i,400,400i,700" rel="stylesheet">
-
-    <!-- HACK: this has to run after A-Frame but before our bundle, since A-Frame blows away the local storage setting -->
-    <script src="https://cdn.rawgit.com/gfodor/ba8f88d9f34fe9cbe59a01ce3c48420d/raw/03e31f0ef7b9eac5e947bd39e440f34df0701f75/naf-janus-adapter-logging.js" integrity="sha384-4q1V8Q88oeCFriFefFo5uEUtMzbw6K116tFyC9cwbiPr6wEe7050l5HoJUxMvnzj" crossorigin="anonymous"></script>
 </head>
 
 <body>
diff --git a/src/hub.js b/src/hub.js
index 564462417517e2ac606c2c2a371957605230194f..608c741514a9d3e3345d9e1c20df9ba2ae912f31 100644
--- a/src/hub.js
+++ b/src/hub.js
@@ -3,6 +3,7 @@ console.log(`Hubs version: ${process.env.BUILD_VERSION || "?"}`);
 import "./assets/stylesheets/hub.scss";
 
 import "aframe";
+import "./utils/logging";
 import { patchWebGLRenderingContext } from "./utils/webgl";
 patchWebGLRenderingContext();
 
@@ -129,12 +130,7 @@ import registerTelemetry from "./telemetry";
 
 import { getAvailableVREntryTypes, VR_DEVICE_AVAILABILITY } from "./utils/vr-caps-detect.js";
 import ConcurrentLoadDetector from "./utils/concurrent-load-detector.js";
-
-function qsTruthy(param) {
-  const val = qs.get(param);
-  // if the param exists but is not set (e.g. "?foo&bar"), its value is the empty string.
-  return val === "" || /1|on|true/i.test(val);
-}
+import qsTruthy from "./utils/qs_truthy";
 
 const isBotMode = qsTruthy("bot");
 const isTelemetryDisabled = qsTruthy("disable_telemetry");
diff --git a/src/react-components/2d-hud.js b/src/react-components/2d-hud.js
index d017dcad47918a476931237eb453fa5d1971a8a8..8bcec6c7137d1a47f8322610fbf3c4891ee1774b 100644
--- a/src/react-components/2d-hud.js
+++ b/src/react-components/2d-hud.js
@@ -3,6 +3,7 @@ import PropTypes from "prop-types";
 import cx from "classnames";
 
 import styles from "../assets/stylesheets/2d-hud.scss";
+import qsTruthy from "../utils/qs_truthy";
 
 const TopHUD = ({ muted, frozen, spacebubble, onToggleMute, onToggleFreeze, onToggleSpaceBubble }) => (
   <div className={cx(styles.container, styles.top)}>
@@ -39,7 +40,7 @@ TopHUD.propTypes = {
 
 const BottomHUD = ({ onCreateObject }) => (
   <div className={cx(styles.container, styles.bottom)}>
-    {new URLSearchParams(document.location.search).get("mediaTools") === "true" && (
+    {qsTruthy("mediaTools") && (
       <div
         className={cx("ui-interactive", styles.iconButton, styles.large, styles.createObject)}
         title={"Create Object"}
diff --git a/src/utils/logging.js b/src/utils/logging.js
new file mode 100644
index 0000000000000000000000000000000000000000..44da14381116618bd8c660664eda95b2efa53a80
--- /dev/null
+++ b/src/utils/logging.js
@@ -0,0 +1,12 @@
+// A-Frame blows away any npm debug log filters so this allow the user to set the log filter
+// via the query string.
+import debug from "debug";
+import qsTruthy from "./qs_truthy";
+
+const qs = new URLSearchParams(location.search);
+const isDebug = qsTruthy("debug");
+const logFilter = qs.get("log_filter") || (isDebug && "naf-janus-adapter:*");
+
+if (logFilter) {
+  debug.enable(logFilter);
+}
diff --git a/src/utils/qs_truthy.js b/src/utils/qs_truthy.js
new file mode 100644
index 0000000000000000000000000000000000000000..5876ae3713415c7f7fcf2a838194dcfbe6a794b1
--- /dev/null
+++ b/src/utils/qs_truthy.js
@@ -0,0 +1,7 @@
+const qs = new URLSearchParams(location.search);
+
+export default function qsTruthy(param) {
+  const val = qs.get(param);
+  // if the param exists but is not set (e.g. "?foo&bar"), its value is the empty string.
+  return val === "" || /1|on|true/i.test(val);
+}