{"id":31482303,"url":"https://github.com/snowflake-labs/streamlit-page-analytics","last_synced_at":"2026-04-02T18:41:01.030Z","repository":{"id":311997301,"uuid":"1044564979","full_name":"Snowflake-Labs/streamlit-page-analytics","owner":"Snowflake-Labs","description":"Capture user interactions in your streamlit apps to logs","archived":false,"fork":false,"pushed_at":"2025-09-23T07:51:58.000Z","size":206,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-23T09:27:25.040Z","etag":null,"topics":["analytics","google-analytics","log-analytics","monitoring","streamlit"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Snowflake-Labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-25T22:08:31.000Z","updated_at":"2025-09-23T07:49:20.000Z","dependencies_parsed_at":"2025-08-28T07:20:43.598Z","dependency_job_id":"4c4d850e-6191-4ec6-8ead-33831327c5fa","html_url":"https://github.com/Snowflake-Labs/streamlit-page-analytics","commit_stats":null,"previous_names":["snowflake-labs/streamlit-page-analytics"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/Snowflake-Labs/streamlit-page-analytics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Snowflake-Labs%2Fstreamlit-page-analytics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Snowflake-Labs%2Fstreamlit-page-analytics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Snowflake-Labs%2Fstreamlit-page-analytics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Snowflake-Labs%2Fstreamlit-page-analytics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Snowflake-Labs","download_url":"https://codeload.github.com/Snowflake-Labs/streamlit-page-analytics/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Snowflake-Labs%2Fstreamlit-page-analytics/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277974415,"owners_count":25908396,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-02T02:00:08.890Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","google-analytics","log-analytics","monitoring","streamlit"],"created_at":"2025-10-02T07:47:22.409Z","updated_at":"2026-04-02T18:41:01.023Z","avatar_url":"https://github.com/Snowflake-Labs.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Streamlit Page Analytics\n\nA Python library for building page analytics in Streamlit applications through logging.\n\nThe solution instruments all `st.\u003cwidget\u003e` with a wrapper function which emits logs,\nthese logs can then be processed to derive analytics information.\n\nThis solution is inspired from [jrieke/streamlit-analytics](https://github.com/jrieke/streamlit-analytics) idea.\n\nEvents are emitted as **JSON objects** (one object per log record) via Python’s `logging` API, using the configured logger and log level (default `INFO`).\n\n### Log format\n\nEach line is a single JSON object produced from a `UserEvent` (or equivalent) after enrichment:\n\n| Field | Meaning |\n|-------|---------|\n| `session_id` | From `StreamlitPageAnalytics` (constructor or `set_session_id`) |\n| `user_id` | From `StreamlitPageAnalytics` (constructor or `set_user_id`) |\n| `page_name` | Present when page tracking is active and set |\n| `action` | Event type (string); see table below |\n| `widget` | Present when the event targets a widget (id, type, label, values, etc.); omitted when empty |\n| `extra` | Additional payload (form field snapshots, notices, etc.); omitted when empty |\n\nEmpty or null values are typically **omitted** from the JSON (`clean_values`).\n\n**`action` values** (see `UserEventAction` in code): `start_tracking`, `form_instrumentation_notice`, `click`, `change`, `submit`, `other`.\n\n## Installation\nUse the releases to download assets:\n\n### Local\nTo run it locally, Download the wheel(`.whl`) file and install or\ninstall from git:\n\n```bash\npip install \\\ngit+https://github.com/Snowflake-Labs/streamlit-page-analytics@latest\n```\n### Streamlit in Snowflake (SiS)\nDownload the `streamlit_page_analytics-\u003cversion\u003e.zip` file and copy it to a\nSnowflake Internal Stage for use in SiS and run the following command:\n\n```snowflake\nALTER STREAMLIT \u003cyour-streamlit-name\u003e SET \n  IMPORTS = ('@\u003cyour-internal-stage\u003e/\u003cpath/to/your/zip/file\u003e');\n```\n\n## Usage\n\n```python\nimport streamlit as st\nfrom streamlit_page_analytics import StreamlitPageAnalytics\n\nwith StreamlitPageAnalytics.track(\n    name=\"my-app\", session_id=f\"{session_id}\", user_id=f\"{user_id}\"\n):\n\n    st.title(\"My Awesome App\")\n    st.button('my awesome button')\n```\n\nor\n\n```python\nimport streamlit as st\nfrom streamlit_page_analytics import StreamlitPageAnalytics\n\npage_analytics = StreamlitPageAnalytics(\n        name=\"my-app\", session_id=f\"{session_id}\", user_id=f\"{user_id}\"\n)\n\npage_analytics.start_tracking()\n\nst.title(\"My Awesome App\")\nst.button('my awesome button')\n\npage_analytics.stop_tracking()\n```\n\n### Page Tracking\n\nTrack page visits in multi-page Streamlit applications by passing a `page_name` to `start_tracking()`. A `start_tracking` event is logged only when the user navigates to a different page, avoiding duplicate logs on page reruns.\n\n```python\nimport streamlit as st\nfrom streamlit_page_analytics import StreamlitPageAnalytics\n\npage_analytics = StreamlitPageAnalytics(\n    name=\"my-app\", session_id=f\"{session_id}\", user_id=f\"{user_id}\"\n)\n\n# Pass the current page name - logs only when page changes\npage_analytics.start_tracking(page_name=\"Home\")\n\nst.title(\"Home Page\")\nst.button(\"Click me\")\n\npage_analytics.stop_tracking()\n```\n\nWhen the user navigates between pages:\n- `start_tracking(page_name=\"Home\")` - Logs (first visit)\n- `start_tracking(page_name=\"Home\")` - No log (same page, e.g., rerun)\n- `start_tracking(page_name=\"Settings\")` - Logs (different page)\n- `start_tracking(page_name=\"Home\")` - Logs (navigated back)\n\nIf `page_name` is not provided or is empty, no page tracking event is logged.\n\n### Forms (`st.form`)\n\nStreamlit does not allow `on_change` / `on_click` on widgets inside a form except on `st.form_submit_button`. This library therefore does **not** attach per-widget analytics callbacks to inputs inside `st.form()`. Instead:\n\n- **One-time notice (`form_instrumentation_notice`)** — The first time a tracked widget is created inside a form in a session, the library logs a single event through the same **`log_event`** path as every other analytics event, so **`session_id`**, **`user_id`**, and optional **`page_name`** match the rest of the stream. The human-readable explanation is in **`extra.message`**. There is usually **no `widget`** on this object after serialization (same as other events with no element).\n- **Submit (`submit`)** — When the user presses **`st.form_submit_button`**, a **`submit`** event is logged. The **submit button** appears under **`widget`**. Registered field values at submit time are in top-level **`extra`**: **`extra.form_id`** and **`extra.form_fields`** (each entry: id, type, label, value). Masking options apply to text inputs and text areas in that snapshot the same way as elsewhere.\n- If you pass your own `on_change` or `on_click` on a widget **inside** a form, Streamlit may reject it or it conflicts with form rules; this package does **not** forward those developer callbacks for form widgets. Use callbacks on `st.form_submit_button` if you need custom logic on submit.\n\n### Masking Text Input Values\n\nFor privacy-sensitive applications, you can mask the values of `text_input` and `text_area` widgets in the logs by setting `mask_text_input_values=True`. When enabled, the actual input values will be replaced with `\"[REDACTED]\"` in the log output.\n\n```python\nimport streamlit as st\nfrom streamlit_page_analytics import StreamlitPageAnalytics\n\nwith StreamlitPageAnalytics.track(\n    name=\"my-app\",\n    session_id=f\"{session_id}\",\n    user_id=f\"{user_id}\",\n    mask_text_input_values=True,  # Enable masking for text inputs\n):\n    st.text_input(\"Password\")  # Value will be logged as \"[REDACTED]\"\n    st.text_area(\"Notes\")      # Value will be logged as \"[REDACTED]\"\n    st.selectbox(\"Option\", [\"A\", \"B\"])  # Not affected, logs actual value\n```\n\n## Current Status\n\nThe following Streamlit widgets are currently supported:\n- `st.button` - Click events\n- `st.form_submit_button` - Submit events; combined snapshot of tracked form fields in `extra.form_fields` when used inside `st.form()`\n- `st.checkbox` - Change events\n- `st.radio` - Change events\n- `st.selectbox` - Change events\n- `st.multiselect` - Change events\n- `st.slider` - Change events\n- `st.select_slider` - Change events\n- `st.text_input` - Change events\n- `st.number_input` - Change events\n- `st.text_area` - Change events\n- `st.date_input` - Change events\n- `st.time_input` - Change events\n- `st.file_uploader` - Change events\n- `st.color_picker` - Change events\n\n\n## Analytics Tables\nUse the sample [analytics script](dashboard/snowflake_views_dynamic_tables.sql) to setup analytics on top of the\nlogs can be quickly built using dynamic tables.\n\n## Developer documentation\n\n- **[DEVELOPMENT.md](DEVELOPMENT.md)** — Workflow, tasks, and how integration tests assert on JSON logs.\n- **[LINTING.md](LINTING.md)** — Linter configuration and commands.\n\n## Disclaimer\nLicense: Apache 2.0\n\nThis is not an official Snowflake product or feature.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnowflake-labs%2Fstreamlit-page-analytics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnowflake-labs%2Fstreamlit-page-analytics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnowflake-labs%2Fstreamlit-page-analytics/lists"}