Presence tracking for dashboard tabs.
Tracks which users are viewing which dashboard tabs, enabling features like:
- "2 users viewing" indicators on tabs
- Real-time user count updates
- Activity heatmaps
- User awareness for collaborative features
Integration with PhoenixKit Presence
This module integrates with PhoenixKit's existing presence system to provide dashboard-specific tracking while sharing the underlying infrastructure.
Usage in LiveViews
def mount(_params, _session, socket) do
if connected?(socket) do
# Track user on this tab
PhoenixKit.Dashboard.Presence.track_tab(socket, :orders)
# Subscribe to presence updates
PhoenixKit.Dashboard.Presence.subscribe()
end
{:ok, assign(socket, tab_viewers: Presence.get_tab_viewers(:orders))}
end
def handle_info({:presence_diff, _diff}, socket) do
{:noreply, assign(socket, tab_viewers: Presence.get_tab_viewers(:orders))}
endConfiguration
config :phoenix_kit, :dashboard_presence,
enabled: true,
show_user_count: true,
show_user_names: false, # Privacy setting
track_anonymous: false
Summary
Functions
Broadcasts a tab viewer count update.
Clears the cached presence module detection.
Checks if presence tracking is enabled.
Gets viewer counts for all tabs at once.
Gets all users currently viewing a specific tab.
Gets the main presence topic for all dashboard presence updates.
Checks if user counts should be shown.
Checks if user names/emails should be shown.
Subscribes to presence updates for all dashboard tabs.
Subscribes to presence updates for a specific tab.
Gets the presence topic for a specific tab.
Checks if anonymous users should be tracked.
Tracks a user's presence on a specific dashboard tab.
Untracks a user from a dashboard tab.
Functions
@spec broadcast_tab_count(atom()) :: :ok
Broadcasts a tab viewer count update.
This is called automatically when presence changes, but can also be called manually to force a refresh.
@spec clear_presence_module_cache() :: :ok
Clears the cached presence module detection.
Call this after hot code reloading if the presence module configuration has changed. The next call to any presence function will re-detect.
@spec enabled?() :: boolean()
Checks if presence tracking is enabled.
@spec get_all_tab_counts() :: map()
Gets viewer counts for all tabs at once.
Returns a map of tab_id => count.
Examples
Presence.get_all_tab_counts()
# => %{orders: 3, printers: 1, settings: 0}
Gets all users currently viewing a specific tab.
Options
:format- Output format: :full (default), :count, :emails, :ids
Examples
Presence.get_tab_viewers(:orders)
# => [%{user_uuid: "019...", user_email: "user@example.com", online_at: ~U[...]}]
Presence.get_tab_viewers(:orders, format: :count)
# => 3
Presence.get_tab_viewers(:orders, format: :emails)
# => ["user@example.com", "admin@example.com"]
@spec presence_topic() :: String.t()
Gets the main presence topic for all dashboard presence updates.
@spec show_user_count?() :: boolean()
Checks if user counts should be shown.
@spec show_user_names?() :: boolean()
Checks if user names/emails should be shown.
@spec subscribe() :: :ok | {:error, term()}
Subscribes to presence updates for all dashboard tabs.
The subscriber will receive messages in the format:
{:presence_diff, %{joins: %{}, leaves: %{}}}- When users join/leave{:tab_viewers_updated, tab_id, count}- Simplified count update
Subscribes to presence updates for a specific tab.
Gets the presence topic for a specific tab.
@spec track_anonymous?() :: boolean()
Checks if anonymous users should be tracked.
@spec track_tab(Phoenix.LiveView.Socket.t(), atom(), keyword()) :: {:ok, String.t()} | {:error, term()}
Tracks a user's presence on a specific dashboard tab.
Options
:meta- Additional metadata to track with the presence (default: %{}):tab_path- The full path of the tab (used for analytics)
Examples
Presence.track_tab(socket, :orders)
Presence.track_tab(socket, :printers, meta: %{printer_id: 123})
@spec untrack_tab(Phoenix.LiveView.Socket.t(), atom()) :: :ok
Untracks a user from a dashboard tab.