PHPackages                             vizuh/shopware-clicktrail - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. vizuh/shopware-clicktrail

ActiveShopware-platform-plugin

vizuh/shopware-clicktrail
=========================

Shopware 6.6 plugin for ClickTrail attribution: storefront touch capture, consent-aware sale/refund forwarding, first-party collect proxy.

v0.1.0(today)00[3 issues](https://github.com/vizuh/clicktrail-shopware/issues)MITPHPPHP &gt;=8.1CI passing

Since Aug 25Pushed todayCompare

[ Source](https://github.com/vizuh/clicktrail-shopware)[ Packagist](https://packagist.org/packages/vizuh/shopware-clicktrail)[ RSS](/packages/vizuh-shopware-clicktrail/feed)WikiDiscussions main Synced today

READMEChangelog (1)Dependencies (2)Versions (2)Used By (0)

[English](README.md) | [Português](README.pt-BR.md) | [Deutsch](README.de.md) | [中文](README.zh-CN.md)

**vizuh/shopware-clicktrail**

ClickTrail attribution across the full Shopware 6 commerce lifecycle — capture the storefront visit, then forward consent-gated sale and refund events that stay attached to the original attribution.

[![CI](https://github.com/vizuh/clicktrail-shopware/actions/workflows/ci.yml/badge.svg)](https://github.com/vizuh/clicktrail-shopware/actions/workflows/ci.yml)[![License: MIT](https://camo.githubusercontent.com/08cef40a9105b6526ca22088bc514fbfdbc9aac1ddbf8d4e6c750e3a88a44dca/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d626c75652e737667)](LICENSE)

Index
-----

[](#index)

- [Why](#why)
- [Installation](#installation)
- [Quick start: storefront visit capture](#quick-start-storefront-visit-capture)
- [Plugin configuration](#plugin-configuration)
- [Order lifecycle forwarding](#order-lifecycle-forwarding)
- [Consent gating](#consent-gating)
- [First-party proxy](#first-party-proxy)
- [State storage](#state-storage)
- [How it differs](#how-it-differs)
- [Shopware Store review requirements](#shopware-store-review-requirements)
- [Status and deferrals](#status-and-deferrals)
- [Testing](#testing)
- [License](#license)

Why
---

[](#why)

Ecommerce trackers usually fire a purchase pixel and forget it. This Shopware 6.6 plugin attaches the deterministic ClickTrail core ([`clicktrail/php-sdk`](https://github.com/vizuh/clicktrail-php)) to the whole commerce lifecycle: a paid-search visit is captured on the storefront, and every later state change — placed, paid, completed, cancelled, refunded — becomes a consent-gated event envelope carrying order value, currency, customer and order IDs. A refund is never an orphan row; it stays attached to the attribution that created the sale.

Installation
------------

[](#installation)

Shopware 6.6 **plugin** (not app):

```
composer require vizuh/shopware-clicktrail
bin/console plugin:refresh
bin/console plugin:install --activate ClickTrail
```

Requires PHP &gt;= 8.1, `shopware/core` ~6.6, and `clicktrail/php-sdk` (dev-main).

Quick start: storefront visit capture
-------------------------------------

[](#quick-start-storefront-visit-capture)

On every main storefront request, the `kernel.request` subscriber runs the SDK merge law against query parameters, referrer and landing page:

```
// inside ClickTrail\Shopware\Storefront\Subscriber\RequestSubscriber:
$stored = StoredState::fromJson($session->get('clicktrail_attribution'));

$merged = TouchMerger::observe($stored, new AttributionInput(
    query: $request->query->all(),
    host: $request->getHost(),
    landingPage: $request->getUri(),
    referrer: $request->headers->get('referer'),
    touchTimestamp: gmdate('c'),
));

$session->set('clicktrail_attribution', $merged->toJson());
// After a ?gclid=... landing, the session holds first->source === 'google'
// with the click ID stored. A direct visit afterwards changes nothing:
// first touch stays. Same merge laws as every other ClickTrail adapter.
```

Capture can be turned off per sales channel with the *Capture storefront touches* switch (see below).

Plugin configuration
--------------------

[](#plugin-configuration)

Settings → Extensions → ClickTrail (`src/Resources/config/config.xml`), readable per sales channel through `Service\PluginConfig`:

SettingMeaningDefaultSite IDIdentifier issued by the collectoremptyAPI endpointIngest base URLemptyConsent integration mode`auto-detect` (CMP hook point) or `custom` (developer-supplied resolver)auto-detectCapture storefront touchesEnables the request subscriberonForward sale.completed / lifecycle eventsGates all commerce subscribersonForward sale.refunded eventsGates refund forwarding onlyonEnable first-party proxy route (`/clicktrail/collect`)Off by default; enable when your stack wants a first-party cookie contextoffOrder lifecycle forwarding
--------------------------

[](#order-lifecycle-forwarding)

Five subscribers translate Shopware state changes into schema-versioned SDK envelopes via `PayloadSerializer`, each passing config gate → consent gate → serialization:

SubscriberShopware eventEnvelopeOrderPlacedSubscriber`checkout.order.placed``sale.completed`OrderPaidSubscriber`state_enter.order_transaction_state.paid``sale.completed` (paid stage)OrderCompletedSubscriber`state_enter.order_state.completed``sale.completed` (fulfilled)OrderCancelledSubscriber`state_enter.order_state.cancelled``sale.completed` + `status=cancelled` extra — not a refundRefundSubscriber`state_enter.order_transaction_state.refunded``sale.refunded`Every envelope carries order value, currency, customer ID and order number. The refund envelope keeps the link to the attribution captured at `storefront_visit`. State-machine event names are marked `TODO verify` against 6.6 before the first release tag.

Consent gating
--------------

[](#consent-gating)

One gate guards every outbound path. Forwarding conversion data requires `advertising_storage` granted; unknown counts as denied:

```
// ClickTrail\Shopware\Consent\ConsentGate
$snapshot = $this->consentGate->allows(ConsentSnapshot::CAP_ADVERTISING_STORAGE);
if ($snapshot === null) {
    // no snapshot => delivery suppressed; nothing leaves the shop
}
```

`ShopwareConsentResolver` is the CMP hook point: in `auto-detect` mode it reads a `window.__clicktrail_consent` payload injected by the loader snippet; in `custom` mode you replace the service definition in `services.xml`. Until a real resolver is wired it returns an all-unknown snapshot — so by default, nothing forwards.

First-party proxy
-----------------

[](#first-party-proxy)

Optional route `POST /clicktrail/collect` lets the storefront loader post envelopes to your own domain instead of straight to the ingest endpoint, keeping a first-party cookie context:

```
// CollectController: disabled route answers 404 {"error":"disabled"};
// missing analytics consent answers 403 {"error":"consent_required"}.
return new JsonResponse(['queued' => 0], 202);
```

Queueing into `BatchClient` and flushing on `kernel.terminate` is deferred pending live-endpoint verification.

State storage
-------------

[](#state-storage)

A documented v1 choice: attribution state lives **in the storefront session only**. No database tables ship, therefore no migrations. Consequence: order lifecycle events cannot read back attribution captured days earlier yet — persisting `StoredState` with the order is planned v2 work.

How it differs
--------------

[](#how-it-differs)

This pluginGeneric ecommerce trackingAttributionDeterministic first/last-touch merge laws from the shared SDK, identical in WordPress/GTM adaptersPer-platform last-click guessesRefunds`sale.refunded` stays attached to the initial attributionUsually a detached refund eventConsentNormalized contract, unknown = denied, enforced before any sendOften a client-side flag onlyStorageSession-only v1, zero migrationsPlugin-specific tables from day oneShopware Store review requirements
----------------------------------

[](#shopware-store-review-requirements)

Distribution goes through the Shopware Store, which reviews quality, security, compatibility and compliance before listing:

- No dynamic SQL — DAL repositories or parameterized DBAL only.
- CSRF handling on any storefront write route.
- No PII beyond what consent allows.
- CSP-compatible script injection through theme blocks.
- Consent behavior follows the normalized contract in [`docs/consent-compatibility-plan.md`](../docs/consent-compatibility-plan.md) (unknown = denied).

Status and deferrals
--------------------

[](#status-and-deferrals)

- Concrete CMP integration (Cookiebot/CookieYes/iubenda bridge): DEFERRED — the resolver returns all-unknown today, so nothing forwards until wired.
- `BatchClient` queueing in `CollectController` and commerce subscribers: DEFERRED pending live-endpoint verification.
- Twig block names and state-machine event names: marked `TODO verify` against Shopware 6.6 before the first release tag.

Testing
-------

[](#testing)

No PHPUnit suite ships yet. CI lints every PHP file on PHP 8.1–8.3; XML resources were parsed during scaffolding validation:

```
composer install --prefer-dist --no-interaction || echo "no deps"
find . -name '*.php' -not -path './vendor/*' -print0 | xargs -0 -n1 php -l   # exits clean on success
python3 -c "import xml.etree.ElementTree as ET; ET.parse('src/Resources/services.xml'); ET.parse('src/Resources/config/config.xml')"   # XML well-formedness
```

License
-------

[](#license)

MIT - Copyright (c) 2026 Vizuh OÜ. See [LICENSE](LICENSE).

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity32

Early-stage or recently created project

 Bus Factor1

Top contributor holds 88.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/20295730?v=4)[Hugo ](/maintainers/Atroci)[@Atroci](https://github.com/Atroci)

---

Top Contributors

[![Atroci](https://avatars.githubusercontent.com/u/20295730?v=4)](https://github.com/Atroci "Atroci (8 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

analyticsattributionclickstreamconsent-managementconversion-trackingecommercefirst-party-datagdprmarketing-analyticsoffline-conversionsorder-trackingphpshopwareshopware-6utmshopwareUTMattributionconsentgclid

### Embed Badge

![Health badge](/badges/vizuh-shopware-clicktrail/health.svg)

```
[![Health](https://phpackages.com/badges/vizuh-shopware-clicktrail/health.svg)](https://phpackages.com/packages/vizuh-shopware-clicktrail)
```

###  Alternatives

[shopware/storefront

Storefront for Shopware

674.7M288](/packages/shopware-storefront)[frosh/tools

Provides some basic things for managing the Shopware Installation

88858.1k3](/packages/frosh-tools)[shopware/production

176216.5k](/packages/shopware-production)[shopware/administration

Administration frontend for the Shopware Core

404.5M135](/packages/shopware-administration)[shopware/elasticsearch

Elasticsearch for Shopware

144.1M21](/packages/shopware-elasticsearch)[adyen/adyen-shopware6

Official Shopware 6 Plugin to connect to Payment Service Provider Adyen

25119.6k](/packages/adyen-adyen-shopware6)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
