jackfumanchu/cookieless-analytics-bundle

Lightweight, cookieless, GDPR-compliant analytics bundle for Symfony 6.4+

Maintainers

Package info

github.com/jackfumanchu/cookieless-analytics-bundle

Type:symfony-bundle

pkg:composer/jackfumanchu/cookieless-analytics-bundle

Statistics

Installs: 8

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 16

v0.4.0 2026-04-14 23:49 UTC

This package is auto-updated.

Last update: 2026-04-15 00:15:57 UTC


README

CI codecov Mutation testing badge PHPStan PHP Symfony

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:

  1. The tracking script does not set any cookie.
  2. No personal data (name, email, IP address, persistent identifier) is stored.
  3. Data is processed exclusively on your own server.
  4. 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.