Pixelex.Query.Retention (Pixelex v0.1.0)

Copy Markdown View Source

Of the people who first appeared in week 0, how many came back in week 1, week 2, week 3.

Pixelex.Query.Retention.cohorts("shop", range, bucket: "week")

%{
  bucket: "week",
  cohorts: [
    %{cohort: ~U[2026-08-03 00:00:00Z], size: 412,
      periods: [%{period: 0, users: 412, rate: 1.0},
                %{period: 1, users: 173, rate: 0.42},
                %{period: 2, users: 98,  rate: 0.238}]},
    
  ]
}

This works on user_id, and it has to

visitor_id is a keyed hash under a salt that rotates every UTC day. Tomorrow the same person hashes to a different value — that is what makes pixelex cookieless, and it makes anonymous retention arithmetically impossible, not merely unimplemented. Retaining a stable identifier across days means putting one on the visitor's device, and putting one there is exactly what ePrivacy Article 5(3) governs.

So this counts signed-in users, from Pixelex.identify/3 onward. If nothing calls identify/3, every cohort is empty and that is the honest answer rather than a plausible-looking wrong one.

Cohorts are scoped to the window

A user's cohort is the bucket of their first event inside the range, not their first event ever. Someone who signed up last year and returned today appears in today's cohort. Widening the range fixes it and costs more; there is no third option that is both bounded and correct, and an unbounded scan of the events table is not an option at all.

:first_seen_from moves just the first-seen lookback earlier while keeping the activity window narrow, which is the useful middle:

cohorts("shop", last_30_days, first_seen_from: ninety_days_ago)

Summary

Functions

Retention grid for signed-in users.

Functions

cohorts(site_id, range, opts \\ [])

@spec cohorts(String.t(), Pixelex.Query.Range.t(), keyword()) :: map()

Retention grid for signed-in users.

Options

  • :bucket"day", "week" (default) or "month"
  • :first_seen_from — a DateTime to look further back for first-seen
  • :event — only count activity on this event name
  • :limit — maximum cohorts returned (default 26)