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
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.”
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.
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 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.
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 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.
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.
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.
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:
- Commerce Events for sales, refunds, coupons, renewals, and leads
- Attribution Events for opportunity tracking and engagement creation
- Conversion Events for the conversion lifecycle from initialization through approval
- Payment Events for transactions, obligations, fulfillments, and payouts
- Distribution Events for the scheduled reward system
- System Events for collaborator registration, recipes, and custom events
For a general introduction to how events work in Siren (listening patterns, the HasListeners interface, direct attachment), see the Events Introduction.