Skip to content

Admin API: Analytics

This page covers trends, top links, referrers, geo, and device analytics endpoints.

Analytics API

Analytics API provides detailed click statistics, including click trends, top links, referrer stats, and geographic distribution.

You need to enable analytics.enable_detailed_logging in runtime config (restart required; restart the server after changing it) to record detailed click logs.

  • Default range: last 30 days. To set a custom range, provide both start_date and end_date (if only one is provided, it falls back to the default range; if parsing fails, it falls back to the default start/end values).
  • Date formats: RFC3339 (e.g. 2024-01-01T00:00:00Z) or YYYY-MM-DD (e.g. 2024-01-01; note: YYYY-MM-DD is interpreted as 00:00:00Z of that day).
  • In the current implementation, GeoIP lookup is not yet wired into the click-write path (click_logs.country/city are null by default), so /analytics/geo and per-link geo_distribution may be empty unless historical data already contains geo fields.
  • Startup [analytics] config (analytics.maxminddb_path / analytics.geoip_api_url) is retained for GeoIP provider selection; the external API provider has built-in caching (LRU 10,000, TTL 15 minutes, negative caching, singleflight, 2-second timeout).
  • Device/browser distribution (/analytics/devices) is based on user_agent_hash (User-Agent strings are deduplicated into user_agents and linked by hash).
  • click_logs.source derivation is: utm_source first; otherwise ref:{domain} (from Referer); otherwise direct.

Common Query Parameters (Most Endpoints)

ParamTypeDescription
start_dateRFC3339 / YYYY-MM-DDStart date (optional; only effective when provided together with end_date; default = last 30 days)
end_dateRFC3339 / YYYY-MM-DDEnd date (optional; only effective when provided together with start_date; default = last 30 days)
limitIntegerResult size (optional; defaults and max values vary by endpoint)

Endpoint-specific defaults: top/referrers=10, geo=20, devices=10, links/{code}/analytics/devices=10. export currently ignores limit.

bash
curl -sS -b cookies.txt \
  "http://localhost:8080/admin/v1/analytics/trends?start_date=2024-01-01T00:00:00Z&end_date=2024-12-31T23:59:59Z&group_by=day"

Query params:

  • Supports common params: start_date, end_date
  • Endpoint-specific param: group_by (optional; default day): hour / day / week / month

Response:

json
{
  "code": 0,
  "message": "OK",
  "data": {
    "labels": ["2024-01-01", "2024-01-02", "2024-01-03"],
    "values": [100, 150, 120]
  }
}
bash
curl -sS -b cookies.txt \
  "http://localhost:8080/admin/v1/analytics/top?limit=10"

Query params:

  • Supports common params: start_date, end_date, limit
  • limit default 10, max 100

Response:

json
{
  "code": 0,
  "message": "OK",
  "data": [
    {"code": "github", "clicks": 500},
    {"code": "google", "clicks": 300}
  ]
}

GET /analytics/referrers - Get referrer stats

bash
curl -sS -b cookies.txt \
  "http://localhost:8080/admin/v1/analytics/referrers?limit=10"

Query params:

  • Supports common params: start_date, end_date, limit
  • limit default 10, max 100

Response:

json
{
  "code": 0,
  "message": "OK",
  "data": [
    {"referrer": "https://google.com", "count": 200, "percentage": 40.0},
    {"referrer": "(direct)", "count": 150, "percentage": 30.0}
  ]
}

GET /analytics/geo - Get geographic distribution

bash
curl -sS -b cookies.txt \
  "http://localhost:8080/admin/v1/analytics/geo?limit=20"

Query params:

  • Supports common params: start_date, end_date, limit
  • limit default 20, max 100

Response:

json
{
  "code": 0,
  "message": "OK",
  "data": []
}

GET /analytics/devices - Get device analytics

bash
curl -sS -b cookies.txt \
  "http://localhost:8080/admin/v1/analytics/devices?limit=10"

Query params:

  • Supports common params: start_date, end_date, limit
  • limit default 10, max 20

Response:

