Skip to main content

streamlit-analytics2

Privacy-first usage analytics for Streamlit apps. One with block gives you pageviews, visitors, widget clicks, custom events, a built-in dashboard and SQL over your own data. No JavaScript, no cookies, no IP addresses stored.

PyPI Python Downloads License: MIT Build

Use it

  1. Install:
    pip install streamlit-analytics2
    
  2. Wrap your app:
    import streamlit as st
    import streamlit_analytics2 as sa2
    
    with sa2.track():
        st.write("Hello")
        st.button("Click me")
    
  3. Open your app with ?analytics=on on the URL:
    http://localhost:8501/?analytics=on
    

That is the whole integration. Everything below is optional.

Dashboard: views, visits, visitors, bounce rate, visit time, active now, views per page over time

Keep the numbers across restarts

with sa2.track(save_to_json="analytics.json"):   # counters + analytics.events.jsonl
    ...

with sa2.track(events_path="analytics.db"):      # SQLite, unlocks the query tab
    ...

Protect the dashboard

with sa2.track(unsafe_password=st.secrets["analytics_password"]):
    ...

The password is plain text inside the app, so keep it in st.secrets or an environment variable and pick something you would not reuse.

What the dashboard shows

  • Views, visits, visitors, bounce rate, average visit time, active now.
  • Views per page over time, hourly for today, with range and page filters.
  • Pages, widgets, browsers, OS, devices, languages, regions, UTM sources and campaigns, custom events.
  • A weekday-by-hour traffic-load heatmap and the busiest hour.
  • Recent visits.
  • Raw data query: read-only SQL over the SQLite log, example queries, CSV download and a chart picker. Needs events_path on a .db file and a password.

Your own runs with ?analytics=on open are not counted.

Breakdowns: pages, widgets, browsers, devices, OS, languages, regions

Traffic load: weekday by hour heatmap

Raw data query: SQL over your own event log, shown as a line chart

Track your own events

if st.button("Generate report"):
    sa2.event("report generated", rows=len(df))

Privacy

Stored per visit: a hash of address and browser that changes every day, browser, OS and device family, language, timezone, theme, UTM tags, pages. Stored per interaction: widget type, label, key, page and the chosen option.

Never stored: IP addresses, raw User-Agent strings, query strings, or anything typed into text fields. Set store_values=True if you do want typed text.

Options

Argument Default What it does
unsafe_password None Password for the dashboard. Also gates the reset and the query tab.
save_to_json None Counters file (0.10 shape). Events go to <name>.events.jsonl beside it.
load_from_json None Load counters from that file at start.
events_path None Event log path. .jsonl by default, .db / .sqlite for SQLite.
store None Your own backend: any object with append(events) and read().
store_values False Record typed text instead of <text>.
session_id None Also keep per-session counters in Firestore under this document.
firestore_key_file, firestore_collection_name, firestore_document_name, firestore_project_name, streamlit_secrets_firestore_key Persist the counters in Firestore. See the wiki.
verbose False Log what is loaded and saved.

start_tracking() and stop_tracking() take the same arguments if you prefer them to the with block. Every event is a plain record (ts, kind, session, visitor, page, name, widget_type, key, value, props), so the log is easy to feed into pandas, DuckDB or an LLM.

Multipage apps

Call sa2.track() on every page. Views and widgets are recorded per page in the event log and on the dashboard. The legacy counters in streamlit_analytics2.data are shared across pages, as before.

How it works

Streamlit already knows which widget a user changed on each rerun. This library reads that from one place instead of wrapping every st.* function, so widgets inside columns, forms, expanders, tabs, dialogs and the sidebar are all seen, and a widget rendering with its default is never counted as a click.

Upgrading from 0.10

Nothing to change in your code. The numbers will be lower because a widget rendering with its default no longer counts as an interaction, typed text is no longer stored unless you ask, and the dashboard reset now needs a password. Details in CHANGELOG.md.

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md. Development: uv sync --all-extras && uv run pytest. A dev app with every widget type lives in examples/dev/; examples/dev/seed.py fills a dev log with made-up traffic so the dashboard has something to show.

License

MIT. See LICENSE.

Release files for streamlit-analytics2 0.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for streamlit-analytics2 0.11.0
File Size Uploaded
streamlit_analytics2-0.11.0.tar.gz 28.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for streamlit-analytics2 0.11.0
File Interpreter ABI Platform
streamlit_analytics2-0.11.0-py3-none-any.whl Python 3 none any Details

Total release size: 61.2 kB

Release files / streamlit_analytics2-0.11.0.tar.gz

Download URL streamlit_analytics2-0.11.0.tar.gz
Size 28.7 kB
Tags Source
SHA-256 checksum
How to use checksums
65a1c490c7b5e88d4744d71d5c9f54af134b7dcd0380012b6cedd68199f08a50
BLAKE2b-256 checksum
How to use checksums
97fe5789bf741c359f7df4bfe48a2b266877e57f9203449242f6ff98983e1e51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / streamlit_analytics2-0.11.0-py3-none-any.whl

Download URL streamlit_analytics2-0.11.0-py3-none-any.whl
Size 32.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d38f6f74f8d8d1c14bc74e5826d57f09bfea3c438b7275643ac3d7ec2acf54cd
BLAKE2b-256 checksum
How to use checksums
01fcdeaecc0861bc7fbaa81b91d1aac4c1bf56dee7097350628f1ae946e44ea4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.11.0 This release

2 release files

0.10.7

2 release files

0.10.6

2 release files

0.10.4

2 release files

0.10.3

2 release files

0.10.2

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.8

2 release files

0.8.7

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.7

2 release files

0.7.6

2 release files

0.7.5

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.6.5

2 release files

0.6.4

2 release files

0.6.3

2 release files

0.6.1

2 release files

0.5.3

2 release files

0.4.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page