Problem
Some sites use external analytics exclusively (Matomo, Piano, GA) and do not need the built-in shorturl_visits database tracking. Currently, the VisitDatabaseSubscriber always writes to the DB, and the stats tab/API always display. There is no way to disable the DB storage without uninstalling or hacking code.
Proposed solution
Add two hierarchical settings to shorturl.settings:
Settings form UI
[x] Enable visit tracking
Tracks visits to short URL redirects. Dispatches a visit
event that analytics subscribers can consume.
[x] Enable built-in statistics
Stores visit data in the database for the statistics
dashboard and API endpoints.
- Enable visit tracking (checkbox, default: on)
- Unchecked: middleware and all subscribers removed from container. Nothing tracked. Zero overhead.
- Checked: middleware active,
ShortUrlVisitEventdispatched on every redirect. External analytics subscribers receive events.
- Enable built-in statistics (checkbox, default: on, visible only when tracking is enabled)
- Checked:
VisitDatabaseSubscriberactive, stats tab and API visible, purge cron active. - Unchecked: DB subscriber removed, stats tab hidden, API returns 403, purge skipped. Event still dispatches for external analytics.
- Checked:
Config keys
# shorturl.settings enable_tracking: true enable_builtin_stats: true
Implementation
Use the ServiceProvider::alter() pattern to remove services at compile time based on config. This means zero runtime overhead — disabled services are never instantiated.
// In ShorturlServiceProvider::alter():
$config = BootstrapConfigStorageFactory::get()
->read('shorturl.settings');
if (empty($config['enable_tracking'])) {
// No tracking at all.
$container->removeDefinition(
'Drupal\shorturl\EventSubscriber\VisitDatabaseSubscriber'
);
$container->removeDefinition(
'Drupal\shorturl\StackMiddleware\ShortUrlVisitMiddleware'
);
}
elseif (empty($config['enable_builtin_stats'])) {
// Event dispatches for external analytics,
// but no DB writes.
$container->removeDefinition(
'Drupal\shorturl\EventSubscriber\VisitDatabaseSubscriber'
);
}
Affected areas
| Area | Both enabled | Tracking on, stats off | Both disabled |
|---|---|---|---|
| VisitDatabaseSubscriber | Active | Removed | Removed |
| ShortUrlVisitMiddleware | Active | Active (dispatches event) | Removed |
| Stats tab | Visible | Hidden | Hidden |
| Stats API endpoints | Active | 403 | 403 |
| Purge cron | Active | Skipped | Skipped |
| VisitTracker::supportsStats() | TRUE | FALSE | FALSE |
Depends on #3584485 (visit event system).
Issue fork shorturl-3584516
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mably commentedComment #4
mably commentedComment #6
mably commented