Skip to content

Visit Tracking

Short URL tracks every redirect hit via a lightweight HTTP middleware that runs before Drupal's page cache. This ensures visits are recorded even on cached responses without a full Drupal bootstrap.

How it works

  1. A visitor requests a short URL (e.g. /promo).
  2. The Redirect module matches the slug and returns a redirect response (301/302/307).
  3. The hook_redirect_response_alter hook stamps the response with internal X-Shorturl-Nid and X-Shorturl-Langcode headers. These headers are cached alongside the response.
  4. On the next request, the ShortUrlVisitMiddleware (priority 210, above PageCache at 200) detects the redirect response, reads the headers, and inserts a row into the shorturl_visits table.
  5. The internal headers are stripped before the response reaches the client.

Recorded data

Each visit record contains:

Column Description
nid The short URL node ID
langcode The language of the translation that was hit
timestamp Unix timestamp of the visit
referrer The HTTP Referer header (up to 2048 chars)
country_code Two-letter ISO country code (requires Smart IP)
ip_hash SHA-256 hash of the visitor's IP address

Privacy

IP addresses are never stored in plain text. Only a one-way SHA-256 hash is recorded, which cannot be reversed to recover the original IP.

Statistics dashboard

Each short URL node has a Statistics tab that displays:

Traffic tab

  • Line chart of visits over time (7 days, 30 days, or all time)
  • Visit history table (24h, 7d, 30d, all time with daily averages)
  • Best day (date and count of highest traffic)

Referrers tab

  • Pie chart of referrer distribution
  • Pie chart of direct vs. referred visits
  • Top referring sites list

Traffic origin tab

  • Pie chart of top countries
  • Country list with flag emojis, names, and visit counts

Info

The Traffic origin tab requires country data. Without the Smart IP module, it displays a message suggesting installation.

Country detection (Smart IP)

Country detection is optional and requires the Smart IP module with a configured data source (e.g. MaxMind GeoLite2-Country binary database).

When Smart IP is installed and configured:

  • The middleware calls SmartIp::query() with the visitor's IP to resolve the country code.
  • The two-letter ISO code is stored in the country_code column.

When Smart IP is not installed or the lookup fails:

  • The country_code column is left empty.
  • Visit tracking continues normally — only the geographic data is missing.

Warning

Smart IP's MaxMind GeoIP2 binary database submodule has a known PHP 8.1+ compatibility issue with typed properties. Short URL catches \Throwable (not just \Exception) to handle this gracefully.

Enabling and disabling

Visit tracking can be toggled in the module settings at /admin/config/shorturl/settings. When disabled, the middleware is not registered at all — there is zero performance overhead.

The no-store setting controls whether a Cache-Control: no-store header is added to redirect responses. This prevents browsers from caching the redirect so that every click is recorded.

Data retention

The Visit retention period setting controls how long visit records are kept. When set to a positive number of days (e.g. 90), a cron job automatically deletes records older than the configured period. Set to 0 (default) to retain all records indefinitely.

This helps keep the shorturl_visits table manageable on high-traffic sites. The purge runs on every cron execution and deletes records whose timestamp is older than the retention window.