Web analytics for PhoenixKit sites, recorded by the server — who comes, where from, what they do, and when they leave.
Where the data comes from
PhoenixKitWebAnalytics.Plug— one line in the host's browser pipeline records every HTML page view.PhoenixKitWebAnalytics.LiveHook— on LiveView pages, records live navigation, every event the LiveView handles (by name, never form contents), and — throughPhoenixKitWebAnalytics.LivePresence— when the visitor leaves and who is online right now.- The optional client script (
js_sources/0) — outbound and download clicks, scroll depth, exits from pages without a LiveView. Its reports are stored only when switched on in Settings. track_event/2— facts your server already knows.
No cookie, no IP address, no raw User-Agent and no query string is stored;
visitors are a salted daily hash — see PhoenixKitWebAnalytics.Visitor.
Reports and alerts
Admin pages: overview, right now, sessions with a per-visit timeline, pages,
acquisition, technology, events, settings. Everything they show comes from
PhoenixKitWebAnalytics.Reports, a plain module you can call:
alias PhoenixKitWebAnalytics.Reports
Reports.top_paths(Reports.filter(period: "30d"), limit: 20)PhoenixKitWebAnalytics.Alerts registers a "Website activity" notification
type — new visitors (filtered), sign-ups, tracked events — delivered through
PhoenixKit's notification channels (in-app, email, Telegram, digests).
Installation
# host mix.exs
{:phoenix_kit_web_analytics, "~> 0.2"}Then mix deps.get and mix phoenix_kit.update, add the plug and the hook,
list :peer_data, :x_headers and :user_agent in the LiveView socket's
connect_info (websocket and longpoll), and enable the module on the admin
Modules page.
Data growth
PhoenixKitWebAnalytics.Retention rolls completed days into daily totals and
prunes raw events past the retention window (365 days by default), so the
trend line is permanent while the row count is bounded.
Summary
Functions
Sidebar entries. Routes come from route_module/0, so no tab carries a
:live_view — these are navigation and active-state anchors only.
Background workers: the task supervisor that absorbs writes off the request path, and the hourly rollup/prune pass — plus a one-off check of the application config, logged once as the module starts.
Turns tracking on, generating the visitor-hash salt if this is a first enable — so the very first request already hashes against a real secret.
Whether tracking is on.
Summary shown on the admin Modules page.
The optional client script (clicks the server can't see, scroll depth, exits
from non-LiveView pages), folded into the host's phoenix_kit_modules.js.
It sends nothing the server accepts until Client script is switched on
in settings.
The events + daily stats tables (run by mix phoenix_kit.update).
The Website activity notification type — new visitors, sign-ups and
tracked events. See PhoenixKitWebAnalytics.Alerts.
The admin pages plus the public collection endpoints.
Records a custom event from server-side code.
Records a page view from server-side code.
Functions
Sidebar entries. Routes come from route_module/0, so no tab carries a
:live_view — these are navigation and active-state anchors only.
Background workers: the task supervisor that absorbs writes off the request path, and the hourly rollup/prune pass — plus a one-off check of the application config, logged once as the module starts.
Turns tracking on, generating the visitor-hash salt if this is a first enable — so the very first request already hashes against a real secret.
Whether tracking is on.
Defensive against the DB being unavailable (boot ordering, a test sandbox
owner that just stopped): every failure path answers false, so the plug
treats "we don't know" as "don't track".
Summary shown on the admin Modules page.
The optional client script (clicks the server can't see, scroll depth, exits
from non-LiveView pages), folded into the host's phoenix_kit_modules.js.
It sends nothing the server accepts until Client script is switched on
in settings.
The events + daily stats tables (run by mix phoenix_kit.update).
The Website activity notification type — new visitors, sign-ups and
tracked events. See PhoenixKitWebAnalytics.Alerts.
The admin pages plus the public collection endpoints.
Records a custom event from server-side code.
Use this for things that happen in your context modules rather than in the browser — an order placed, a subscription upgraded — where the event is a fact the server already knows and shouldn't depend on the client to report.
PhoenixKitWebAnalytics.track_event("order.placed", %{
path: "/checkout",
metadata: %{"total_cents" => 4900},
user_uuid: user.uuid
})attrs accepts any key from PhoenixKitWebAnalytics.Collector's hit shape.
Returns :ok immediately; the write happens in a supervised task.
Without :ip and :user_agent the event still records, but under a visitor
hash that won't match that person's page views — pass conn values through
when the event happens inside a request and you want it attributed to the
same visitor.
@spec track_pageview(map()) :: :ok
Records a page view from server-side code.
Only needed for pages the plug can't see — a response rendered by something other than the browser pipeline. Ordinary pages are already counted.