Building your first Adaptive Journey
This guide walks you from zero to a published, measured journey in about 10 minutes. We'll start from a template, customize one step, ship it to production, and watch the calibrated-impact panel light up.
Prerequisites
- An Apex workspace (publish limits are lifted while pricing is reworked — any workspace can publish unlimited journeys for now).
- The Apex SDK installed and sending events (
apex.track('user.signed_up', { ... })). - At least one active marketing communication in
/dashboard/communications. If you don't have one yet, click "Create new communication" from the Lifecycle Messages card and pick the Email channel.
If you haven't sent any events yet, the Quickstart gets the SDK live in two minutes.
Step 1 — Pick a template
Open /dashboard/communications/journeys/templates. Five starter templates ship with every workspace:
| Template | Use it for | Channels |
|---|---|---|
| Activation Onboarding | Welcome → engage in the first 7 days | Email + In-app + Mobile push |
| Trial Conversion | T-7d / T-3d / T-0 nudges before trial expires | Email + In-app |
| Renewal QBR | 30-day window before subscription renews | |
| Expansion Nudge | Detected upgrade signal → tier-up CTA | Email + In-app |
| Win-back | 30 days after cancel |
Click "Use template" on Activation Onboarding. Apex clones the template into a draft journey under your workspace; the canvas opens automatically.
Step 2 — Customize the canvas
The journey detail page splits into three parts:
- Canvas (left, takes most of the viewport) — the journey graph. Drag nodes to reposition, click to select.
- Step config drawer (right) — slides out when you click a step.
- Info sidebar (toggleable) — name, description, audience, goal event, audit timeline.
The Activation Onboarding template gives you 6 steps:
- Trigger:
user.signed_up - Send (email): welcome
- Wait 3 days
- Branch (condition): "did they activate?"
- Send (email): re-engagement (if no)
- Exit
Click step 2 (the welcome send). In the drawer:
- Communication dropdown — pick your welcome marketing comm. Subject + body + CTA preview as a thumbnail card below the picker.
- Channels — leave email checked.
Click step 4 (the branch). The branch is in conditional mode — Apex routes based on whether the activation event fired. To switch it to an adaptive branch (Thompson sampling), toggle the mode in the drawer; you'll be asked to define arms with their own next-step pointers. Conditional is fine for your first journey.
Hit Save in the toolbar. The dirty badge clears.
Step 3 — Set a goal event
Open the Info sidebar (the "Info" button in the toolbar). At the bottom, set:
- Optimization goal — the event name that counts as success. For Activation Onboarding, this is usually
user.activatedor your equivalent (the event your scoring system says completes onboarding). - Attribution window — how long after journey entry the goal counts. Default 7 days. Inherits from
/dashboard/settings/journeysif unset.
Save. The goal event is what calibrated impact will measure lift on.
Step 4 — Dry-run before publish
In the canvas toolbar, click Dry run. The Dry-run panel slides in:
- Pick a real end-user (search by email or pick from "recent users").
- Click Run simulation. Apex traces the journey step-by-step against that user's actual attributes — no sends fire.
- The trace shows every step with the eligibility decisions (sent / skipped / blocked-with-reason) and renders the templated body so you can confirm
{{firstName}}resolves correctly.
If you want to test a path that's blocked by opt-outs or holdout — and you're a workspace owner — toggle the owner overrides at the top of the panel. Every override emits a dry-run-override-applied audit event so the bypass is auditable.
If the trace looks right, dismiss the panel.
Step 5 — Publish
Click Publish in the toolbar. Apex:
- Validates every send step references a
marketingcommunication (transactional comms are refused at publish time per CAN-SPAM / GDPR regulatory gating). - Checks your workspace tier's
maxJourneyslimit (Free=1, Starter=5, Pro=25, Growth+=∞). - Writes an immutable
JOURNEY#<id>#v<n>record + advances thelatestpointer with a conditional write (concurrent-publish-safe). - Returns a 200; the canvas swaps from editor mode to read-only viewer.
The journey is now live. Inbound user.signed_up events will trigger executions immediately.
Step 6 — Watch it work
Three panels update in real time:
Live executions
Shows the last 50 executions with status (running / succeeded / failed / timed-out) and a deep link to the Step Functions console for full execution history. New executions appear within ~1s of trigger.
Branch performance
For every adaptive branch, shows per-arm reach + goal rate + 95% credible intervals. As traffic accumulates, Thompson sampling shifts allocation toward the higher-rate arm. The display honors a min-sample floor of 200 per arm before drawing strong conclusions.
Calibrated impact
Shows triggered (exposed) vs triggered (holdout) and converted (exposed) vs converted (holdout) cohorts. Lift is the formula (exposed_rate / holdout_rate) - 1. The daily-lift sparkline (last 30 days) gives you a trend overlay. Honest "underpowered" messaging shows when n < 100 per cohort.
The first 24-48h of data are noisy. Lift becomes meaningful once you have at least a few hundred subjects through the journey.
What's next
- Customize other steps. The Activation Onboarding template has a re-engagement send at step 5 — replace its comm with a real one.
- Set up the Webhook destination registry if you want to call external systems (Slack, Hubspot, Stripe billing) from journey steps.
- Adjust holdout & cap settings for the workspace defaults.
- When something looks off, see the Debugging journeys guide.
Related concepts
- Adaptive Journeys — the system at a glance
- Adaptive Branches — Thompson sampling reference
- Journey Audiences — predicate language
- Calibrated Impact — measurement methodology
- Global Holdout — why some sends are deliberately skipped