← StrategyJourney 3 campaign brief
Journey 3, Engineering briefPack version: 14 Oct 2026, 09:01 (London)
Leave feedback
The Engineering brief

What Journey 3 needs, and who owns it: the funnel event package, none of it gating phase 1

🔧 Open the marketing to engineering board
The board is the system of record: live rows, owners, status, and each row's today-vs-to-be.
The hard rules: one funnel nudge per session, deepest step wins; two touches per episode, then silence; replace, never stack. Any bid, purchase or new funnel session exits the episode instantly. No recovery sends from this journey while the legacy abandonment pushes still fire on the same cohort, and one owner per customer: a live bid means the live-auction journey owns them.
1The requirements

No send in this journey is fired natively by the app itself, so there is no native-to-Braze migration roster here: everything that sends today already lives in the messaging platform or an external one, and each row’s call sits on the As-is tab.

13 rows: 10 data points and 3 computed traits (Analytics builds, no engineering hours). The D badge is the walkthrough pin number. Delivery fixes and app defects follow in their own sections.

Events, feeds and data points

The funnel event package: what already exists of each, and what is left to build. None of it gates phase 1, which ships copy in the flow plus a next-day batch recovery on data that already lands in the warehouse. Each row is the contract: what fires, what it carries, who reads it.

The data pointWhat exists todayThe workWhat it must carryPhase · status · depends on
D5Dwell and cancel events on the price view
price_view_dwell · price_view_cancel, real time
Build the events after Analytics defines the dwell threshold that separates hesitation from reading.
DOES NOT EXIST YET
Do not exist.
New app eventsThe in-session price-view check: a true comparison for this route before the customer leaves. Firing on readers rather than hesitators is the failure the threshold definition exists to prevent.
Used where: The price-view check
PHASE 2
gated
Blocked on the threshold definition
Analytics defines dwell thresholds per screen first.
PAUSED 5 OCT 2026 · No longer a requirement for now. Journey 3 makes no change at the confirm screen and sends no message when a customer leaves it, so nothing needs this event. Do not scope or build it.
D6The confirm-abandon event, bid and Buy Now separated
confirm_abandon, real time
First check whether review_and_bid carries the amount and the auction; build confirm_abandon only for what is missing, with the bid and Buy Now confirm screens separated for the first time.
DOES NOT EXIST YET
No event records the abandon. The bid confirm screen already sends review_and_bid daily; if it carries the amount and the auction, the abandon may be readable without a new event.
New app eventThe last-step recovery test and the diagnostic's raw material. The two confirm screens are not separated in the data today, so even the abandon count is assumed.
Used where: The last-step check and its recovery test
PHASE 2
gated
Paused, 5 Oct 2026
Analytics designs the diagnostic that reads it.
D9The dead-end reason at fire time
dead_end_reason: too-early · not-covered · covered-no-auction · cabin-miss
Carry the reason on the dead-end render event, so the screen can say the truth per case.
DOES NOT EXIST YET
The split does not exist.
New event propertyThe honest dead-end copy and the right capture. An Avanti cabin miss must never be labelled not covered; without the split, one generic message is the honest interim.
Used where: The dead-end answer
PHASE 2
gated
Queued
Nothing: the states are known at render.
D10Route Watch triggers and registrations
auction_alert_requested (live) · watch_removed · window_open · coverage_live
Confirm that alert requests (auction_alert_requested) land in the warehouse, add watch_removed, and build the coverage-live supply event. The window-open re-timing itself is Braze work on the existing matched-alert event and needs nothing here.
PARTLY LIVE IN BRAZE
Alert requested (auction_alert_requested) reaches Braze daily and matches land in the warehouse. Nothing records a watch removed; the warehouse copy of requests is unconfirmed; there is no coverage event.
Event plumbingThe alert engine: fire on supply, not a morning batch.
Used where: The dead-end capture and the watch-set exit
PHASE 2
gated
Queued
Nothing.
D7Lead state on bid placed
lead_state on the bid event
Carry whether the bid entered the lead, for the signed consent ladder's outcome branch.
DOES NOT EXIST YET
Not carried.
Event propertyThe post-bid in-lead and outbid states the signed shared row branches on. Verified not carried by the bid event today.
Used where: The post-bid consent ladder, at the exit to the live-auction journey
PHASE 2
gated
Owned by the signed shared row
The signed Journey 1 rows.
D3The journey-ownership flag
journey_state, campaign-written
Nothing to build for entry; the broadcast stand-down wiring makes the flag readable by batch sends.
DOES NOT EXIST YET
Does not exist in the warehouse; the campaign writes it.
Braze configurationOne owner per customer: the spine admits only unowned customers and stands broadcasts down during an episode. The flag is campaign-written, so batch sends cannot exclude on it until the stand-down segment is wired. An open P1 decision gates the spine's launch on it.
Used where: Entry, the recovery spine, the day-7 hand-back
PHASE 1
ships now
Wiring at build; the ruling is on the morning agenda
The recovery-owner ruling.
D4The episode record
episode: deepest step, opened_at, touches_used, auction_id, close_at (checked when each touch sends: a closed auction or a departed train stops it)
Nothing: the canvas writes and reads it. Stated so the contract exists once.
CAMPAIGN-OWNED
Written by the canvas at build.
No workDeepest-step upgrade in place and the two-touch cap, enforced in the canvas, never by goodwill.
Used where: The message pick and the second touch
PHASE 1
ships now
Canvas build
Nothing.
D8Consent, read at send time
push permission + subscription state, from the sender's own record
Read consent from the sending platform's state at trigger time; the warehouse copy is three months stale and records consent, not deliverable reach. The consent write-back (transactional and marketing layers tracked separately, pin D12) is the signed rows' engineering requirement.
EXISTS, PIPELINE STALE
Braze holds current state; the warehouse copy lags.
Braze configuration + the signed write-backChannel choice on every send and the capture asks. A named launch gate for the spine.
Used where: The permission ask and the channel pick on both touches
PHASE 1
ships now
Configuration at build
The signed consent-ladder rows for the write-back half.
D13The search event package (abandoned search)
auction_results_returned (live) · result_opened · results_exit, real time to Braze and to the warehouse
Extend auction_results_returned so every search, from every entry point (the newer Home search included), carries origin, destination, travel date, party size, results count, the lowest opening bid and the walk-up fare shown, a session id and a timestamp; add result_opened (which auction) and results_exit (dwell seconds). Board row: ACTIVATE · Search events: extend auction_results_returned, add result_opened and results_exit (recPr3zDAFp70cytF).
PARTLY LIVE IN BRAZE
Search results returned (auction_results_returned) reaches Braze daily; what it carries is not yet checked. Nothing records a result opened or the results left.
An event payload and two new app events; the warehouse copy for the next-day armThe abandoned-search recovery (row 7b): entry, personalisation, the searched-date-passed fallback, the unaided-return curve, the depth and frequency ranking
Used where: Row 7b, and rows 1 and 2 on the results screen
PHASE 2
gated
Ruled 6 Sep 2026 (J3-01 to J3-04); the next-day arm ships on warehouse data first
Analytics measures the unaided-return curve before the arms are sized.
D14The results deep link with the search restored
deep link: origin, destination, date, party size → results screen, search re-run
A deep-link route that carries the searched route, date and party, re-runs the search and opens the results; where the searched date has passed it lands on the route with the next available date. Board row: ACTIVATE · Results deep link with the search restored (recva0gFBgqT8WZdY).
DOES NOT EXIST YET
The app creates nothing for a results-only search; a tap can only open the app.
New app route, iOS and Android; the AppsFlyer email fix for email tapsEvery abandoned-search push and email lands where the customer left
Used where: Row 7b
PHASE 2
gated
Ruled 6 Sep 2026 (J3-05)
The AppsFlyer OneLink fix (boarded).
▸ The 3 computed traits this journey reads: Analytics builds them, no engineering hours; and what is not listed, and why

