Docs menu

Install StageWhisper in Django

Install StageWhisper in Django by adding one async script tag to your base template — every template that extends it inherits the widget, so one edit covers your whole app. No package, no app to register, no migration.

Prerequisites

  • A StageWhisper site created in the dashboard.
  • Your app’s origin on the site’s origin allowlist — enable the localhost toggle while you test with runserver locally.

Add the loader to your base template

  1. Open templates/base.html — the template every page {% extends %} — so the widget rides along on every page without per-view wiring.
  2. Paste the loader tag inside the <head>, and swap pub_your_site_key for the public site key shown on your site’s install page in the dashboard:
    templates/base.html
    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <title>{% block title %}My app{% endblock %}</title>
        <script async src="https://cdn.stagewhisper.co/loader.js" data-sw-key="pub_your_site_key"></script>
        {% block extra_head %}{% endblock %}
      </head>
      <body>
        {% block content %}{% endblock %}
      </body>
    </html>
    

The tag is async, so it never blocks your page render — the widget mounts quietly once the page is up.

Strict CSP with django-csp

Serving a strict Content Security Policy with django-csp? Install its middleware and enable per-request nonces by including the NONCE constant (csp.constants.NONCE) in your script-src directive config:

settings.py
# settings.py
from csp.constants import NONCE, SELF

MIDDLEWARE = [
    # ...
    "csp.middleware.CSPMiddleware",
]

CONTENT_SECURITY_POLICY = {
    "DIRECTIVES": {
        "script-src": [SELF, NONCE, "https://cdn.stagewhisper.co"],
        "style-src": [SELF, NONCE],
        "connect-src": [SELF, "https://api-staging.stagewhisper.co"],
    },
}

Then carry the nonce on the loader tag itself with nonce="{{ request.csp_nonce }}":

Loader tag with nonce
<script async src="https://cdn.stagewhisper.co/loader.js" data-sw-key="pub_your_site_key" nonce="{{ request.csp_nonce }}"></script>

The Content Security Policy guide has the full directive list, including the Turnstile origins to allow if you enable it.

Verify

Refresh your app, then watch the site’s install status in the dashboard — it flips the moment the first ping arrives.

Widget not showing up? Head to Troubleshooting for the usual suspects — blocked origins, CSP, localhost, and stale config.