Siren

Commerce Events

Domain events triggered by e-commerce activity. Sales, refunds, coupons, renewals, and leads.

Last updated: April 8, 2026

Commerce Events

Commerce events are the entry point into Siren’s attribution pipeline. They fire when something happens in an integrated e-commerce platform: a sale completes, a coupon is applied, a subscription renews, or a form submission arrives. All commerce events live in the Siren\Commerce\Events namespace and implement PHPNomad’s Event interface. See the integration feature matrix for which events each integration supports.

Extensions produce commerce events through transformers. Your extension code does not dispatch these events directly; it returns an event instance from a transformer callback, and the framework broadcasts it. See the Commerce Events extension guide for how to produce these events from your own integration.

How commerce events enter the pipeline

Commerce events follow a consistent path from the e-commerce platform into Siren’s core. An extension registers a transformer that maps a platform hook (such as a WooCommerce order status change) to a commerce event class. When the hook fires, the framework calls the transformer, which constructs the appropriate event instance and returns it. The framework then broadcasts the event through the event bus, where core listeners pick it up and begin processing.

This design means extensions never call the event dispatcher themselves. They declare what platform activity maps to which event, and the framework handles the rest. The result is a clean boundary between platform-specific integration code and Siren’s core attribution logic.

Each event carries the data that downstream listeners need: opportunity IDs for attribution lookup, transaction details for conversion building, binding fields for mapping back to external records, and source identifiers for tracking which extension produced the event.

The typical sale flow looks like this:

SaleTriggered Extension detects a purchase
TransactionCompleted Payment gateway confirms

For coupon-based attribution, the flow is slightly different. The coupon event fires first to establish the engagement, then a subsequent sale event creates the conversion:

CouponApplied Customer uses coupon at checkout
SaleTriggered Sale completes with coupon attribution

Commerce events in this category

SaleTriggered

The primary commerce event for purchases. Fires when an extension detects an order that Siren should track. This event carries the opportunity ID, transaction details, and source identifier, and triggers the conversion pipeline that produces conversions, obligations, and eventually payouts.

TransactionCompleted

Fires when an order reaches its final approved state, typically after the payment gateway confirms the charge. This is separate from SaleTriggered because many platforms create orders before payment clears. Approving a transaction advances its obligations from draft to pending status, making them eligible for payout.

RefundTriggered

Fires when a completed order is reversed, whether through a cancellation, refund, or deletion. Core listeners cancel the associated conversions, mark the transaction as refunded, and adjust metric totals so collaborator performance numbers stay accurate.

CouponApplied

Fires when a customer uses a coupon code during checkout. Unlike sale events, this event carries the coupon code and the opportunity rather than transaction details. Siren uses the coupon code to look up which collaborator owns it and creates engagements that a subsequent sale event converts into credited commissions.

RenewalTriggered

Fires when a subscription renewal payment completes. This event traces back to the original purchase transaction so that the same collaborator continues earning commissions on recurring revenue. The conversion process mirrors the initial sale flow but uses the original transaction’s attribution data instead of looking up a new opportunity.

LeadTriggered

The non-monetary equivalent of SaleTriggered. Fires when a form submission or signup action occurs, carrying an opportunity ID and source string but no transaction details. The downstream pipeline creates conversions and obligations using lead-specific incentive types rather than sale-based ones.

Listening to commerce events from an extension

Here is a complete example of registering a listener that reacts to SaleTriggered from an extension. The listener uses dependency injection to access the collaborator datastore and a logger.

<?php

namespace Siren\WordPress\Extensions\MyExtension\Listeners;

use PHPNomad\Events\Interfaces\CanHandle;
use PHPNomad\Events\Interfaces\Event;
use PHPNomad\Logger\Interfaces\LoggerStrategy;
use Siren\Collaborators\Core\Datastores\Collaborator\Interfaces\CollaboratorDatastore;
use Siren\Commerce\Events\SaleTriggered;

/**
 * @implements CanHandle<SaleTriggered>
 */
class NotifyOnSale implements CanHandle
{
    protected CollaboratorDatastore $collaborators;
    protected LoggerStrategy $logger;

    public function __construct(
        CollaboratorDatastore $collaborators,
        LoggerStrategy $logger
    ) {
        $this->collaborators = $collaborators;
        $this->logger = $logger;
    }

    public function handle(Event $event): void
    {
        $this->logger->info(
            'Sale triggered for opportunity ' . $event->getOpportunityId()
            . ' from source ' . $event->getSource()
        );
    }
}
use PHPNomad\Events\Interfaces\HasListeners;
use Siren\Commerce\Events\SaleTriggered;
use Siren\WordPress\Extensions\MyExtension\Listeners\NotifyOnSale;

class MyExtensionInitializer implements HasListeners
{
    public function getListeners(): array
    {
        return [
            SaleTriggered::class => NotifyOnSale::class,
        ];
    }
}

The listener is resolved through the DI container when the event fires, so CollaboratorDatastore and LoggerStrategy are injected automatically. See the Listeners & Event Handlers guide for more patterns and details on writing listener classes.