Computed traits this journey reads · Analytics builds, no engineering hours

Named here so the full picture is one table. The contract is the row: what each trait computes, what reaches the sender today, and what remains to build.

The computed traitWhat exists todayThe workWhat it must carryPhase · status · depends on
D1The never-bid against bid-before flag
bid_behaviour, nightly
Compute nightly from warehouse auction history and add to the daily sync payload.
BUILDABLE TODAY
Derivable daily; not in the sync payload.
One computed traitThe bid card's fork (never bid, bid before, power user), used on the bid screen only; the recovery sends the same answers to everyone. The degrade path is the never-bid copy, which is the safe default.
Used where: The bid screen and the recovery message
PHASE 1
ships now
With Analytics
The CDI payload extension above.
D2The power band
rfm_segment = "Power user", nightly sync
None outstanding: the Analytics recency, frequency and value segmentation is live in Braze as rfm_segment (delivered 27 Aug 2026, verified in production 31 Aug).
LIVE IN BRAZE
Live in Braze. The legacy £500 flag matched roughly a tenth of the band and is retired.
Sync payload extensionSuppression from every hesitation treatment and every recovery send; the standard screens still serve the band.
Used where: Every hesitation surface and the whole spine
PHASE 1
ships now
Done (Analytics); the suppression is ruled
Nothing.
D11The comparison figures: walk-up, from-bid, winning-bid band; the saved amount waits on the saved-bid store
route_walkup · route_from_bid · winning_band, nightly computed (last_bid waits on the saved-bid store)
Compute nightly from what actually happened on the route, on the standing pattern: never a live lookup, never an up-to claim. Analytics sets the band's window and the minimum number of winning bids behind it; below that the band is blank and the no-band copy sends. A missing figure drops its line to the designed fallback.
DOES NOT EXIST YET
Computable from warehouse data; not built.
Computed traits, Analytics-ownedEvery true figure in the journey: the results comparison, the bid screen's and the recovery's winning-bid band. The saved amount (last_bid) waits on the saved-bid store: no message mentions a saved amount until it is built. The standing pattern from the first-slip and post-trip journeys applies: nightly computed attributes through the Braze CDI, no backend dependency.
Used where: The landing answer, the bid screen, the recovery message
PHASE 1
ships now
With Analytics
The CDI payload extension above; substantiation of the walk-up source.

