Siren

The Attribution Pipeline

End-to-end walkthrough of how a customer interaction becomes a collaborator payout. Covers every stage from opportunity creation through fulfillment.

Last updated: April 8, 2026

The Attribution Pipeline

When a customer clicks an affiliate link, Siren begins tracking a chain of events that can end with a collaborator receiving a payout. The path from that first click to a deposited commission passes through six distinct stages, each connected only by domain events. No stage calls the next directly. Each one reacts to the event that came before it, which means extensions can hook into any point in the pipeline without modifying the core.

This page walks through the full pipeline end-to-end. If you are debugging a specific stage, this is where you find out which events to look at and how data flows between them. If you are building an extension, this is where you learn where your code fits in.

The full pipeline at a glance

Opportunity Customer visits via referral link
Engagement Collaborators earn credit claims
Commerce Sale, lead, or renewal detected
Conversion Credit assigned per program
Obligation Business records what it owes
Payout Collaborator receives payment

Each stage produces one or more events. Each event triggers listeners that advance the pipeline to the next stage. The sections below explain what happens at each stage, which events fire, and how data threads through from start to finish.

Stage 1: Opportunity creation

The pipeline begins when a customer arrives through a referral mechanism. When someone clicks an affiliate link, Siren creates an opportunity record that captures the referral context: which link was used, when the visit happened, and what tracking data is available. The opportunity is Siren’s way of saying “this customer might convert, and here’s who referred them.”

OpportunityTriggered Referral link clicked or coupon used

The OpportunityTriggered event carries the opportunity model and the trigger type (link visit, coupon code, manual creation). Engagement trigger strategies listen for this event and decide which collaborators should receive credit claims. If the opportunity is invalid (expired link, duplicate detection, validation failure), OpportunityInvalidated fires instead and the pipeline stops here.

An opportunity carries an ID that threads through the entire pipeline. Every subsequent event references this ID to trace back to the original customer interaction.

Stage 2: Engagement tracking

Engagements represent a collaborator’s credit claim against a specific program. When an opportunity fires, the system evaluates which programs apply and which collaborators are eligible, then creates engagement records.

OpportunityTriggered Customer referred
EngagementsTriggered Credit claims created per program

A single opportunity can produce multiple engagements. If a collaborator participates in three programs, the system creates three engagement records, each linking the collaborator to a specific program for this opportunity. Each engagement has a score that program group resolution strategies use later to determine which engagement wins if programs are mutually exclusive.

Engagements sit in an active state until a commerce event converts them. They are claims, not credits. The collaborator does not earn anything yet.

Stage 3: Commerce events

Commerce events are the entry points where real business activity enters the pipeline. When an e-commerce platform detects a sale, renewal, refund, or lead, the appropriate extension produces a commerce event. These events carry the financial details that the conversion system needs to calculate what each collaborator earns.

SaleTriggered Extension detects a purchase
TransactionCompleted Payment gateway confirms

SaleTriggered is the most common entry point. It carries the opportunity ID (linking back to the referral), transaction details (line items with names, values, and types), the source extension identifier, and optional binding fields for mapping back to external records like WooCommerce order IDs.

Extensions do not dispatch commerce events directly. They return event instances from transformer callbacks, and the framework broadcasts them. This keeps extension code cleanly separated from the core attribution logic.

How commerce events branch

The pipeline branches depending on how the customer was attributed and what kind of activity occurred.

Link attribution follows the standard path. The opportunity was created by a link click, engagements already exist, and the sale event triggers conversion processing against those existing engagements.

Coupon attribution works differently. CouponApplied fires first when the customer enters a coupon code at checkout, creating engagements directly from the coupon ownership. A subsequent SaleTriggered event then converts those engagements into credits.

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

Lead attribution uses LeadTriggered instead of SaleTriggered. Leads carry an opportunity ID and source string but no transaction details. The downstream pipeline uses lead-specific incentive types rather than sale-based ones.

Renewals use RenewalTriggered, which traces back to the original purchase transaction so the same collaborator continues earning on recurring revenue. The conversion process mirrors the initial sale flow but reuses the original engagement records instead of looking up a new opportunity.

Stage 4: Conversion building

This is where the pipeline calculates what each collaborator actually earns. The conversion system takes the commerce event, finds all qualifying programs, and builds conversion records.

ConversionInitialized Commerce event received
ConversionsAwarded Credit assigned per program
ConversionApproved Conversion passes review

ConversionInitialized is the handoff event from commerce to conversions. The BuildConversions listener picks it up, retrieves all programs compatible with the conversion type, and delegates to the ConversionAwardStrategy for each qualifying program. The strategy evaluates which engagements win (using program group resolution if programs are mutually exclusive), calculates incentive amounts, and creates conversion records.

