Branching
Branching tiles split a journey into multiple paths, letting you personalize the customer experience based on their attributes, behavior, or randomization. This page covers all branching strategies available in SignalSmith journeys.
Branch Types
SignalSmith supports three types of branches:
| Type | Use Case | Deterministic? |
|---|---|---|
| Condition | Route based on traits, events, or audience membership | Yes — same data produces the same path |
| Percentage Split | A/B testing and holdout groups | Yes — same customer ID always takes the same branch |
| Random | Equal distribution across N paths | Yes — uses customer ID for consistent assignment |
Condition Branches
Condition branches evaluate one or more rules and route the customer to the first matching branch. An else branch handles customers who match no conditions.
How Conditions Are Evaluated
Conditions are evaluated top-to-bottom at the moment the customer reaches the branch tile. The customer takes the first branch whose condition evaluates to true.
Branch Tile
├── Condition 1: lifetime_value > 500 → VIP Path
├── Condition 2: lifetime_value > 100 → Standard Path
└── Else (default) → Nurture PathIf a customer has a lifetime value of 300, they match Condition 2 and take the Standard Path. If their lifetime value is 600, they match Condition 1 and take the VIP Path. If their lifetime value is 50, they match neither and take the Else path.
Condition Types
Trait-Based Conditions
Evaluate a customer’s trait values using comparison operators:
| Operator | Description | Example |
|---|---|---|
equals | Exact match | plan = "enterprise" |
not_equals | Not equal | status != "churned" |
greater_than | Numeric greater than | lifetime_value > 500 |
less_than | Numeric less than | days_since_signup < 30 |
greater_than_or_equal | Numeric >= | engagement_score >= 80 |
less_than_or_equal | Numeric <= | support_tickets <= 2 |
contains | String contains | email contains "@company.com" |
not_contains | String does not contain | email not_contains "test" |
starts_with | String prefix match | name starts_with "Dr." |
is_set | Trait has a value (not null) | phone is_set |
is_not_set | Trait is null or missing | phone is_not_set |
in | Value is in a list | country in ["US", "CA", "UK"] |
not_in | Value is not in a list | country not_in ["CN", "RU"] |
Event-Based Conditions
Evaluate whether a customer has performed a specific event within a time window:
- Has performed —
performed "purchase" in last 7 days - Has not performed —
not performed "login" in last 30 days - Event count —
count of "page_view" in last 24 hours > 5 - Event property —
last "purchase" where amount > 100
Event conditions query the events store in real time at the moment of evaluation.
Audience-Based Conditions
Check whether a customer is a member of a specific audience:
- Is member of — Customer is currently in the audience
- Is not member of — Customer is not currently in the audience
This is useful for cross-referencing journey members against other segments (e.g., “Is this customer also in the ‘Enterprise Accounts’ audience?”).
Compound Conditions
You can combine multiple conditions within a single branch using AND/OR logic:
Branch 1: (lifetime_value > 500) AND (country in ["US", "CA"])
Branch 2: (lifetime_value > 500) AND (country NOT in ["US", "CA"])
Else: default pathNested groups are supported for complex logic:
Branch 1: (plan = "enterprise") OR ((lifetime_value > 1000) AND (tenure_months > 12))Percentage Splits
Percentage splits randomly assign customers to branches based on specified allocations. This is the primary mechanism for A/B testing within journeys.
Configuration
Define two or more branches, each with a percentage:
| Branch | Percentage | Use |
|---|---|---|
| Branch A | 80% | New email template |
| Branch B | 20% | Control (existing template) |
Percentages must sum to exactly 100%. You can define up to 10 branches.
How Assignment Works
Customer assignment is deterministic based on a hash of the customer ID and the branch tile ID. This means:
- The same customer always takes the same branch, even if the journey is paused and resumed
- If a customer re-enters the journey, they take the same branch again
- Different branch tiles produce independent assignments (a customer in branch A of one split may be in branch B of another)
This determinism is important for A/B test integrity — you don’t want the same customer receiving both the test and control treatments.
Best Practices for A/B Testing
- Use a control group — Always include a holdout group that receives the existing treatment for comparison
- Track conversion per branch — Use different exit labels per branch to measure performance
- Run for statistical significance — Allow enough customers through each branch before drawing conclusions
- Avoid nesting percentage splits — Nested splits create complex interactions. Use a single multi-way split instead.
Time-Based Branches
Time-based branches route customers based on temporal conditions. While not a separate tile type, these are condition branches that use time-related traits or expressions.
Day of Week
Route customers based on the current day:
Branch 1: day_of_week in ["Saturday", "Sunday"] → Weekend messaging
Else: Weekday messagingTime of Day
Route based on the customer’s local time (if timezone is available):
Branch 1: local_hour >= 9 AND local_hour < 17 → Business hours
Branch 2: local_hour >= 17 AND local_hour < 22 → Evening
Else: Overnight (perhaps skip or wait)Relative Timing
Route based on how long the customer has been in the journey or since a specific event:
Branch 1: hours_since_entry < 24 → Fast responder
Else: Slow responderMulti-Level Branching
You can chain branches to create decision trees:
Entry
└── Branch (Country)
├── US
│ └── Branch (LTV)
│ ├── High → VIP US treatment
│ └── Low → Standard US treatment
├── EU
│ └── Branch (GDPR consent)
│ ├── Consented → EU marketing
│ └── Not consented → EU minimal
└── Else
└── Global default treatmentWhile powerful, deep nesting makes journeys harder to understand and maintain. Consider using sub-journeys to encapsulate complex branch trees.
Branch Analytics
Each branch tracks:
| Metric | Description |
|---|---|
| Customers entered | Total customers who took this branch |
| Percentage actual | Actual distribution (may differ slightly from configured percentage for small samples) |
| Conversion rate | Percentage of customers who reached a “converted” exit tile |
| Average time | Average time customers spend in this branch before exiting |
| Drop-off | Number of customers who exited via timeout or exit criteria rather than completing the branch |
These metrics are available in the Execution & Monitoring dashboard and can be exported for deeper analysis.
Common Patterns
Win-Back with Escalation
Branch (Days inactive)
├── 7-14 days → Gentle reminder email
├── 14-30 days → Stronger re-engagement with incentive
├── 30-60 days → Final attempt with large discount
└── 60+ days → Mark as churned, exitChannel Preference Routing
Branch (Preferred channel)
├── Email → Send email
├── SMS → Send SMS
├── Push → Send push notification
└── Else → Send email (default)Geographic Personalization
Branch (Region)
├── North America → English content, USD pricing
├── Europe → Localized content, EUR pricing, GDPR-compliant
├── APAC → Localized content, time-zone adjusted sending
└── Else → Global default content