Installation guides
Flask and FastAPI
Add ProductLense to a Flask or FastAPI site in the Jinja2 base template, then identify the signed-in user with the tojson filter.
Flask and FastAPI both render HTML with Jinja2 templates. Put the script in the base template that other pages extend, and every page carries it. If your FastAPI app only serves an API to a separate frontend, follow the guide for that frontend instead, such as React (Vite).
Add the script
Replace SITE_ID with the id from Settings → Sites in the ProductLense dashboard.
<!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>In FastAPI, render pages with Jinja2Templates(directory="templates") and templates.TemplateResponse(request, "page.html", context) so they extend the same base.
Identify users
Jinja2's tojson filter escapes the value for use inside a script block:
{% if user_id %}
<script>
window.productlense('identify', String({{ user_id|tojson }}));
</script>
{% endif %}Pass user_id from the view: in Flask with Flask-Login, current_user.get_id() when current_user.is_authenticated; in FastAPI, from whatever dependency resolves the signed-in user. Place the block after the queue stub. Use the same id you store on the customer in your billing provider; see how payments are attributed.
Events from your server
Actions that happen only on the server, such as a background 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.
Verify your installation
- Deploy, then open your site in a normal browser window.
- Open the Live page in the ProductLense dashboard. Your visit appears within a few seconds.
- In the browser's developer tools, the Network tab shows a
POSTtohttps://api.productlense.app/api/ewith status204.
During development, open flask run or uvicorn 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.