Search by

tenbruggencate / analytics-lite

guy@tenbruggencatedevelopment.nl

Shopware 6 analytics: multi-backend (Matomo + Plausible), cookieless by default, respects GPC, with Matomo e-commerce tracking (product views, cart updates, checkout steps, orders with revenue).

Package info

bitbucket.org/Bruggencate/sw-plugin-analytics-lite

Homepage

Issues

Documentation

Type:shopware-platform-plugin

pkg:composer/tenbruggencate/analytics-lite

Statistics

Installs: 204

Dependents: 0

Suggesters: 0

2.2.7 2026-10-15 10:27 UTC

README

Ten Bruggencate Development

Analytics Lite (multi-backend, GDPR-first)

Analytics Lite

Multi-backend analytics for Shopware 6. Ships a TrackerInterface abstraction plus two production-ready adapters (Matomo + Plausible); plug in any other backend by implementing the interface. Cookieless by default. GDPR-first defaults.

Free edition โ€” frozen. This free edition stays available and keeps working, but gets no new features. It receives security and Shopware compatibility fixes until at least December 2032. New features go into the paid edition of this plugin, coming to the Shopware Store; your data and settings carry over when you switch. The two cannot be active together: once the paid plugin (2.0 or later) is active, this plugin refuses to activate. Questions or help with switching: tenbruggencatedevelopment.nl/en/contact

License: MIT ยท Shopware: 6.7.x ยท PHP: 8.2 or newer

๐Ÿ‡ฌ๐Ÿ‡ง English ยท ๐Ÿ‡ณ๐Ÿ‡ฑ Nederlands ยท ๐Ÿ‡ฉ๐Ÿ‡ช Deutsch

๐Ÿ“– More context: Why we built this ยท How it compares

Free edition

This free edition ships the full multi-backend tracker abstraction (Matomo + Plausible adapters), cookieless mode, GPC respect, sales-channel-scoped configuration, Matomo e-commerce tracking (product views, cart updates, checkout steps and orders with revenue) and the brand + page-type custom dimensions โ€” everything you need to run a privacy-first analytics setup in production.

Screenshots

The plugin emits invisible tracker scripts on the storefront โ€” there's nothing for visitors to see. The visible surface is the admin config card; neutral screenshots of it follow in a later release.

What it does

Most analytics plugins for Shopware are single-backend ("Matomo plugin", "GA plugin", "Plausible plugin"), which forces a lock-in: switching backend means uninstalling one plugin and learning another. This plugin separates "what to track" from "where to send it":

  • TrackerInterface โ€” stable contract (emitHeadScript(), emitBodyEnd(), trackEvent(...)) that any backend implements
  • TrackerRegistry โ€” admin picks the active backend from a list; switching is a config change, not a reinstall
  • Bundled adapters โ€” Matomo (was formerly its own plugin, folded in so shop owners install one thing) and Plausible
  • Cookieless by default โ€” no cookies set unless the admin explicitly opts in
  • E-commerce tracking (Matomo) โ€” product views on the product page, cart updates on the cart and every checkout step (including the off-canvas cart), and the order with revenue, tax, shipping and discount on the finish page. Only product lines are reported; promotion discounts go in the order's discount field. With Plausible, the finish page sends a purchase event with the order revenue
  • Global Privacy Control respect โ€” when a visitor's browser sends Sec-GPC: 1 and the new respectGpc config is on (default), no analytics script is rendered for that request. No Matomo loader, no Plausible script, no third-party origin call. GPC is the W3C-standard successor to Do-Not-Track, with regulatory teeth (CCPA already binds operators to honour it). Server-side detection via the request header โ€” the cleanest possible privacy story

Install

composer require tenbruggencate/analytics-lite
bin/console plugin:refresh
bin/console plugin:install --activate TenBruggencateAnalytics
bin/console cache:clear

Configuration

Configurable per sales channel from Settings โ†’ System โ†’ Plugins โ†’ Analytics.

