GoodAnalytics.Core.Links.Redirect (GoodAnalytics v0.1.1)

Copy Markdown View Source

Handles short link redirects.

On each redirect:

  1. Look up link by domain + key
  2. Generate unique click_id
  3. Capture server-side data
  4. Check dedup cache
  5. Record click event if not duplicate
  6. Build redirect URL with link UTMs, passthrough params, and ga_id
  7. Fire :link_click hook (sync, crash-isolated)
  8. 302 redirect

Geo routing callback

When link.geo_targeting is non-empty, the redirect path consults the configured :geo_routing_enabled_fn callback to decide whether to apply country-based routing. The callback shape is {Module, :function} and must accept a workspace_id :: Ecto.UUID.t().

Contract:

  • MUST return a boolean.
  • MUST NOT raise. A raise propagates and the redirect 500s — this is host-app misconfiguration that should be fixed, not silently swallowed. Cache lookups (e.g. via Nebulex) keep this hot.

Summary

Functions

Builds the final redirect URL by merging params in priority order

Handles a redirect for the given domain and key.

Functions

build_redirect_url(base_url, link, conn, click_id, geo_map \\ nil)

Builds the final redirect URL by merging params in priority order:

  1. Destination URL's existing query params (base)
  2. Link-level UTM params (stored on the link record)
  3. Short link request query params (passthrough from the clicked URL)
  4. ga_id (always appended, highest priority)

Higher priority params overwrite lower. This means:

  • Link UTMs override destination UTMs (marketer intent > default)
  • Request passthrough overrides link UTMs (per-click override > per-link default)
  • ga_id is always present

When geo_map is provided AND the workspace has geo routing enabled via the host-app :geo_routing_enabled_fn callback AND link.geo_targeting maps the resolved country code to a non-empty URL, that URL replaces the device- targeted/default destination before params are merged.

handle_redirect(conn, domain, key)

Handles a redirect for the given domain and key.