# Django

Add ProductLense to a Django site in base.html, then identify the signed-in user with the json_script filter.

In Django the script goes into the base template that your other templates extend, usually `templates/base.html`. Every rendered page then carries it.

## Add the script

Replace `SITE_ID` with the id from Settings → Sites in the ProductLense dashboard.

```html title="templates/base.html" {5-6}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <script>window.productlense=window.productlense||function(){(window.productlense.q=window.productlense.q||[]).push(arguments)}</script>
    <script defer data-site="SITE_ID" src="https://api.productlense.app/a.js"></script>
    <title>{% block title %}{% endblock %}</title>
  </head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>
```

If you use `django-csp`, add `https://api.productlense.app` to `script-src` and `connect-src`; see [Content Security Policy](/docs/install/script-tag#content-security-policy).

## Identify users

`json_script` writes the value into a JSON block that cannot break out of the page, and a short script reads it:

```html title="templates/base.html" {2-6}
{% if user.is_authenticated %}
  {{ user.pk|json_script:"productlense-uid" }}
  <script>
    var uid = JSON.parse(document.getElementById('productlense-uid').textContent);
    window.productlense('identify', String(uid));
  </script>
{% endif %}
```

Place it after the queue stub. Use the same id you store on the customer in your billing provider; see [how payments are attributed](/docs/revenue/attribution).

## Events from your server

Actions that happen only on the server, such as a Celery task that converts a trial, can be sent to the Events API with an API key. API keys are on the Scale plan; see [server-side events](/docs/install/server-side-events).

## Verify your installation

1. Deploy, then open your site in a normal browser window.
2. Open the Live page in the ProductLense dashboard. Your visit appears within a few seconds.
3. In the browser's developer tools, the Network tab shows a `POST` to `https://api.productlense.app/api/e` with status `204`.

During development, open `manage.py runserver` at `localhost`, where nothing is sent unless you add `data-dev="true"` to the tag. The script skips only the hostname `localhost`; events from `127.0.0.1` are sent and then rejected, because that host is not on the site's list. Ad blockers in your own browser may block the request. If the visit does not appear, follow [Verify your installation](/docs/install/verify).
