GoodAnalytics.Core.Events (GoodAnalytics v0.1.1)

Copy Markdown View Source

Context for event queries.

Summary

Functions

Counts events matching the same filters as list_events/2 (minus limit/offset).

Returns distinct event_type and source_platform values for a workspace.

Gets a single event by id only — not workspace-scoped.

Finds an event by idempotency key within a workspace.

Gets a single event by id scoped to a workspace.

Gets the most recent event of a given type for a visitor.

Lists events for a workspace with filtering, pagination, and date-range bounding.

Returns source platform/medium breakdown for a workspace.

Functions

count_events(workspace_id, opts \\ [])

@spec count_events(Ecto.UUID.t(), keyword()) :: non_neg_integer()

Counts events matching the same filters as list_events/2 (minus limit/offset).

filter_options(workspace_id)

@spec filter_options(Ecto.UUID.t()) :: %{
  event_types: [String.t()],
  source_platforms: [String.t()]
}

Returns distinct event_type and source_platform values for a workspace.

Scans events from the last 90 days to keep the query partition-safe. Used to populate multi-select filter options.

get_by_id(id)

Gets a single event by id only — not workspace-scoped.

Repo.get(Event, id) is unsafe because the events table has a composite primary key (id, inserted_at) (required by Postgres for partitioned tables). This helper performs the equivalent fetch using a where clause and returns nil if no event is found.

WARNING: This function does NOT scope by workspace. Callers MUST ensure tenant isolation before exposing results to users. Prefer get_event/2 for workspace-scoped lookups.

get_by_idempotency_key(workspace_id, idempotency_key)

Finds an event by idempotency key within a workspace.

Returns nil if no event matches the key.

get_event(workspace_id, event_id)

@spec get_event(Ecto.UUID.t(), Ecto.UUID.t()) ::
  GoodAnalytics.Core.Events.Event.t() | nil

Gets a single event by id scoped to a workspace.

Returns nil if the event doesn't exist or belongs to a different workspace. Uses WHERE clause instead of Repo.get due to composite primary key.

NOTE: This query has no inserted_at bound, so Postgres will scan all partitions. Acceptable for single-row lookups hitting idx_ga_events_workspace, but pass inserted_at from the caller if performance becomes an issue.

last_event(visitor_id, event_type)

Gets the most recent event of a given type for a visitor.

list_events(workspace_id, opts \\ [])

@spec list_events(Ecto.UUID.t(), keyword()) :: [GoodAnalytics.Core.Events.Event.t()]

Lists events for a workspace with filtering, pagination, and date-range bounding.

Options

  • :event_type{:in, list} or {:not_in, list} for multi-select filtering
  • :source_platform{:in, list} or {:not_in, list} for multi-select filtering
  • :source_campaign{:in, list} or {:not_in, list} for multi-select filtering
  • :url{:in, list} or {:not_in, list} for multi-select filtering
  • :click_id{:in, list} or {:not_in, list} for multi-select filtering
  • :visitor_id — exact match on visitor_id
  • :search — ILIKE search across event_name and url
  • :start_at — lower bound for inserted_at (defaults to 7 days ago)
  • :end_at — upper bound for inserted_at (defaults to now)
  • :limit — page size (default 50)
  • :offset — page offset (default 0)

All queries include date-range bounds to enable partition pruning.

source_breakdown(workspace_id, opts \\ [])

Returns source platform/medium breakdown for a workspace.

Accepts :start_at and :end_at to bound the date range for partition pruning. Defaults to the last 7 days when no bounds are provided.