json
{
  "code": 0,
  "message": "OK",
  "data": {
    "browsers": [
      {"name": "Chrome", "count": 120, "percentage": 60.0}
    ],
    "operating_systems": [
      {"name": "Mac OS X", "count": 80, "percentage": 40.0}
    ],
    "devices": [
      {"name": "pc", "count": 150, "percentage": 75.0}
    ],
    "bot_percentage": 12.3,
    "total_with_ua": 200
  }
}
bash
curl -sS -b cookies.txt \
  "http://localhost:8080/admin/v1/links/github/analytics"

Query params:

  • Supports common params: start_date, end_date

Response:

json
{
  "code": 0,
  "message": "OK",
  "data": {
    "code": "github",
    "total_clicks": 500,
    "trend": {
      "labels": ["2024-01-01", "2024-01-02"],
      "values": [100, 150]
    },
    "top_referrers": [
      {"referrer": "https://google.com", "count": 100, "percentage": 20.0}
    ],
    "geo_distribution": []
  }
}
bash
curl -sS -b cookies.txt \
  "http://localhost:8080/admin/v1/links/github/analytics/devices?limit=10"

Query params:

  • Supports common params: start_date, end_date, limit
  • limit default 10, max 20

Response:

json
{
  "code": 0,
  "message": "OK",
  "data": {
    "browsers": [
      {"name": "Chrome", "count": 80, "percentage": 53.3}
    ],
    "operating_systems": [
      {"name": "Windows", "count": 60, "percentage": 40.0}
    ],
    "devices": [
      {"name": "pc", "count": 120, "percentage": 80.0}
    ],
    "bot_percentage": 8.5,
    "total_with_ua": 150
  }
}

GET /analytics/export - Export analytics report (CSV)

bash
curl -sS -b cookies.txt \
  -o analytics_report.csv \
  "http://localhost:8080/admin/v1/analytics/export?start_date=2024-01-01T00:00:00Z&end_date=2024-12-31T23:59:59Z"

Query params:

  • Supports common params: start_date, end_date, limit
  • limit is currently ignored; export includes all records within the date range (narrow date range to control output size)

The exported CSV contains these columns: short_code,clicked_at,referrer,source,ip_address,country,city

The Content-Disposition filename format is: analytics_YYYYMMDD_YYYYMMDD.csv (derived from the parsed date range).

Note:

  • The source column follows the redirect source derivation rule (utm_sourceref:{domain}direct).
  • Export does not include raw user_agent; device analytics is built via user_agent_hash + user_agents.

Analytics configuration

These runtime config options control Analytics behavior:

Config keyTypeDefaultDescription
analytics.enable_detailed_loggingboolfalseEnable detailed logging (writes to click_logs table; restart required)
analytics.enable_auto_rollupbooltrueEnable automatic data retention task (restart required; runs every 4 hours by default)
analytics.log_retention_daysint30Raw click log retention in days (cleaned by background task; requires analytics.enable_auto_rollup)
analytics.hourly_retention_daysint7Hourly rollup retention in days (cleans click_stats_hourly / click_stats_global_hourly; requires analytics.enable_auto_rollup)
analytics.daily_retention_daysint365Daily rollup retention in days (cleans click_stats_daily / click_stats_global_daily; requires analytics.enable_auto_rollup)
analytics.enable_ip_loggingbooltrueWhether to record IP addresses
analytics.enable_geo_lookupboolfalseReserved GeoIP switch (currently not consumed in click-write path; country/city remain null by default)
analytics.sample_ratefloat1.0Detailed logging sample rate (0.0-1.0; 1.0 = log all clicks)
analytics.max_log_rowsint0Maximum rows in click_logs (0 = unlimited)
analytics.max_rows_actionenumcleanupAction when max rows exceeded: cleanup (delete oldest) / stop (stop detailed logging)
utm.enable_passthroughboolfalseForward UTM params during redirect (utm_source/utm_medium/utm_campaign/utm_term/utm_content)

Note: in the current implementation, retention parameters are read when the background task starts; after changing retention days, you may need to restart the server for the cleanup task to pick up new values.

Released under the MIT License