PHPackages                             rasuvaeff/yii3-ab-testing-outbox - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. rasuvaeff/yii3-ab-testing-outbox

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

rasuvaeff/yii3-ab-testing-outbox
================================

Outbox producer for Yii3 A/B testing exposure and conversion events

v1.2.2(4w ago)04↓50%BSD-3-ClausePHPPHP 8.3 - 8.5CI passing

Since Jun 12Pushed 1w agoCompare

[ Source](https://github.com/rasuvaeff/yii3-ab-testing-outbox)[ Packagist](https://packagist.org/packages/rasuvaeff/yii3-ab-testing-outbox)[ Docs](https://github.com/rasuvaeff/yii3-ab-testing-outbox)[ RSS](/packages/rasuvaeff-yii3-ab-testing-outbox/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (23)Versions (8)Used By (0)

rasuvaeff/yii3-ab-testing-outbox
================================

[](#rasuvaeffyii3-ab-testing-outbox)

[![Stable Version](https://camo.githubusercontent.com/171d441964f1f60d9394369b7f8a253bc44f6ae19a03487987604b559f082abf/68747470733a2f2f706f7365722e707567782e6f72672f7261737576616566662f796969332d61622d74657374696e672d6f7574626f782f762f737461626c65)](https://packagist.org/packages/rasuvaeff/yii3-ab-testing-outbox)[![Total Downloads](https://camo.githubusercontent.com/7a5b82b6beb396325831fb560e5a3937f07c82e309692127cea852bf389de41d/68747470733a2f2f706f7365722e707567782e6f72672f7261737576616566662f796969332d61622d74657374696e672d6f7574626f782f646f776e6c6f616473)](https://packagist.org/packages/rasuvaeff/yii3-ab-testing-outbox)[![Build](https://github.com/rasuvaeff/yii3-ab-testing-outbox/actions/workflows/build.yml/badge.svg)](https://github.com/rasuvaeff/yii3-ab-testing-outbox/actions)[![Static analysis](https://github.com/rasuvaeff/yii3-ab-testing-outbox/actions/workflows/static-analysis.yml/badge.svg)](https://github.com/rasuvaeff/yii3-ab-testing-outbox/actions)[![Psalm Level](https://camo.githubusercontent.com/8ce0435fcc7740722570b3ddd6028a428a820b8278d0c45487bd8909e8c8668d/68747470733a2f2f73686570686572642e6465762f6769746875622f7261737576616566662f796969332d61622d74657374696e672d6f7574626f782f6c6576656c2e737667)](https://shepherd.dev/github/rasuvaeff/yii3-ab-testing-outbox)[![License](https://camo.githubusercontent.com/0dbc74aff7df6b55358fdc1896fea1e4bdcb16d5aea114994e8af7ac920dc6b7/68747470733a2f2f706f7365722e707567782e6f72672f7261737576616566662f796969332d61622d74657374696e672d6f7574626f782f6c6963656e7365)](https://packagist.org/packages/rasuvaeff/yii3-ab-testing-outbox)[Русская версия](README.ru.md)

Records [`rasuvaeff/yii3-ab-testing`](https://github.com/rasuvaeff/yii3-ab-testing)exposure and conversion events into [`rasuvaeff/yii3-outbox`](https://github.com/rasuvaeff/yii3-outbox)as durable messages. The request path stays fast and survives analytics outages; a worker exports the outbox asynchronously (e.g. with `yii3-outbox-clickhouse`).

> Using an AI coding assistant? [llms.txt](llms.txt) has a compact API reference you can use.

Direct sink vs durable pipeline
-------------------------------

[](#direct-sink-vs-durable-pipeline)

DirectDurable (this package)Package`yii3-ab-testing-clickhouse``yii3-ab-testing-outbox` + `yii3-outbox(-db)` + `yii3-outbox-clickhouse`Batchingper requestlarge, cross-requestSurvives ClickHouse outagenoyesSetupminimalworker + outbox storageRequirements
------------

[](#requirements)

- PHP 8.3+
- `rasuvaeff/yii3-ab-testing` ^1.2
- `rasuvaeff/yii3-outbox` ^1.0
- `psr/clock` ^1.0

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

[](#installation)

```
composer require rasuvaeff/yii3-ab-testing-outbox
```

Usage
-----

[](#usage)

```
use Rasuvaeff\Yii3AbTesting\AbTesting;
use Rasuvaeff\Yii3AbTestingOutbox\OutboxConversionTracker;
use Rasuvaeff\Yii3AbTestingOutbox\OutboxExposureTracker;
use Rasuvaeff\Yii3Outbox\Outbox;

$outbox = new Outbox(storage: $storage, clock: $clock);   // storage from yii3-outbox-db
$exposureTracker = new OutboxExposureTracker($outbox);
$conversionTracker = new OutboxConversionTracker($outbox);

$assignment = $abTesting->assign(experiment: 'checkout', subjectId: $userId);
$exposureTracker->trackExposure($assignment);             // durable, no network call
// later, on the goal:
$conversionTracker->trackConversion($assignment, goal: 'purchase');
```

### Payload

[](#payload)

`ab.exposure` / `ab.conversion` messages carry a JSON object whose field names match the analytics columns of `yii3-ab-testing-clickhouse`:

```
{"v":1,"event_at":"2026-06-12 10:00:00","experiment":"checkout","variant":"green","subject_id":"user-1","is_forced":0,"is_fallback":0,"is_sticky":0,"environment":"production"}
```

The leading `v` field is a transport-meta schema version (`DefaultAbTestingOutboxMessageFactory::PAYLOAD_VERSION`). It is **not** listed in `AbTestingClickHouseRoutes` columns and is never written to ClickHouse — it exists so downstream consumers reading raw outbox messages can detect payload schema generations. Conversions add `"goal"`. Flags are `0|1`; `environment` is always present. `event_at` is the event time (UTC `Y-m-d H:i:s`) stamped when tracked — distinct from the worker's export time.

### ClickHouse routing

[](#clickhouse-routing)

`AbTestingClickHouseRoutes::map()` returns a ready-made route map for `yii3-outbox-clickhouse`. Two transport-meta columns lead each row: `event_id`(filled by the exporter from the message id, for `ReplacingMergeTree` dedup) and `event_at` (event time from the payload):

```
use Rasuvaeff\Yii3AbTestingOutbox\AbTestingClickHouseRoutes;

$router = new MapClickHouseMessageRouter(routes: AbTestingClickHouseRoutes::map());
```

### Yii3 DI

[](#yii3-di)

`config/di.php` binds `ExposureTracker` and `ConversionTracker`. Bind each from a **single** source — installing this next to another tracker backend that also binds them triggers a `yiisoft/config` `Duplicate key` error. To use several sinks at once, compose them in your app config:

```
use Rasuvaeff\Yii3AbTesting\CompositeExposureTracker;
use Rasuvaeff\Yii3AbTesting\ExposureTracker;
use Rasuvaeff\Yii3AbTestingOutbox\OutboxExposureTracker;

return [
    ExposureTracker::class => static fn (Outbox $outbox, LoggerInterface $log): ExposureTracker
        => new CompositeExposureTracker(new OutboxExposureTracker($outbox), new LoggerExposureTracker($log)),
];
```

Security
--------

[](#security)

- `subject_id` may be PII; this package never hashes it silently — privacy policy is the application's.
- Payloads are JSON strings written through the outbox; `goal`/`experiment` are trusted analytics dimensions from your application.

Examples
--------

[](#examples)

See [`examples/`](examples/).

Development
-----------

[](#development)

```
make build
make test
make test-coverage
make mutation
```

See [AGENTS.md](AGENTS.md) for the monorepo-root Docker invocation (path repo).

License
-------

[](#license)

BSD-3-Clause. See [LICENSE.md](LICENSE.md).

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance97

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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

Every ~4 days

Total

5

Last Release

28d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/b0812d5572a7041dfe36e222d295b2e6dc55833a605350fcde58a51a5965ed30?d=identicon)[rasuvaeff](/maintainers/rasuvaeff)

---

Top Contributors

[![rasuvaeff](https://avatars.githubusercontent.com/u/1352718?v=4)](https://github.com/rasuvaeff "rasuvaeff (10 commits)")

---

Tags

ab-testinganalyticsevent-trackingoutbox-patternphpyii3analyticsyii3trackerab-testingoutbox

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm, Rector

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/rasuvaeff-yii3-ab-testing-outbox/health.svg)

```
[![Health](https://phpackages.com/badges/rasuvaeff-yii3-ab-testing-outbox/health.svg)](https://phpackages.com/packages/rasuvaeff-yii3-ab-testing-outbox)
```

###  Alternatives

[symfony/symfony

The Symfony PHP framework

31.4k87.2M2.2k](/packages/symfony-symfony)[ecotone/ecotone

Enterprise architecture layer for Laravel and Symfony — CQRS, Event Sourcing, Durable Workflows (Sagas, Orchestrators), Projections, and Outbox messaging via PHP attributes.

564576.7k54](/packages/ecotone-ecotone)[symfony/clock

Decouples applications from the system clock

433205.7M428](/packages/symfony-clock)[flow-php/etl

PHP ETL - Extract Transform Load - Abstraction

378604.0k107](/packages/flow-php-etl)[mcp/sdk

Model Context Protocol SDK for Client and Server applications in PHP

1.5k1.5M108](/packages/mcp-sdk)[eventsauce/eventsauce

A pragmatic event sourcing library for PHP with a focus on developer experience.

8662.2M57](/packages/eventsauce-eventsauce)

PHPackages © 2026

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