PostHog / PostHog/posthog-elixir

Autocapture for Phoenix LiveView

Open
#66 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Elixir
Stars
65
Forks
30
Avg merge
1d 16h
Merged PRs (30d)
16

Description

Congrats on the 2.0 release! The SDK looks great. We're evaluating PostHog to replace our current analytics setup, but have a pain point we'd like to solve first.

The Problem

The PostHog JS SDK looks like it has great autocapture for client-side events. Phoenix LiveView apps handle most interactions server-side via handle_event/3 callbacks, which are invisible to client-side autocapture. This means we need manual PostHog.capture() calls for every event, making it easy to miss tracking new features—which is our biggest pain point with our current setup.

The Opportunity

LiveView provides lifecycle hooks that can intercept all handle_event/3 calls. Event names are already semantic ("create_account", "delete_deal"), and user context is always available in the socket. This is actually better than DOM events for autocapture.

Proposed Approach

Add optional autocapture via on_mount hook:

defmodule MyAppWeb.SomeLive do
  use MyAppWeb, :live_view
  on_mount {PostHog.LiveView, :autocapture}

  # All handle_event calls now auto-captured
  def handle_event("create_account", params, socket) do
    {:ok, account} = Accounts.create_account(params)
    {:noreply, socket}
  end
end

What gets captured automatically:

  • Event name
  • User ID from socket assigns
  • View name and live_action
  • Sanitized params

Smart filtering to reduce noise:

# Ignore by default: validate, change, keyup, focus, paginate
# Always capture: create, delete, update, save, submit

Optional property enrichment for complex cases:

def handle_event("create_account", params, socket) do
  {:ok, account} = Accounts.create_account(params)

  # Enrich with computed properties
  socket = PostHog.enrich_properties(socket, %{
    method: if(account.fast_add, do: "fast_add", else: "full"),
    stage: format_stage(account.stage)
  })

  {:noreply, socket}
end

Implementation

The core is straightforward—attach to LiveView's :handle_event hook:

def on_mount(:autocapture, _params, _session, socket) do
  socket = attach_hook(socket, :posthog, :handle_event, fn event, params, socket ->
    if should_capture?(event, socket) do
      properties = build_properties(params, socket)
      user_id = get_in(socket.assigns, [:current_user, :id])
      PostHog.capture(event, %{distinct_id: user_id, properties: properties})
    end
    {:cont, socket}
  end)

  {:cont, socket}
end

Impact

For our app (770 lines of analytics code, 49 tracked events):

  • Simple events: zero code needed (currently 150 lines)
  • Medium complexity: one-line enrichment (currently 320 lines)
  • Complex events: custom enrichment helper (currently 300 lines)

Estimated 50-70% reduction in analytics boilerplate.

Questions

  1. Is this something that would fit in the SDK?
  2. Any concerns about the approach?
  3. Would you prefer this as a separate package?

We're considering building this either way, but wanted to check if you had thoughts on design or would be interested in collaborating.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the proposed Phoenix LiveView on_mount entry point and :handle_event hook; the issue names no repository files or tests. Resolve the scope for filtering, socket user context, parameter sanitization, enrichment, and whether this belongs in the SDK or a separate package. Done means the design and implementation boundaries are agreed, with tests covering captured and ignored events.

Written by the indexing model from the issue text.

Assessment

Tech stack
elixir
Domain
analytics, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.