GoodAnalytics.Hooks (GoodAnalytics v0.1.1)

Copy Markdown View Source

Event hooks for downstream consumers.

Dispatch tiers based on latency requirements:

  • Sync tier (notify_sync/3, the redirect path's :link_click): each callback runs via Task.Supervisor.async_nolink with a 50ms timeout. Crash or timeout never blocks the caller. Use it for fast hooks whose result the caller needs in-band (e.g. cookie directives).
  • Async opt-in tier (notify_detached/3): callbacks registered with async: true are skipped by the sync tier and dispatched here fire-and-forget, with no time budget. Use it for slow, side-effecting hooks (e.g. a DB-bound subscriber identify) that must not run under the 50ms redirect budget.
  • Broadcast tier (notify_async/3, every non-click event): broadcast via Phoenix.PubSub after the enclosing transaction commits.

The link redirect pairs the first two: notify_sync/3 for the bounded, cookie-setting hooks and notify_detached/3 for the async-tier side effects.

Registration

GoodAnalytics.Hooks.register(:sale, fn event, visitor ->
  # handle sale event
  :ok
end)

GoodAnalytics.Hooks.register(:link_click, {MyApp.ClickHandler, :handle})

# Slow side-effect hook — runs off the 50ms redirect budget.
GoodAnalytics.Hooks.register(:link_click, {MyApp.Identify, :call}, async: true)

Summary

Functions

Returns a specification to start this module under a supervisor.

Async dispatch — broadcasts via Phoenix.PubSub after transaction commit.

Detached dispatch — runs only the async-tier callbacks (registered with async: true) for event_type, each in a supervised task with no time budget and no reply. Sync-tier callbacks are ignored, and nothing is broadcast over PubSub.

Sync dispatch — used only for :link_click hooks on the redirect path.

Registers a callback for the given event type.

Types

hook_event()

@type hook_event() ::
  :link_click
  | :lead
  | :sale
  | :identify
  | :pageview
  | :visitor_merged
  | :custom

hook_fn()

@type hook_fn() :: (map(), map() -> :ok | {:ok, map()})

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

notify_async(event_type, event, visitor)

Async dispatch — broadcasts via Phoenix.PubSub after transaction commit.

Used for all non-click hooks.

notify_detached(event_type, event, visitor)

Detached dispatch — runs only the async-tier callbacks (registered with async: true) for event_type, each in a supervised task with no time budget and no reply. Sync-tier callbacks are ignored, and nothing is broadcast over PubSub.

Pair this with notify_sync/3 on latency-sensitive paths (the link redirect): notify_sync/3 awaits the bounded, cookie-setting hooks, while this lets slow side-effect hooks run to completion off the request's critical path.

notify_sync(event_type, event, visitor)

Sync dispatch — used only for :link_click hooks on the redirect path.

Each callback runs in a supervised task with a 50ms timeout. Crashed or timed-out hooks return :error and are excluded from results.

register(event_type, callback, opts \\ [])

Registers a callback for the given event type.

Options:

  • :async (boolean, default false) — when true, the callback joins the async tier: it is skipped by notify_sync/3 and instead dispatched fire-and-forget by notify_detached/3, with no time budget. Use it for slow, side-effecting hooks (e.g. a DB-bound subscriber identify) that must not run under the 50ms sync redirect budget. false keeps the legacy sync tier behaviour (bounded, reply-carrying, cookie-capable).

start_link(opts \\ [])