Who came, from where, on what, and to which pages.
Every function takes site_id and a Pixelex.Query.Range and returns plain
maps. Every grouped query carries a LIMIT; every query is bounded by the
range, so the planner prunes to the partitions it overlaps.
visitors is a daily count
Within a single day count(DISTINCT visitor_id) is exact. Over a longer
window it is a sum of dailies and therefore an over-count of people,
because the visitor hash rotates at midnight UTC. summary/2 returns it as
:visitors_daily_sum rather than :visitors, because a field called
"unique visitors" that is not unique is worse than no field.
Summary
Functions
Browsers.
Paid campaigns by name, with the click ids that carried them.
Countries, by ISO-3166-1 alpha-2 code.
Device types: desktop, smartphone, tablet, …
Custom events by name, page views excluded.
Traffic by channel: organic_search, paid_social, referral, none, …
Operating systems.
Where visitors came from, by resolved source.
Headline numbers for the window.
Page views and sessions per time bucket, for a chart.
Most-viewed paths.
Functions
@spec browsers(String.t(), Pixelex.Query.Range.t(), keyword()) :: [map()]
Browsers.
@spec campaigns(String.t(), Pixelex.Query.Range.t(), keyword()) :: [map()]
Paid campaigns by name, with the click ids that carried them.
@spec countries(String.t(), Pixelex.Query.Range.t(), keyword()) :: [map()]
Countries, by ISO-3166-1 alpha-2 code.
@spec devices(String.t(), Pixelex.Query.Range.t(), keyword()) :: [map()]
Device types: desktop, smartphone, tablet, …
@spec events(String.t(), Pixelex.Query.Range.t(), keyword()) :: [map()]
Custom events by name, page views excluded.
@spec mediums(String.t(), Pixelex.Query.Range.t(), keyword()) :: [map()]
Traffic by channel: organic_search, paid_social, referral, none, …
@spec operating_systems(String.t(), Pixelex.Query.Range.t(), keyword()) :: [map()]
Operating systems.
@spec sources(String.t(), Pixelex.Query.Range.t(), keyword()) :: [map()]
Where visitors came from, by resolved source.
Reads attribution->'last'->>'source', so a Google ad shows as google and
organic Google as Google — the click-id path and the referrer path resolve
separately by design. Group by medium/1 to collapse them.
@spec summary(String.t(), Pixelex.Query.Range.t()) :: map()
Headline numbers for the window.
%{
pageviews: 4_182,
events: 5_006,
sessions: 1_204,
visitors_daily_sum: 1_103,
bounce_rate: 0.42,
views_per_session: 3.47
}bounce_rate is the share of sessions with exactly one page view.
@spec timeseries(String.t(), Pixelex.Query.Range.t(), keyword()) :: [map()]
Page views and sessions per time bucket, for a chart.
The bucket is chosen from the window's length unless given, so a year never returns 8,760 hourly points to render across eight hundred pixels.
@spec top_pages(String.t(), Pixelex.Query.Range.t(), keyword()) :: [map()]
Most-viewed paths.