jackfumanchu / cookieless-analytics-bundle
Lightweight, cookieless, GDPR-compliant analytics bundle for Symfony 6.4+
Package info
github.com/jackfumanchu/cookieless-analytics-bundle
Type:symfony-bundle
pkg:composer/jackfumanchu/cookieless-analytics-bundle
Requires
- php: >=8.2
- doctrine/dbal: ^4.0
- doctrine/doctrine-bundle: ^2.13 || ^3.0
- doctrine/orm: ^3.0
- symfony/doctrine-bridge: ^6.4 || ^7.4 || ^8.0
- symfony/framework-bundle: ^6.4 || ^7.4 || ^8.0
- symfony/security-core: ^6.4 || ^7.4 || ^8.0
- twig/twig: ^3.0 || ^4.0
Requires (Dev)
- dbrekelmans/bdi: ^1.4
- friendsofphp/php-cs-fixer: ^3.94
- infection/infection: ^0.32.6
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.1
- phpstan/phpstan-doctrine: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^11.1 || ^12.0 || ^13.1
- symfony/browser-kit: ^6.4 || ^7.4 || ^8.0
- symfony/css-selector: ^6.4 || ^7.4 || ^8.0
- symfony/panther: ^2.4
- symfony/twig-bundle: ^6.4 || ^7.4 || ^8.0
- symfony/var-exporter: ^6.4 || ^7.4 || ^8.0
- symfony/yaml: ^6.4 || ^7.4 || ^8.0
Suggests
- symfony/ux-turbo: For lazy-loading dashboard widgets via Turbo Frames
README
A lightweight, self-hosted, cookieless analytics bundle for Symfony 7.4+.
No cookies. No consent banner. No external service. Full GDPR compliance out of the box.
Tracks page views, daily visitors, and custom events (e.g. booking clicks) using a daily-rotated anonymous fingerprint — no personal data is ever stored.
Features
- ✅ Cookieless by design — no consent banner required under GDPR/ePrivacy
- ✅ Self-hosted — all data stays on your own server
- ✅ Multi-database — supports PostgreSQL, MySQL, and SQLite
- ✅ Daily visitors per page — via anonymous daily fingerprint (IP + User-Agent, hashed and rotated)
- ✅ Referrer tracking — see where your visitors come from, with domain extraction
- ✅ Custom event tracking — track any click or interaction with a
data-attribute - ✅ Standalone dashboard — built-in analytics UI, no EasyAdmin required
- ✅ Multi-site ready — one bundle installation per Symfony app
- ✅ Lightweight script — under 1 KB injected into your pages
Requirements
- PHP 8.2+
- Symfony 6.4, 7.4 or 8.x
- Doctrine ORM 3.x
- PostgreSQL 12+, MySQL 5.7+ / MariaDB 10.3+, or SQLite 3
Installation
composer require jackfumanchu/cookieless-analytics-bundle php bin/console cookieless:install
The cookieless:install command creates the required database tables. It is safe to run multiple times — on subsequent runs it will apply any schema updates or report that nothing changed.
Quick Start
1. Enable the bundle
Register the bundle in your application:
// config/bundles.php return [ // ... Jackfumanchu\CookielessAnalyticsBundle\CookielessAnalyticsBundle::class => ['all' => true], ];
2. Add the tracking script to your base template
{# templates/base.html.twig — before </head> #}
{{ cookieless_analytics_script() }}
This injects a minimal inline script (under 1 KB) that sends a beacon on each page load and listens for custom event attributes.
3. Track a custom event (e.g. a booking button)
Add data-ca-event and optionally data-ca-value to any HTML element:
<a href="{{ path('app_booking', {slug: event.slug}) }}" data-ca-event="booking-click" data-ca-value="{{ event.title }}"> Book now → </a>
No JavaScript required on your side — the bundle's script handles everything.
Configuration
Create config/packages/cookieless_analytics.yaml:
cookieless_analytics: # Exclude paths from tracking (regex patterns) exclude_paths: - '^/admin' - '^/_' - '^/api' # Enable or disable the built-in dashboard dashboard_enabled: true # Route prefix for the dashboard (default: /analytics) dashboard_prefix: '/analytics' # Role required to access the dashboard dashboard_role: 'ROLE_ANALYTICS'
Accessing the Dashboard
Once installed and configured, visit:
https://your-site.com/analytics
Access is restricted to users with the configured role (default: ROLE_ANALYTICS). Assign this role to users who should see analytics, or use Symfony's role hierarchy to link it to ROLE_ADMIN.
Dashboard setup
The dashboard requires Symfony UX Turbo for interactive features (lazy-loading widgets, live search, detail pane navigation). Data collection works without it.
composer require symfony/ux-turbo php bin/console importmap:require uplot
To use your own layout (with your app's navbar, footer, etc.), set dashboard_layout to your base template:
cookieless_analytics: dashboard_layout: 'base.html.twig'
What the dashboard shows
| Section | Description |
|---|---|
| Overview | Total page views and daily visitors for the selected period |
| Top pages | Most visited URLs with daily visitor counts |
| Events | Custom events ranked by count, with distinct value counts |
| Trends | Daily page view and daily visitor chart for the selected period |
How anonymization works
No cookie, no session ID, no persistent identifier is ever stored.
Each request generates a daily fingerprint:
SHA-256( client_ip + user_agent + YYYY-MM-DD )
This hash:
- changes every day — a returning visitor cannot be tracked across days
- is not reversible — the original IP address cannot be recovered
- is not personal data under GDPR — no individual can be singled out
Because the fingerprint rotates daily, the "Daily Visitors" metric is deduplicated within a single day only. Over a multi-day period, the same person visiting on different days is counted once per day — not once for the entire period. This is a deliberate privacy tradeoff: it prevents long-term tracking at the cost of cross-day deduplication.
This approach is consistent with the CNIL guidelines on cookieless audience measurement (délibération n°2020-091).
Custom Event Tracking Reference
| Attribute | Required | Description |
|---|---|---|
data-ca-event |
✅ | Event name (e.g. booking-click, download, outbound-link) |
data-ca-value |
optional | Contextual value (e.g. event title, file name, URL) |
Events are sent via navigator.sendBeacon() — non-blocking, fires even if the user navigates away immediately.
Privacy & Legal
This bundle is designed to operate without a cookie consent banner under the following conditions:
- The tracking script does not set any cookie.
- No personal data (name, email, IP address, persistent identifier) is stored.
- Data is processed exclusively on your own server.
- The purpose is strictly limited to anonymous audience measurement.
Disclaimer: This bundle is provided as-is. You remain responsible for your own GDPR compliance. Consult your DPO or legal counsel if you have specific regulatory obligations.
Roadmap
- CSV/JSON data export
- Bot and crawler filtering
- UTM campaign parameter tracking
- Weekly summary email report
- Dashboard without Turbo (static fallback)
- Symfony Flex recipe (auto-configure, post-install message)
Contributing
Contributions are welcome. Please open an issue before submitting a pull request.
git clone https://github.com/jackfumanchu/cookieless-analytics-bundle.git
cd cookieless-analytics-bundle
composer install
php vendor/bin/phpunit
License
MIT License. See LICENSE for details.