Not listed because there is nothing to build: the funnel step events themselves (live in the analytics stream; the warehouse batch trigger rides them today), and the episode record the canvas writes and reads itself.

Five changes the customer never sees: what is broken today, the fix we are asking Engineering for, and why it belongs in this journey rather than a general engineering backlog. None is a comm and none needs a decision from Marketing. Each one either loses a message this journey depends on, or decides whether something else can be built at all.

2Four delivery fixes

Three plumbing questions, none of them a new surface: a sync-payload extension on the standing Braze CDI pattern, alert registrations landing in the warehouse, and confirmation of which funnel events already stream to the sender.

The delivery fixThe fix we are asking forWho does itPhase
The journey ownership flag (journey_state): the shared buildBuild journey_state once, estate-wide: one attribute carrying the owning journey, the episode id and the entry time. Every owning canvas writes it at entry and clears it at exit; every broadcast and wave segment excludes on it; it is mirrored nightly to the warehouse and readable at render by the home surface. The Braze developer wires the canvases and the exclusion segments, Engineering mirrors it to the warehouse and exposes the render read, Analytics keeps the state history. One board row carries it for all ten journeys.BACKEND ENGPHASE 1
ships now
▸ The problem today, and why it sits here
The problem today
Every journey's stand-down and hand-off assumes one owner per customer, and the flag those rules read is campaign-written today: invisible to broadcast segments, the warehouse and the app, so the rule cannot be enforced. Two live journeys can reach one customer in one week with clashing messages.
Why it sits in this journey
Here it marks the recovery episode so batch sends filter on it and the owner ruling can be enforced.
The Braze CDI route for the two selection traitsAdd both attributes to the daily Snowflake-to-Braze sync on the standing pattern: Analytics compute and pipe them from their side, Engineering only if the CDI mapping needs registering.BACKEND ENGPHASE 1
ships now
▸ The problem today, and why it sits here
The problem today
The never-bid flag and the winning-bid band are computable nightly from warehouse data Analytics already hold; neither is in the sync payload today.
Why it sits in this journey
Every personalised line rides these figures. The standing pattern (the Braze CDI is the engineering-free route for warehouse attributes) says Engineering's involvement is likely zero.
Alert registrations into the warehouseConfirm they land in the warehouse; if not, land them beside the matches, so the segment and the opt-in read both exist.BACKEND ENGPHASE 2
gated
▸ The problem today, and why it sits here
The problem today
Alert requests (auction_alert_requested) reach Braze daily, but whether they land in the warehouse beside the matches is unconfirmed, so a has-an-active-alert segment cannot be counted and the alert engine cannot be sized.
Why it sits in this journey
The dead-end recovery is the watch; today we cannot even count who holds one.
Which funnel events already reach the senderConfirm the coverage against the step set this journey's phase 2 triggers need, before any real-time trigger is designed.BACKEND ENGPHASE 2
gated
▸ The problem today, and why it sits here
The problem today
Some mobile funnel events already stream into Braze (fare selection, review-and-bid, upgrade-now start among them) but no live send enters on any of them, and whether the exact step set is covered is unconfirmed.
Why it sits in this journey
The pipes may already exist unused; confirming beats building.
3One defect in the app itself

One shared instrumentation gap. It does not block launch; it blocks reading the one in-app surface the no-channel cohort depends on.

The defectThe fix we are asking for
Content-card impressions and clicks do not registerFix the shared content-card instrumentation so impressions and clicks register.
▸ The problem today, and why it matters here
The problem today
The estate-wide instrumentation gap: content-card impressions and clicks register zero in the warehouse, confirmed. Journey 3 sends no card: a customer with no consented channel gets no send (nothing is added to Home, 29 Sep 2026).
Why it matters here
Most funnel abandoners hold no marketing channel; until this lands, the only surface that reaches them runs blind.

Source: the 20 Aug 2026 data-availability sweep in the journey spec, the pins record (warehouse audit 20 Aug, states carried forward), and the comms estate record. Nothing lands on the sprint board from this pack; the board rows are raised from these contracts once sized.

Working detailPack version: 14 Oct 2026, 09:01 (London)