Next-Best-Action Marketing
From 'should we act' to 'which action, specifically'
Propensity models and RFM segments answer 'is this customer likely to respond' or 'which bucket does this customer fall into.' Next-best-action (NBA) systems go a step further: for a given customer, at a given moment, they decide which specific action — among a defined set of candidate actions (an offer, a piece of content, a channel, a message, or sometimes 'no action') — is predicted to produce the best outcome right now. This reframes marketing decisioning from segment-level campaign targeting into per-individual, context-aware decisioning, evaluated continuously rather than at a fixed campaign-planning cadence.
The architecture: candidate generation, scoring, and arbitration
A working NBA system has three stages. Candidate generation narrows the full universe of possible actions down to those actually eligible for this customer right now (business rules: don't offer a discount to someone who already redeemed one this month, don't recommend an out-of-stock product). Scoring predicts the expected value of each remaining candidate for this specific customer — often using uplift modeling (predicted incremental effect of the action, not just predicted baseline propensity) rather than a plain propensity score, since the goal is the *marginal* benefit of taking the action, not just whether the customer is generally likely to convert regardless. Arbitration picks the winning action, applying business constraints (frequency capping across channels, budget limits, legal/compliance rules) on top of the raw score.
interface CandidateAction {
actionId: string;
type: "offer" | "content" | "channel_message";
predictedUpliftScore: number; // expected incremental value, not raw propensity
costToExecute: number;
}
interface ArbitrationConstraints {
maxActionsPerWeek: number;
actionsAlreadyTakenThisWeek: number;
excludedActionIds: Set<string>; // e.g. compliance or recent-redemption exclusions
}
function selectNextBestAction(
candidates: CandidateAction[],
constraints: ArbitrationConstraints
): CandidateAction | null {
if (constraints.actionsAlreadyTakenThisWeek >= constraints.maxActionsPerWeek) {
return null; // frequency cap reached - no action this cycle
}
const eligible = candidates.filter(
(c) => !constraints.excludedActionIds.has(c.actionId)
);
if (eligible.length === 0) return null;
// Rank by uplift net of cost, not raw predicted propensity.
return eligible.reduce((best, current) =>
current.predictedUpliftScore - current.costToExecute >
best.predictedUpliftScore - best.costToExecute
? current
: best
);
}Uplift modeling, not propensity, is the correct scoring foundation
Propensity scoring vs. uplift modeling for action selection
| Dimension | Propensity scoring | Uplift modeling |
|---|---|---|
| What it estimates | P(convert), regardless of whether action was taken | P(convert | action) - P(convert | no action) |
| Risk if misused for targeting | Targets people who'd convert anyway, wasting incentive spend | Correctly targets people the action actually moves |
| Training data requirement | Historical conversion outcomes | Requires a randomized treatment/control group to isolate causal effect |
| Typical use | Lead prioritization, general ranking | Deciding whether an incentive/action is worth the cost for this individual |
NBA systems need hard governance rails, not just good models
What's Next?
A single next-best-action decision is useful in isolation, but the real operational leverage comes from wiring many such decisions together into a persistent, continuously running decisioning engine that governs an entire customer relationship over time.
I build these systems professionally.
Whether it's a RAG pipeline, analytics migration, or AI workflow — let's talk.