Program Groups
Program groups in Siren — data model, sorting strategies, REST API, and PHP data access for program priority resolution.
Last updated: April 9, 2026
Program Groups
A program group collects one or more programs under a shared sorting strategy. When a collaborator qualifies for multiple programs within the same group, the sorter determines which program takes priority. This lets you set up layered incentive structures. For example, a seasonal bonus program can override the default commission without worrying about double-counting.
Each group has a sorter strategy that controls how priority is resolved. The built-in strategies are oldestBindingWins (the program with the earliest engagement takes priority) and newestBindingWins (the most recently engaged program wins). The relationship between programs and groups is managed through a separate junction datastore in PHP and via extended fields in REST.
Program groups do not carry a status field, so there is no soft-delete lifecycle. Deletes are always permanent.
The program group object
| Field | REST name | PHP getter | Type | Description |
|---|---|---|---|---|
| ID | id | getId() | integer | Unique identifier |
| Name | name | getName() | string | Display name of the group |
| Description | description | getDescription() | string | Human-readable description of the group’s purpose |
| Sorter | sorter | getSorter() | string | Sorting strategy identifier (see below) |
Extended fields (REST only, via ?fields=)
These fields are resolved dynamically by the REST API field resolver system and must be explicitly requested.
| Field | Type | Description |
|---|---|---|
programIds | integer[] | Array of program IDs assigned to this group |
programs | object[] | Array of program objects with id, name, and status for each program in the group |
Sorting strategies
The sorter field controls how the system resolves priority when a collaborator matches multiple programs in the same group.
| Strategy | Behavior |
|---|---|
oldestBindingWins | The program the collaborator was bound to first takes priority |
newestBindingWins | The most recently bound program takes priority |
Accessing program group data
# List all program groups
curl -X GET "https://your-site.com/wp-json/siren/v1/program-groups?fields=id,name,sorter,programIds" \
-H "Authorization: Bearer YOUR_TOKEN"
# Get a single program group with full program details
curl -X GET "https://your-site.com/wp-json/siren/v1/program-groups/5?fields=id,name,description,sorter,programs" \
-H "Authorization: Bearer YOUR_TOKEN" use Siren\ProgramGroups\Core\Datastores\ProgramGroup\Interfaces\ProgramGroupDatastore;
class GroupManager
{
protected ProgramGroupDatastore $groups;
public function __construct(ProgramGroupDatastore $groups)
{
$this->groups = $groups;
}
public function getGroup(int $groupId): \Siren\ProgramGroups\Core\Models\ProgramGroup
{
return $this->groups->getById($groupId);
}
} use Siren\ProgramGroups\Core\Facades\ProgramGroups;
$group = ProgramGroups::getById(5);
$allGroups = ProgramGroups::andWhere([]); Siren is built on an event-driven architecture. Program groups are normally configured through the admin UI. If you need to create them programmatically (e.g., during a migration or recipe import), the datastores documented here are the right tool. The group’s sorting strategy is applied automatically during the attribution pipeline. You don’t need to invoke it manually.
PHP domain methods
The program-group junction
The relationship between programs and groups is tracked through a junction datastore. Each junction record links one program to one group. A program can belong to at most one group.
The junction model has two fields:
| Field | PHP getter | Type | Description |
|---|---|---|---|
| Program ID | getProgramId() | integer | The program’s primary key (also serves as the junction’s identity) |
| Group ID | getGroupId() | integer | The group this program belongs to |
use Siren\ProgramGroups\Core\Datastores\ProgramsProgramGroups\Interfaces\ProgramsProgramGroupsDatastore;
class GroupInspector
{
protected ProgramsProgramGroupsDatastore $junctions;
public function __construct(ProgramsProgramGroupsDatastore $junctions)
{
$this->junctions = $junctions;
}
public function getProgramsInGroup(int $groupId): array
{
return $this->junctions->getProgramsForGroup($groupId);
}
public function findGroupForProgram(int $programId): ?\Siren\ProgramGroups\Core\Models\ProgramGroup
{
return $this->junctions->getProgramGroupForProgram($programId);
}
} use Siren\ProgramGroups\Core\Facades\ProgramsProgramGroups;
// Get all programs in a group
$programs = ProgramsProgramGroups::getProgramsForGroup($groupId);
// Find which group a program belongs to (returns null if ungrouped)
$group = ProgramsProgramGroups::getProgramGroupForProgram($programId); Looking up programs in a group
getProgramsForGroup retrieves all program models that belong to a specific group. This crosses the junction boundary. It accepts a group ID but returns full Program model instances, not junction records.
use Siren\ProgramGroups\Core\Facades\ProgramsProgramGroups;
$programs = ProgramsProgramGroups::getProgramsForGroup($groupId);
foreach ($programs as $program) {
echo $program->getName() . ' (' . $program->getIncentiveType() . ')';
}
Finding a program’s group
getProgramGroupForProgram looks up the group a program belongs to. Returns null if the program is not in any group. This is useful for checking whether attribution deduplication applies to a given program.
use Siren\ProgramGroups\Core\Facades\ProgramsProgramGroups;
$group = ProgramsProgramGroups::getProgramGroupForProgram($programId);
if ($group !== null) {
echo $program->getName() . ' is in group: ' . $group->getName();
echo 'Priority strategy: ' . $group->getSorter();
} else {
echo 'This program is not in a group — no deduplication applies.';
}
Relationships
- Programs. A program group contains zero or more programs via a junction table. Each program can belong to at most one group (the
programIdis the primary key on the junction table). TheprogramsandprogramIdsextended fields expose these associations on read endpoints. - Sorting and Attribution. When a collaborator qualifies for multiple programs within the same group, the group’s
sorterstrategy determines which program takes precedence. This affects which incentive structure applies to a given conversion.
REST endpoints
See the individual endpoint pages in the sidebar for full request and response details, or browse the all REST endpoints reference.