Siren

Conversions

Conversion records in Siren's attribution pipeline — data model, status lifecycle, REST API, and PHP data access.

Last updated: April 9, 2026

Conversions

A conversion represents a tracked event where a collaborator’s engagement resulted in a measurable outcome — a sale, a lead capture, or a subscription renewal. Conversions sit between engagements (the upstream referral activity) and obligations (the downstream reward owed to the collaborator). They are the pivot point in Siren’s attribution pipeline: an engagement produces a conversion, and an approved conversion triggers an obligation.

Conversions are created by Siren’s event pipeline when an engagement is matched to a qualifying outcome. The incentive system evaluates the program’s rules, checks the engagement bindings, and creates conversion records automatically. The most common reasons to access conversion data directly are reading conversions for dashboards or reports, looking up conversions to make decisions in custom logic, and writing migration scripts that import historical data from another system.

The conversion object

FieldREST namePHP getterTypeDescription
IDidgetId()integerUnique identifier
EngagementengagementIdgetEngagementId()integerThe engagement that produced this conversion
TransactiontransactionIdgetTransactionId()integer or nullThe associated transaction (e.g., an order), if any
ObligationobligationIdgetObligationId()integer or nullThe obligation created from this conversion, if any
TypetypegetType()stringConversion type identifier (e.g., sale, lead, renewal)
StatusstatusgetStatus()stringCurrent status (see lifecycle below)
CreateddateCreatedgetCreatedDate()datetimeWhen the record was created
ModifieddateModifiedgetModifiedDate()datetimeWhen the record was last updated

The transactionId and obligationId fields are nullable because not every conversion starts with both. A conversion is created when the outcome is detected, but the obligation is only linked later once the incentive system calculates what the collaborator is owed. Similarly, some conversion types (like lead captures) may not involve a transaction at all.

Extended fields (REST only, via ?fields=)

These fields are resolved dynamically by the REST API field resolver system and must be explicitly requested.

FieldTypeDescription
engagementScoremixedScore from the originating engagement
engagementStatusstringStatus of the originating engagement
programIdintegerID of the program the conversion belongs to
collaboratorIdintegerID of the collaborator who earned this conversion
collaboratorNamestringDisplay name of the collaborator
transactionStatusstringStatus of the linked transaction
transactionTotalmixedTotal value of the linked transaction

The ConversionType object

Conversion types define what kinds of events can be tracked as conversions. Each type declares which incentive structures support it.

FieldTypeDescription
idstringUnique type identifier (e.g., sale, lead)
labelstringPlural display label
singularLabelstringSingular display label
supportedIncentivesstring[]Array of incentive type IDs this conversion type supports

Status lifecycle

StatusDescription
pendingInitial state, awaiting review. Every conversion starts here.
approvedThe conversion is valid and triggers downstream obligation creation through the ConversionApproved event and MarkObligationsAsPending listener. This is the path that ultimately leads to a collaborator being rewarded.
rejectedThe conversion was denied. Fires the ConversionRejected event, which triggers RejectObligations to cancel any linked obligation.
expiredThe conversion fell outside the attribution window and is no longer valid. Expiration logic depends on program configuration.
deletedSoft-deleted. A second DELETE call permanently removes the record from the database.

See How Refunds Work for a complete walkthrough of how refunds propagate through the system.

Accessing conversion data

# List pending conversions for a collaborator
curl -X GET "https://your-site.com/wp-json/siren/v1/conversions?status=pending&fields=id,type,status,collaboratorName" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Get a single conversion with extended fields
curl -X GET "https://your-site.com/wp-json/siren/v1/conversions/15?fields=id,type,status,programId,collaboratorName,transactionTotal" \
  -H "Authorization: Bearer YOUR_TOKEN"
use Siren\Conversions\Core\Datastores\Conversion\Interfaces\ConversionDatastore;

class ConversionReport
{
    protected ConversionDatastore $conversions;

    public function __construct(ConversionDatastore $conversions)
    {
        $this->conversions = $conversions;
    }

    public function getPendingConversions(): array
    {
        return $this->conversions->andWhere([
            ['column' => 'status', 'operator' => '=', 'value' => 'pending']
        ]);
    }
}
use Siren\Conversions\Core\Facades\Conversions;

$pending = Conversions::andWhere([
    ['column' => 'status', 'operator' => '=', 'value' => 'pending']
]);

$conversion = Conversions::getById(42);

Siren is built on an event-driven architecture. Creating conversions manually via PHP bypasses the attribution system. The engagement won’t be validated, the program’s incentive rules won’t be evaluated, and downstream obligations won’t be created through the normal flow. If you need to trigger a conversion, fire the appropriate domain event instead of writing directly to this datastore.

PHP domain methods

The conversion datastore supports all shared methods documented in the introduction. There are no additional domain-specific methods beyond the standard CRUD operations.

Querying conversions for a transaction

A common read pattern is finding all conversions tied to a specific transaction. This is how Siren’s own listeners determine which conversions to approve or reject when a transaction completes or is refunded.

$conversions = $this->conversions->andWhere([
    ['column' => 'transactionId', 'operator' => '=', 'value' => $transactionId]
]);

Querying conversions by engagement

To find conversions that originated from a specific engagement:

$conversions = $this->conversions->andWhere([
    ['column' => 'engagementId', 'operator' => '=', 'value' => $engagementId]
]);

Counting pending conversions

$pendingCount = $this->conversions->countAndWhere([
    ['column' => 'status', 'operator' => '=', 'value' => 'pending']
]);

Relationships

Every conversion is linked to exactly one engagement via engagementId. The engagement sits upstream in the attribution pipeline and must exist at creation time, validated by the IdsExist middleware.

A conversion may optionally reference a transaction (such as an e-commerce order) via transactionId. This links the conversion to the concrete event it represents.

On the downstream side, approving a conversion causes the system to create an obligation recording what is owed to the collaborator. The obligationId back-reference is then stored on the conversion, closing the loop between the referral activity and the reward.

REST endpoints

See the individual endpoint pages in the sidebar for full request and response details, or browse the all REST endpoints reference.