Add next best action to journeys you already run in Braze
Per-customer arbitration written into the canvases your team already operates.
The short answer
Next best action inside Braze means Markin decides which single action each customer should receive, writes that decision onto the profile as an attribute, and lets your existing canvases branch on it. Braze keeps delivery, frequency capping and consent. Markin supplies the choice and reads it against a holdout.
Last reviewed 2026-09-10
Who this applies to, and who it must not reach
Eligible
- Customers reachable on at least one Braze channel with valid consent.
- At least two competing actions the business would genuinely be willing to send.
- A canvas or campaign that can branch on a custom attribute.
Excluded
- Customers under an active frequency cap or quiet-hours rule. Braze enforces this, not Markin.
- Transactional and regulatory messages, which must never be arbitrated.
- Holdout members, who continue to receive the existing programme unchanged.
The minimum data, and where it normally comes from
| What is needed | Usual source |
|---|---|
| Profiles, attributes and subscription state | Braze |
| Message exposure and engagement history | Braze Currents into the warehouse |
| Revenue, plan and order history | Warehouse or billing system |
| Product behaviour | Product analytics or event tables |
| Consent and identity resolution | CDP, where one is in use |
Step by step
How the decision runs
- 01Your team
Define the action set
List the actions that already exist in Braze, plus the ones you would run if you had a reason to. Arbitration is only meaningful when the alternatives are real.
- 02Markin
Estimate expected value per customer per action
Each candidate action is valued for each customer on expected incremental margin, not on propensity to click.
- 03Markin
Arbitrate to one decision
One action wins per customer per window, with the losing candidates and the reason recorded so the choice can be audited later.
- 04Markin
Write the decision to the profile
The chosen action, its reason and its decision ID are written to Braze as custom attributes. Latency is your sync interval.
- 05Your stack
Branch the canvas on the attribute
Existing canvases add a branch per action. Templates, localisation, send-time optimisation and capping stay exactly where they are.
- 06Markin
Return exposure and read the holdout
Currents flows exposure back keyed to the decision ID, so every action is read against the randomised control instead of against last month.
Measurement
How you know whether it worked
- Holdout
- A global randomised holdout that keeps receiving the pre-existing programme, so the read is arbitration versus business as usual.
- Window
- Eight to twelve weeks. Shorter reads capture novelty, not lift.
- Primary result
- Incremental revenue per reachable customer against the holdout.
Guardrails
- Unsubscribe and complaint rate.
- Message volume per customer, which should not rise.
- Cannibalisation of actions that were already working.
- Share of customers where no action clears the value bar.
Illustrative only
A worked example
Illustrative shape of a first deployment, to show what is decided where.
| Reachable customers per week | 600,000 |
|---|---|
| Candidate actions in the set | 7, plus 'no action' |
| Decided by Markin | Which one, for whom, and why |
| Decided by Braze | When it sends, on which channel, under which cap |
| Holdout | Randomised, receives the existing programme |
| Read | Incremental revenue per reachable customer over 12 weeks |
Nothing about the canvas library is rebuilt. The branch is the only structural change.
Run it on your own numbers
The arithmetic, spelled out
Holdout size is the constraint people get wrong, not the model. For a two-sided test at 95% confidence and 80% power on a revenue-per-customer metric, n per group is approximately 16 x (standard deviation / minimum detectable effect) squared.
| Input | Value |
|---|---|
| Reachable customers per week | 600,000 |
| Baseline revenue per reachable customer per 12 weeks | $18.00 |
| Standard deviation of that figure | $54.00 (three times the mean, typical for skewed revenue) |
| Minimum detectable effect you care about | 2% of $18.00 = $0.36 |
| n per group | 16 x (54 / 0.36)^2 = 16 x 22,500 = 360,000 |
| Implied holdout as a share of the weekly reachable base | Feasible: 360,000 is well inside 600,000 accumulated over a 12 week window |
| If you only ran 50,000 customers per group | Smallest detectable effect becomes 54 x sqrt(16 / 50,000) = $0.97, or 5.4% |
A 2% revenue effect on this base needs roughly 360,000 customers per group over the window. Below about 50,000 per group, anything under a 5% effect is indistinguishable from noise, and the programme will be judged on a number the test could never have measured.
Inputs are illustrative. The point that transfers is the shape: revenue distributions are skewed, so the standard deviation is large and small holdouts cannot see realistic effects.
Timeline
How long it takes to a first measured result
- 01Week 1
Currents and warehouse connection
Braze Currents lands message and engagement events in the warehouse, and profile and subscription state is mapped. Nothing is written back yet.
- 02Week 2
Action set defined with the lifecycle team
Every action already running in Braze is listed, plus the ones the business would run given a reason, plus an explicit 'no action'.
- 03Weeks 3 to 4
Value model and arbitration
Each action is valued per customer on expected incremental margin, and the arbitration rule and its audit trail are agreed.
- 04Week 5
Attribute write-back and one canvas branched
Decisions land as custom attributes and a single canvas is branched on them. One journey first, not the whole library.
- 05Weeks 6 to 7
Rollout across the canvas library
Remaining canvases add the branch once the write-back has been observed to be stable.
- 06Weeks 13 to 17
First causal read
Eight to twelve weeks after the global holdout was fixed. Earlier reads measure novelty.
Technical detail
What is read and written, field by field
Braze
Read
- User profiles, custom attributes and subscription groups via the /users/export endpoints
- Currents event streams: message sends, opens, clicks, conversions, unsubscribes
- Canvas and campaign metadata for the action inventory
Written
- markin_next_best_action (string): the chosen action key
- markin_decision_id (string): joins exposure back to the decision
- markin_decision_reason (string): why this action won, for audit
- markin_decided_at (time) and markin_holdout (boolean)
- Written through /users/track, batched
Write hourly to daily for journey branching; for send-time or in-app decisions, a synchronous decision API call at render time instead.
Snowflake or your warehouse
Read
- Revenue, plan and order history keyed to the Braze external_id
- Product behaviour events
- Currents tables for exposure
Written
- Decision and exposure tables keyed by markin_decision_id
Continuous ingest, daily decision batch.
Segment or your CDP
Read
- Identity resolution and consent state across channels
Written
- Nothing. Identity stays where it already lives.
Read only.
Effort
What it asks of your team
| Who | How much of their time |
|---|---|
| Lifecycle or CRM manager | The main counterpart: around a day a week for the action set, the branch and the review of decisions. |
| Data engineer | Around 3 days in weeks 1 and 2 for Currents and warehouse access. |
| Marketing operations | Half a day to add the branch pattern and confirm capping is unaffected. |
| Analytics | One session to agree the primary metric and the holdout size before launch. |
What normally goes wrong
Arbitrating by propensity to open
The most clickable message is rarely the most valuable one. Ranking by engagement quietly optimises for cheap actions and flat revenue.
Rebuilding delivery inside the decision layer
Braze already handles capping, quiet hours, localisation and deliverability. Duplicating that creates two sources of truth and a governance argument you will lose.
No 'do nothing' option
Sending the best of a bad set is still a bad send. Silence must be able to win the arbitration.
Losing the decision ID
If exposure cannot be joined back to the decision, the programme produces reporting instead of evidence.
Questions this playbook answers
- How do I add next best action to Braze?
- Can Braze decide the best offer per customer?
- How do I arbitrate between competing campaigns in Braze?
- What does a decision layer add on top of Braze?
- How do I run a holdout across all Braze canvases?
Frequently asked
- Does Braze already do next best action?
- Braze orchestrates journeys extremely well and can personalise content within them. What it does not do is value every competing action per customer on expected margin and arbitrate to one. That decision layer sits above the journey, which is why the two coexist rather than compete.
- How fast does the decision reach Braze?
- Attribute write-back arrives at your sync interval, which suits daily and weekly journeys. Where a decision has to be made at the moment of the send or the screen, Markin answers a decision API call at render time instead.
- Do we have to change our canvases?
- You add a branch that reads the decision attribute. Templates, audiences, capping, localisation and send-time logic stay as they are.
- What happens if Markin returns no action?
- The canvas takes its default path, which is normally to send nothing. Being able to decide against contact is a large part of where the margin comes from.
- How do we prove it worked?
- A randomised holdout keeps receiving the previous programme for the whole measurement window, and exposure returns to Markin through Currents keyed to the decision ID. The read is a comparison between two concurrent groups, never between two time periods.
Where this connects
- PlaybookRun a retention offer before renewal without paying customers who were staying anywayPre-renewal save offers on Stripe, sized by risk instead of by list membership.
- PlaybookCross-sell a second product without cannibalising the plan the customer already pays forSecond-product offers valued on incremental margin, not on attach rate.
- PlaybookWin back lapsed customers with a silence window instead of a discount ladderReactivation timed on returning intent, not on days since last order.
- SolutionNext-Best ActionNext-best action for enterprise growth teams
- SolutionCustomer DecisioningThe decision layer between your customer data and your channels
- ComparisonBraze Decisioning Studio vs Markin: who writes the listBraze picks the best message inside Canvas. Markin picks the opportunity across marketing, product and pricing, and proves it against a holdout.