FieldDefaultPurpose
enabledtrueKill switch for all tracker emission
trackerTypematomomatomo or plausible (or any custom tracker registered via services.xml)
matomoUrlโ€”Your Matomo endpoint (when trackerType=matomo)
siteIdโ€”Matomo site ID
cookielessModetrueMatomo disableCookies toggle
ipAnonymizationtrueDrop last octet before storage
respectDoNotTracktrueHonour the browser's DNT header
trackAdminUsersfalseKept for compatibility; currently no effect: admin preview visits are counted either way (use Matomo's opt-out to exclude them)
brandDimensionId0Matomo custom-dimension ID to record brandKey (when used with TenBruggencateMultiBrand)
pageTypeDimensionId0Dimension ID for page-type labels (home / plp / pdp / checkout)
stoneSlugDimensionId0Matomo custom-dimension ID for the slug of a content detail page (provided by Product Encyclopedia); the key name is historical and kept for compatibility

Usage

The tracker renders itself into every storefront page. No template work needed.

Adding a new backend โ€” implement TrackerInterface:

final class UmamiTracker implements TrackerInterface
{
    public function getKey(): string { return 'umami'; }
    public function emitHeadScript(SalesChannelContext $ctx): string { /* ... */ }
    public function emitBodyEnd(SalesChannelContext $ctx): string { return ''; }
    public function trackEvent(string $event, array $properties): void { /* ... */ }
}

Register it in your plugin's services.xml with the ten_bruggencate_analytics.tracker tag and it appears in the admin dropdown.

Extending: suppress client-side e-commerce events

Since 2.2.5 another plugin can tell Lite to skip its own e-commerce JS for one request โ€” for example a plugin that sends orders server-side and would otherwise count every order twice. Nothing changes as long as nobody flips the switch.

KindWhat Lite leaves out
orderFinish page: Matomo addEcommerceItem ร— N + trackEcommerceOrder (a plain trackPageView is sent instead, so the page still counts) and the Plausible purchase event
cartCart page, address and confirm step: addEcommerceItem ร— N + trackEcommerceCartUpdate (the page view stays), and the off-canvas cart JSON

Three equivalent ways to set it โ€” the request flag, the page extension tbAnalytics (suppress: [...]) or the Twig function:

// PHP, e.g. in a CheckoutFinishPageLoadedEvent subscriber
use TenBruggencateAnalytics\Service\EcommerceSuppression;

if (class_exists(EcommerceSuppression::class)) { // Lite >= 2.2.5
    EcommerceSuppression::suppressOn($event->getRequest(), EcommerceSuppression::ORDER);
}

// or as a page extension
$event->getPage()->addArrayExtension('tbAnalytics', ['suppress' => ['order']]);
{# Twig, in a template that extends storefront/base.html.twig #}
{% block base_body_script %}
    {% do tb_analytics_suppress('order') %}
    {{ parent() }}
{% endblock %}

Lite checks it with tb_analytics_suppressed(kind, page). The Twig call must run before Lite's base_body_script block renders (before parent()). Older Lite versions don't have the class or the function: guard PHP with class_exists() and don't call the Twig function from a template that must also work with Lite < 2.2.5 (Twig fails on unknown functions).

For full control the JS also sits in named blocks you can override: tb_analytics_ecommerce_order (Matomo order), tb_analytics_ecommerce_order_plausible (Plausible purchase), tb_analytics_ecommerce_cart (Matomo cart update) and tb_analytics_ecommerce_offcanvas_cart (off-canvas cart JSON). An empty tb_analytics_ecommerce_order also drops the finish page's page view โ€” use the switch when you only want the order gone.

Standards

  • Performance โ€” single inline script in <head>, ~1.5 KB when Matomo is configured, ~0.4 KB for Plausible. No external library fetch until the user has interacted (cookieless flow).
  • SEO โ€” tracker emission does not touch meta tags, URLs, canonicals, or sitemaps.
  • GDPR โ€” cookieless / DNT-respecting / IP-anonymised defaults ship true. Track-admin-users defaults to false. Includes a Migration<ts>CopyMatomoConfig that forward-migrates existing settings from the deprecated standalone Matomo plugin. Full data-flow + subject-rights documentation in GDPR.md.
  • WCAG โ€” tracker output is an inline script; no visual or interaction surface. Rationale + structural guarantees documented in docs/ACCESSIBILITY.md.
  • Security โ€” all configured URLs are validated as HTTPS in the admin config form. No eval, no dynamic script injection, no third-party CDN fetch until the admin turns off cookieless mode.
  • Uninstall โ€” plugin:uninstall --keep-user-data preserves tracker config (Matomo URL, site IDs, dimensions); plugin:uninstall without the flag also drops any legacy TenBruggencateMatomo.config.* rows from the old standalone plugin. No owned tables โ€” analytics data lives on the configured backend, not in this shop.

Production-readiness checklist

A deliberately short list of things to verify before enabling the plugin on a customer-facing storefront. Not legal cover โ€” the MIT license already disclaims warranty โ€” but practical guidance an experienced operator would want anyway.

  • [ ] Don't accept the default siteId=1 blindly. Especially on a Matomo instance that already has unrelated sites โ€” sending shop traffic to siteId 1 will pollute someone else's stats. Get the right ID from your Matomo admin first.
  • [ ] Set matomoUrl (or plausibleDomain / plausibleScriptUrl) before enabling. With enabled=true but the URL field empty, shouldRender() correctly returns false and no script is emitted โ€” but the admin sees no warning either, just zero data flowing in.
  • [ ] Test with Sec-GPC: 1 on staging. The plugin short-circuits when the header is present and respectGpc is on (default). Easiest way: curl -H "Sec-GPC: 1" https://shop.tld/ and grep for setSiteId / data-domain โ€” should be empty. If you see the script, GPC isn't being respected.
  • [ ] Review the per-SC config for multi-store shops. analytics_tracker_config() reads per-sales-channel โ€” if you've configured Matomo for SC A and Plausible for SC B, the backends genuinely are different per domain. Verify the right script appears on each.
  • [ ] Keep your own visits out with Matomo's opt-out, not with trackAdminUsers. The setting is kept for compatibility but currently has no effect: Shopware gives the storefront no reliable signal that a visitor is a logged-in admin, so admin preview visits are counted whether it is on or off. To test the storefront without polluting stats, use Matomo's "Opt out of tracking" link or a separate browser profile.

Compatibility

Core platform

ShopwarePHPStatus
6.7.x โ€” tested with Shopware 6.7.158.2 or newerStable
6.6.xโ€”Not supported
6.5.x and earlierโ€”Not supported

Database

EngineVersionNotes
MySQL8.0+Primary target; JSON functions used for config-row manipulation in migrations
MariaDB10.11+Tested end-to-end; earlier versions lack some JSON operator support

Browsers (storefront)

Evergreen browsers only โ€” the two most recent stable releases of each:

BrowserDesktopMobile
Chrome / Chromiumโœ…โœ…
Firefoxโœ…โœ…
Safariโœ… (macOS)โœ… (iOS 16+)
Edgeโœ…โ€”

Internet Explorer and legacy Edge are not supported. The plugin emits no runtime JS (where applicable) so graceful degradation on older browsers usually still renders content, just without progressive enhancements.

Admin browsers

Same evergreen matrix โ€” the Shopware admin is Vue-based and has its own compatibility baseline that this plugin doesn't extend or narrow.

Development

ToolVersionScope
PHPโ‰ฅ 8.2Runtime + test suite
Composer2.xDependency management
Node.jsโ‰ฅ 18Only needed if you edit SCSS and re-run the theme compile
Pythonโ‰ฅ 3.9Only needed for the repo's asset-pipeline scripts (scripts/*.py)

Accessibility

WCAG 2.2 level A + AA โ€” see docs/ACCESSIBILITY.md for axe-core audit output and per-page violations.

What we test before each release

  • Full PHPUnit unit suite against PHP 8.2 (source-inspection tests don't need a kernel)
  • PHPStan level 8 + PHP-CS-Fixer (@PSR12 + @Symfony)
  • Composer validate on every plugin
  • Live-DB smoke tests (plugin install โ†’ activate โ†’ route render โ†’ uninstall cycle)
  • axe-core audit on the primary storefront surfaces (see ACCESSIBILITY.md)

Related plugins

Part of the TenBruggencate Suite โ€” small, focused plugins that play well together:

  • MultiBrand โ€” provides the brandKey that brandDimensionId records, so Matomo reports can slice by brand without needing separate site IDs.
  • Maintenance โ€” maintenance page renders with tracker disabled (no analytics noise during downtime).
  • LegalPages โ€” Dutch / German / English legal page templates. Privacy page is the natural target for the Cookie Notice / DPA reference.
  • NewsletterLite โ€” GDPR-safe newsletter signup that pairs naturally with privacy-first analytics.

Migration from the standalone Matomo plugin

If you previously used tenbruggencate/shopware-matomo, upgrade is automatic. Two migrations run on plugin:install --activate TenBruggencateAnalytics:

  1. Migration1713225600CopyMatomoConfig โ€” mirrors TenBruggencateMatomo.config.* rows into TenBruggencateAnalytics.config.*
  2. Migration1776530000RemoveOrphanedMatomoPlugin โ€” defensive cleanup of the now-unused plugin registry row

No admin reconfiguration needed; tracking continues uninterrupted.

More from Ten Bruggencate Development

Shopware 6.7 plugins in nine families. Analytics, Legal Pages, Maintenance (Launch), Newsletter, Product Encyclopedia and Stock Alert are becoming paid plugins in the Shopware Store; Multi-Brand, Seasons and Social Login stay free on Packagist. Overview: tenbruggencatedevelopment.nl/en/initiatieven/shopware-plugins

  • Analytics โ€” Matomo or Plausible, cookieless, with e-commerce events
  • Legal Pages โ€” terms, privacy, shipping and returns pages from templates
  • Maintenance (Launch) โ€” a branded, SEO-correct (HTTP 503) maintenance page
  • Multi-Brand โ€” several brands on one Shopware, recognised by domain
  • Newsletter โ€” GDPR-safe sign-up with double opt-in
  • Product Encyclopedia โ€” educational content pages linked to your products
  • Seasons โ€” scheduled theme variants (colours, typography, hero)
  • Social Login โ€” passwordless login link, Google and Facebook
  • Stock Alert โ€” "notify me when it's back" with double opt-in

Support

Security updates and support period

  • Support period: the latest 2.x release receives security updates until at least December 2032. Fixes ship in the newest 2.x release; updating within 2.x is free and needs no configuration change. Before support ends, the README and CHANGELOG say what comes next.
  • Free of charge: security updates cost nothing, and are released separately from feature updates where possible (a patch release with only the fix).
  • How to install them: Plugin Manager โ†’ Update, or composer update tenbruggencate/analytics-lite followed by bin/console plugin:update TenBruggencateAnalytics and bin/console cache:clear. Shopware does not install plugin updates automatically; check the CHANGELOG Security section after each release.
  • Report a vulnerability: guy@tenbruggencatedevelopment.nl, never a public issue. Rules: SECURITY.md.
  • SBOM: a CycloneDX bill of materials is produced for every release and published on the repository's Downloads page; see SECURITY.md.
  • Removing it securely: uninstall with Delete all app data (or bin/console plugin:uninstall TenBruggencateAnalytics without --keep-user-data) to remove the tracker settings and any leftover settings of the old standalone Matomo plugin (the plugin has no tables; the analytics data on your Matomo or Plausible server is not touched).

Made by Ten Bruggencate Development โ€” tenbruggencatedevelopment.nl.

License

MIT ยฉ Ten Bruggencate Development