Install · Django

Bug reports and feedback from your Django site, in one script tag.

Add a Django feedback widget and bug report button with one script tag in your base template. No pip package, no middleware and no migrations.
Start freeNo credit card required.

Where it goes

In your base template, usually templates/base.html, just before the closing body tag.

Setup

Adding the widget to Django

  1. 01

    Copy your widget key

    From the Widget tab of your project in UserWants. The key starts with uw_pk_ and is public by design: it is rendered into every response you send, and the domain allowlist rather than secrecy is what limits where it works.

  2. 02

    Add the tag to your base template

    Every template that extends base.html inherits the widget from a single edit, including the admin-facing pages if they share the base. Read the key from settings rather than hard-coding it.

    html
    {# templates/base.html #}
        {% block content %}{% endblock %}
    
        <script
          src="https://userwants.app/widget.js"
          data-userwants-key="{{ USERWANTS_KEY }}"
          defer
        ></script>
      </body>
  3. 03

    Expose the key through a context processor

    Add a tiny context processor so the template does not reach into settings itself. This is also what lets staging and production point at different UserWants projects from the same template.

    python
    # context_processors.py
    from django.conf import settings
    
    def userwants(request):
        return {'USERWANTS_KEY': settings.USERWANTS_KEY}
  4. 04

    Identify the signed-in user and allow your domain

    Django already knows who is authenticated, so passing the id costs three lines and means the reporter is never asked for an email. Then add your production hostname under Allowed domains in the Widget tab, since the list fails closed.

    html
    {% if user.is_authenticated %}
      <script>
        window.UserWants?.identify({
          identifier: "{{ user.pk }}",
          name: "{{ user.get_full_name|escapejs }}",
          email: "{{ user.email|escapejs }}"
        });
      </script>
    {% endif %}

Worth knowing

What bites on Django

The things that are specific to a Python framework, rather than true of every install.
  • django-csp needs two directives

    If you use django-csp, add https://userwants.app to CSP_SCRIPT_SRC and CSP_CONNECT_SRC. With only the script directive the button appears and submitting fails silently, which is the hardest version of this bug to diagnose.

  • Always escape user values

    The escapejs filter above is not optional. A display name containing a quote will otherwise break the script tag and take the widget down with it.

  • It does not see your Python tracebacks

    The widget collects JavaScript errors from the browser. A 500 from a Django view produces an error page, and the report will carry the URL, the screenshot and the description — pair it with Sentry or your logs for the traceback.

FAQ

Questions

Is there a pip package or Django app to install?
No. Nothing runs on your server, so there is no package, no middleware, no settings block beyond one key and no migrations. The only Django code is the optional context processor that passes the key to your template.
Does it work with Django templates and HTMX together?
Yes. HTMX swaps fragments rather than reloading the document, so the widget attaches once and stays. Each swap that changes the URL is recorded as a step, which shows in the report as the path the person took.

The full reference — every field the widget collects, the domain allowlist rules and the JavaScript API — is in the widget docs.

Try it on your Django site.

Paste the tag, add your domain, and the next report arrives with the screenshot and the JavaScript error already attached.