ConversionsAwarded fires once per program that produces conversions. Each conversion links to a specific engagement, an optional transaction, and will later link to an obligation. Conversions start in draft status.

Conversions advance to approved status through one of two paths. If the transaction’s payment clears, TransactionCompleted fires and the ApproveTransactionConversions listener automatically approves all conversions linked to that transaction. Alternatively, an admin can approve conversions manually through the dashboard. Either way, ConversionApproved fires for each approved conversion, which triggers the next stage.

If a conversion is rejected (refund, admin decision, fraud), ConversionRejected fires and the associated obligations are cleaned up.

Program groups and mutual exclusivity

When programs belong to a program group, only one program per group can award conversions for a given opportunity. ProgramGroupConversionTriggered fires to identify the winning program (determined by the group’s resolution strategy), and listeners clean up engagements on the losing programs.

Manual attribution

Admins can bypass the normal engagement flow entirely using ManualAttributionRequested. This creates conversions for a specific collaborator without requiring an existing engagement, useful for crediting partners retroactively or handling edge cases that the automated pipeline did not capture.

Stage 5: Obligations and transactions

When conversions are awarded, the system creates obligation records that track what the business owes each collaborator.

ConversionsAwarded Credit assigned
ObligationIssued Business records debt
ConversionApproved Payment confirmed
Obligation pending Eligible for payout

ObligationIssued fires when an obligation record is created. Each obligation has a collaborator, a value (in the smallest currency unit), an award type (commission, bonus, etc.), and a status. Obligations start in draft status.

When a conversion is approved, the MarkObligationsAsPending listener transitions the obligation from draft to pending. Pending obligations are eligible for fulfillment and payout. This two-step status progression (draft then pending) gives admins a review window before obligations become payable.

On the transaction side, TransactionCreateRequested fires before a transaction is written to the database. This is a mutable event that lets listeners add, remove, or transform transaction details before creation. After the transaction is persisted, TransactionCreated fires for logging, analytics, and external system syncing.

Stage 6: Fulfillment and payout

The final stage compiles pending obligations into concrete payments.

FulfillmentCreated Payout batch initiated
PayoutCreated Disbursement line item built
PayoutPaid Collaborator receives payment

A fulfillment is a batch operation that groups pending obligations for disbursement. Within a fulfillment, the system creates one payout per collaborator, aggregating all their pending obligations into a single payment amount. FulfillmentCreated fires when the batch begins, and FulfillmentStatusChanged fires as it moves through its lifecycle (pending, processing, completed).

PayoutCreated fires for each individual collaborator payment. PayoutPaid is the terminal event: the collaborator has been paid. When a payout is marked as paid, the associated obligations transition to fulfilled status and the payout ID is written back to each obligation record.

How distributions work differently

Distributions are a separate pipeline for scheduled, metric-based rewards. Instead of reacting to individual sales, distributions accumulate performance metrics over time and periodically award collaborators based on aggregate performance.

DistributionHeartbeat Scheduled trigger fires
DistributionCompleted Reward pool calculated
AllocationCompleted Each collaborator's share determined

DistributionHeartbeatInitialized fires on a regular interval. The system queries for distributions whose trigger date has passed, calculates the reward pool, determines each qualifying collaborator’s share based on accumulated metrics, and creates allocation records. Each allocation produces an obligation that enters the same fulfillment pipeline as conversion-based obligations.

The key difference is timing and basis. The sale pipeline creates obligations in real-time from individual transactions. The distribution pipeline creates obligations on a schedule from aggregated performance data. Both converge at the fulfillment and payout stage.

Metrics accumulate continuously between distribution periods. MetricsTriggered fires when new metric data is recorded, with different trigger strategies producing metrics from different sources (sales, site visits, custom events). See the Distribution Events reference for details.

How data threads through the pipeline

Understanding which IDs connect the stages is critical for debugging and extension development.

The opportunity ID is the anchor. It is created in stage 1 and referenced by every subsequent event through the pipeline. If you are debugging why a collaborator did not get credited for a sale, the opportunity ID is where you start.

The engagement ID connects a collaborator and program to an opportunity. Conversions reference the engagement that triggered them, so the engagement ID tells you which collaborator-program combination earned credit.

The transaction ID is optional and only exists when the commerce event included financial details (sales and renewals, not leads). Conversions reference the transaction, and approving the transaction approves its conversions.

The obligation ID is written to both the conversion record and the payout record, making it the link between “what was earned” and “what was paid.”

Where to go from here

Each stage has its own detailed event reference with payload documentation, listener details, and code examples:

For a general introduction to how events work in Siren (listening patterns, the HasListeners interface, direct attachment), see the Events Introduction.