← StrategyJourney 6 campaign brief
Journey 6, Engineering briefPack version: 15 Oct 2026, 11:47 (London)
Leave feedback
The Engineering brief

What Journey 6 asks Engineering to build, and the one hard rule

🔧 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 one hard rule: no marketing send in this journey fires unless the positive-trip gate passes at the moment of send: the trip completed, with no disruption, no downgrade and no open compensation claim, refund or dispute. The gate is its own requirement row: pin D1. Until it exists and is queryable at send time, nothing in this journey launches.
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.

16 rows: 5 data points, 6 sends moving into Braze and 5 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 data this journey needs from the trip and booking backend. The contract is the row; the surfaces that read it are listed, never restated.

The data pointWhat exists todayThe workWhat it must carryPhase · status · depends on
D11The trip-completion anchor
trip_completed; interim: schedule-derived arrival
Phase 1: nothing. Analytics derives the completion anchor from the booked trip plus timetable scheduled arrival, all data we already hold. Phase 2: emit a real-time trip_completed event (route, product, actual arrival) to make the anchor exact on the day.
BUILDABLE TODAY
Derivable from booking and timetable data already in the warehouse; no real-time event exists.
  • No phase-1 work
  • new real-time event in phase 2
The completed trip with its route, product and arrival time, so the entry clock and the ninety-minute touch are timed off the customer’s trip rather than their purchase. Scheduled vs actual arrival is the only phase-1 approximation, and the phase-2 event removes it.
Used where: Entry, and the whole spine’s clock
PHASE 2
gated
No phase-1 ask; the event is the phase-2 build
Nothing blocks phase 1: the derived anchor launches the journey.
D1The positive-trip gate
positive_trip, evaluated at send time
Phase 1: nothing for Engineering. Analytics computes the reduced gate from existing sale state: trip not cancelled, not refunded, at send time. Phase 2: the composite flag, adding per-trip disruption, downgrade, and open compensation, refund or dispute state.
BUILDABLE TODAY
Refund and cancellation state resolve per sale today; disruption is not modelled per trip.
  • Reduced gate now (Analytics)
  • composite signal in phase 2
One boolean per trip, re-evaluated at each fire time. In phase 1 a delayed trip can still receive the value proof: the copy claims only the true saving, and the holdout reads the cost. The composite adds the disruption feeds already in the warehouse; support-contact history still cannot be built (no support data in the warehouse).
Used where: The gate on every send in this journey
PHASE 2
gated
Analytics computes the phase-1 gate; the composite is the phase-2 build
Analytics signs the reduced-gate definition; nothing engineering-side blocks phase 1.
D8Survey completes
survey_completed + score
Instrument survey completion and score as an event, replacing clicks as the success measure.
DOES NOT EXIST YET
Not instrumented; click tracking is disabled template-wide so even clicks are unreadable.
New instrumentationCompletion and score per survey response, joined to the customer, streamed to the sending platform so survey quality can be read and the phase-2 positive-trip enrichment can eventually read a verified good trip.
Used where: The survey-quality read; the phase-2 positive-trip enrichment
PHASE 1
ships now
Rides the survey repair
The link verification on the defect row: verify the briefed bug before building the fix.
D10The next-trip-booked signal
next trip departure, readable at send time
Delivered: has_upcoming_trip and next_trip_date reached the Braze CDI on 27 Aug 2026, refreshed daily. Remaining ask: confirm daily latency holds for the travel-window rule; no event forwarding needed.
LIVE IN BRAZE
Verified live in the Braze CDI, 31 Aug: has_upcoming_trip and next_trip_date, daily refresh.
Delivered via the CDI; freshness confirmation onlyBooked-trip state at send time, silencing the nudge and driving the travel-window yield: relationship sends never fire from 48 hours before departure to trip completion.
Used where: The nudge’s suppression; the travel-window rule
PHASE 1
ships now
Delivered; freshness to confirm
Nothing.
D6Referral state
open reward window + referrer registration
Phase 1: nothing. The campaign tracks its own asks, as designed. Optional phase 2: Analytics lands reward-window state as a daily CDI attribute from the programme webhooks already in the warehouse; no event forwarding.
BUILDABLE TODAY
Referral activity is in the warehouse; the CDI route can carry it daily.
  • No phase-1 work
  • optional CDI attribute in phase 2
Whether this customer has an open reward window or a standing referral, from the external programme’s webhooks that already land in the warehouse. Until it lands, the campaign tracks its own asks.
Used where: The day-after slot decision
PHASE 2
gated
Campaign self-tracks; CDI attribute optional
The Marketing Ops compliance review of the ungated consent path is unchanged.

The engineering work to move native sends into Braze

No new data in this band: logic, integration and release work.

The changeThe workPhase · status · depends on
The Braze in-app channel, verified
in-app message render + the Keep-me-posted tap + content-card delivery
Verify the three things the in-app surfaces assume before any is called phase 1: the Braze in-app message channel renders on current app versions (one live example exists, the Secret Fare survey in-app); a message tap can raise the OS notification permission prompt (a push-primer deep link); and the content-card delivery path works (the live referral card has never delivered a single impression).
  • Channel verify first
  • small app builds only where a verify fails
PHASE 1
ships now
Verify with Engineering and Product
Nothing else. The out-of-app spine (push and email) does not wait on any of this.
▸ Where it stands, the detail and where it is used
Where it stands
VERIFY FIRST
One live in-app message and live content cards exist; render, tap-action and card delivery are all unverified for our use.
The detail
The app's surfaces are native; Braze reaches into the app only through the SDK's content cards and in-app messages. Where the verify passes, the mirror and the fallback card ship with no app release; where it fails, the fix is a small app build and the affected surface waits for it. The savings-proof card without the opt-in buttons ships on the render verify alone.
Used where: The value-framed opt-in on the mirror
The survey repair
seven live emails + one push
Rebuild the survey links identity-safe, repair the survey push’s dead deep link, and restore a readable success signal.
Config and template fixes on live sendsPHASE 1
ships now
Ready to brief, after the routing verification
The verify-first defect row: the cards’ universal-link claim is uncorroborated.
▸ Where it stands, the detail and where it is used
Where it stands
VERIFY FIRST
Live and sending daily, broken in the ways the delivery-fix table records.
The detail
No new data: the fixes in the delivery-fix table, shipped as one pass over the family so it ends consistent.
Used where: The day-after survey guardrail; the survey-quality read
The reward-experience fix
the external referral programme
Audit the external referral programme’s console, fix reward delivery, and add rejection reasons.
External platform integrationPHASE 1
ships now
Console audit first
Marketing Ops owns the consent-gap half of the same review.
▸ Where it stands, the detail and where it is used
Where it stands
VERIFY FIRST
Invisible to both audit halves; the live qual shows the failures.
The detail
The programme’s copy, reward values and timing captured; delivery verified end to end; every rejection carrying a reason a customer can read.
Used where: Every referral ask in the journey
The post-travel survey’s home
the code-sent Avanti survey
Decide the code-sent post-journey survey’s future: move it to Braze once the trip-completed entry exists, or retire it into the Braze rail.
  • Migration decision
  • placeholder fix either way
PHASE 2
gated
Decision queued behind the phase-1 launch
The derived-anchor entry being live.
▸ Where it stands, the detail and where it is used
Where it stands
VERIFY FIRST
Live, Avanti first-flex purchases only, working by accident.
The detail
It is the estate’s only travel-anchored send, on a clock our own backend owns. Moving it needs the entry event; retiring it loses the post-travel anchor. The broken link placeholder is fixed before any widening, whichever way this goes.
Used where: The day-after window
D12The advocacy home card, Braze-controlled
native Refer-a-Friend tile → Braze-controlled card
The native Refer-a-Friend home tile stands down and returns as a Braze-controlled card under the earned-ask gate (positive trip, open reward window, not already served; never at the win, never inside disruption). One home-card slot, priority-ordered: the opt-in value card for the unreachable first, then the earned referral, then the savings story. The deep Refer-a-Friend share screen stays native as the destination.
The marketing-tiles-to-Braze build + Braze segment priority on the one slotPHASE 2
gated
On the engineering board (the marketing-tiles row and the slot-arbitration row)
The marketing-tiles-to-Braze build; render-time reachability, reward-window and savings reads.
▸ Where it stands, the detail and where it is used
Where it stands
DOES NOT EXIST YET
A static native tile, no state awareness; the For-you content card carries the advocacy job in the interim.
The detail
Today the tile renders state-blind, including at the win and straight after a loss; the slot order is the first live instance of the next-best-action card decision.
Used where: The advocacy surface, the opt-in capture, the savings story
D14The account credit (milestone reward cells and the third-upgrade credit)
a £5, £10 or £20 account credit, issued from Braze
A mechanism to issue a fixed account credit from a Braze webhook and redeem it at the customer’s next upgrade purchase: £5 toward the third upgrade the day after a second positive trip, for customers the churn-risk score flags as unlikely to return unaided; £10 at the tenth upgrade and £20 at the twentieth for the milestone reward test cell. One build serves both.
Integration, not a mechanism build: the discount service already holds a per-customer credit ledger (credits by API with amount, reason and a duration expiry; applied at checkout). The build is the Braze webhook that issues the credit, the credit state back to Braze and the warehouse, and the checkout rules below.PHASE 2
gated
Waits on incentive cost sign-off (the signatory is to be named; not Ian by default) and the compliance view before it is briefed; the third-upgrade credit cannot ship without it
D13, the count that lands the rung or reads 2; the live churn-risk score for the third-upgrade credit; the cost sign-off and the compliance view. Recognition-only ships without it.
▸ Where it stands, the detail and where it is used
Where it stands
PARTLY LIVE IN BRAZE
The credit ledger exists in the discount service: per-customer credits by API with amount in pence, reason, a duration expiry and a Marketing category; applied at checkout on auction, upgrade now, ticketing and train swap; a customer balance endpoint; Customer Support issues credits through the admin panel (engineering documentation v3.10.3, read 28 Sep 2026). No Braze-triggered issue and no checkout rules for marketing credits exist.
The detail
The credit value, what earned it (the second upgrade by score, or the tenth or twentieth rung), the issue time, the expiry and the redemption, so each test reads its cell’s next-transaction rate and the cost per incremental upgrade against recognition-only. Credit rules (Sheran, 15 Oct 2026): one live marketing credit at a time per customer across Journeys 6, 7 and 9, with the promised £5 at the fifth upgrade outside that rule; at checkout one marketing credit per transaction, the soonest-expiring first, any other credit staying on the account with its own expiry; gift voucher balance, the customer's own money, applies alongside after the marketing credit; a credit tied to a customer event runs 60 days, a credit tied to a calendar moment runs to the moment's end date.
Used where: The third-upgrade credit (Moment 2) and the milestone moment’s reward test cell: one mechanism
▸ The 5 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 contracts live on the Analytics brief tab, which is their home.

The computed traitWhat exists todayThe workWhat it must carryPhase · status · depends on
D2The savings traits
per-trip saving + cumulative saving
Phase 1: reuse the Journey 8 workaround as delivered: total_saved (savings since January 2026, a missing figure holds the send, the proposed floor and cap), and extend the same table with the per-trip saving. Phase 2, so it is not missed: rebuild the savings history properly, so the figure is genuinely lifetime. One build, shared with the lapse journey's recognition line.
BUILDABLE TODAY
The cumulative saving is live in the Braze CDI as total_saved (verified 31 Aug; floor and cap proposed). The per-trip saving extends the same savings-table build.
Computed trait, nightlyThe saving on this trip and the running total across trips, true figures only. Until the phase-2 rebuild lands, every surface says what the figure is: savings since January 2026, never lifetime.
Used where: The value proof; the mirror; the savings tracker
PHASE 1
ships now
Half delivered; per-trip saving with Analytics, launch-blocking for the reflection copy
Nothing: buildable from existing sale data.
D3The personal cadence trait
personal median gap between purchases
Build the customer’s own median purchase gap as a shared trait: it times the nudge here and sets the lapse journey’s slip boundary at about one and a half times the median.
DOES NOT EXIST YET
Derivable from purchase history; not modelled. The fifteen-day fallback is computable in Braze from the purchase events it already receives.
Computed trait, nightly, shared with Journey 8The median gap where three or more purchases exist, falling back to the base median of about fifteen days below that. One build, two journeys, per the shared-capability register.
Used where: The nudge’s clock; the slip hand-off
PHASE 2
gated
Priority two: the fallback launches without it
The purchase-gap median reconciliation on the Analytics brief.
D7The persona label
business or leisure + confidence
Delivered: business_leisure_label syncs to the Braze CDI (leisure, business, mixed, unclassified) since 27 Aug 2026.
LIVE IN BRAZE
Verified live in the Braze CDI, 31 Aug (business_leisure_label; rfm_segment beside it).
Sync confirmation onlyTone selection only, never cadence: business and leisure purchase medians are near-identical. Low confidence routes to neutral copy. The current model classifies all but 1.7 percent of the base, superseding the stale unclassified caveat the journey cards still carry.
Used where: Copy tone on the nudge and the slot email
PHASE 1
ships now
Delivered
Nothing else.
D4The transaction count
warehouse purchase count, daily
Add the true purchase count to the CDI payload: Analytics, the same route that landed total_saved. No engineering.
BUILDABLE TODAY
Verified in the live CDI, 31 Aug: only the coarse exactly-one-purchase flag reaches Braze; no true count.
CDI payload extension, Analytics-ownedThe count no longer gates the referral ask: the ask fires from the first completed first-class trip. The count powers the guardrail read instead (referred-friend activation split by the referrer's transaction count at time of ask) and the repeat-register copy switch. The warehouse is the truth, because auction wins emit no client event and app-side counts undercount.
Used where: The referral guardrail read and the repeat-register copy switch
PHASE 1
ships now
With Analytics
Nothing: the CDI route is proven.
D13The lifetime upgrade count
lifetime_upgrade_count, in the daily sync
Add the customer’s lifetime count of First Class upgrades (auction wins and instant purchases) to the daily Braze sync payload, the same route that landed total_saved. Analytics computes it; no engineering hours.
BUILDABLE TODAY
Purchase counts exist in the warehouse user model; only a coarse exactly-one-purchase flag reaches Braze, and no upgrade-only count is modelled.
  • Computed trait, nightly
  • sync payload extended
One integer per customer, refreshed nightly, so the day-after slot can test whether this trip landed a rung (three, five, ten or twenty) and the value proof and savings story can name the next rung for customers on two to four.
Used where: The milestone moment; the ladder line on the value proof and the savings story
PHASE 1
ships now
A new trait, launch-blocking for the milestone; the ladder line ships with it
Nothing: buildable from existing sale data.

Not listed because there is nothing to build: the welcome journey's canvas flag and rated-state, both campaign-written and read (D5, D9); and the persona label, which exists and needs only the sync confirmation carried on the Analytics brief.

Eleven 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.

2Seven delivery fixes

Six of the seven are fixes and configuration rather than new events. A wording release on a live native send costs hours and ships now; a new event or feed queues behind the data it needs.

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 makes the episode cap and the reward windows visible to the broadcasts that cannot see them today.
Referral rewards that never arrive, and rejections with no reasonFix reward delivery and add a reason to every rejection, starting from a console audit of the external programme.BACKEND ENGPHASE 1
ships now
▸ The problem today, and why it sits here
The problem today
The referral programme runs on an external platform. The live support record shows successful referrers told their reward was sent by email when nothing arrives, and referrals rejected with no stated reason. The programme's own copy, reward values and timing are invisible to both audit halves.
Why it sits in this journey
Every referral ask in this journey is gated behind this fix: scaling the ask before it scales the damage. The referral stage scores negative in the sentiment record while the loyalty stage scores plus eighty.
Three survey emails send responses nobody can attributeOne identity-carrying link pattern across the whole survey family.BACKEND ENGPHASE 1
ships now
▸ The problem today, and why it sits here
The problem today
The Uber variant and both operator variants of the survey family use bare survey links with no identity parameters, so their responses cannot be joined back to a customer. The other four carry identity.
Why it sits in this journey
The survey sends is the closest thing the estate has to a positive-trip signal, and a third of it is anonymous.
Customer email addresses travel in URL query stringsCarry identity in an opaque token, never personal data in a query string.BACKEND ENGPHASE 1
ships now
▸ The problem today, and why it sits here
The problem today
The identity-carrying survey links and a tracking pixel put the customer's email address and identity into query strings to third-party survey domains: a recorded security finding.
Why it sits in this journey
A compliance exposure on live daily sends, and it rides the same rebuild as the identity fix above.
The survey push's tap has gone nowhere since FebruaryOne edit to the push action URL.BACKEND ENGPHASE 1
ships now
▸ The problem today, and why it sits here
The problem today
The Secret Fare survey push has sent daily since 25 February with a malformed deep link whose characters are not valid in a hostname, so every tap fails silently.
Why it sits in this journey
It is the only live post-trip survey push, and six months of its taps have been thrown away.
Survey success is measured in clicks a disabled tracker cannot countInstrument survey completion and score as an event the sending platform can read.BACKEND ENGPHASE 1
ships now
▸ The problem today, and why it sits here
The problem today
Click tracking is disabled template-wide on the survey family, so the near-zero click figures are an artefact of the template, and completes are not instrumented anywhere.
Why it sits in this journey
Survey quality reads on completes or it cannot be read at all, and the phase-2 positive-trip enrichment wants a verified good trip rather than an assumed one.
Only a coarse first-purchase flag reaches the sending platformExtend the daily sync payload to carry the warehouse transaction count.BACKEND ENGPHASE 1
ships now
▸ The problem today, and why it sits here
The problem today
The referral gate needs the customer's transaction count at send time; today only an exactly-one-purchase flag syncs, and auction wins emit no client event, so app-side counts undercount. The warehouse is the truth.
Why it sits in this journey
The transaction count powers the referral-quality guardrail read and the repeat-register copy switch; without it neither can run.
3Four defects in the app itself

Instrumentation and delivery defects on the survey and referral rails, all verifiable now. Each one blocks a read or a surface this journey depends on.

The defectThe fix we are asking for
The briefed survey-link bug may be the wrong bugVerify the routing claim end to end before the fix is briefed as written, so the right bug gets fixed once.
▸ The problem today, and why it matters here
The problem today
The journey cards brief a universal-link routing failure on the product survey emails as confirmed, and route a priority-zero fix off it. No artefact in the comms record corroborates that specific failure; the defects the record proves are the link and identity failures in the delivery-fix rows above.
Why it matters here
A priority-zero fix briefed against an unverified defect wastes the sprint it lands in, and survey quality stays unreadable either way until the rail reads completes.
The referral share link is hard to find in the appInvestigate the content-card delivery path, and surface the share link where an earned customer can find it.
▸ The problem today, and why it matters here
The problem today
The live support record shows customers asking where the refer-a-friend link is, and the standing in-app referral card has never delivered a single impression despite being enabled since November.
Why it matters here
The earned ask points customers at a share mechanic they currently cannot find.
Nothing records who has been asked to rateThe campaign writes rated-state and asked-this-version itself; the app exposes the rating sheet behind a working link.
▸ The problem today, and why it matters here
The problem today
No signal exists for whether a customer has rated the app or been shown the rating sheet, and the store's own prompt budget is finite. The review prompt itself is a consider-testing candidate, not proposed strategy, so this is test-enabling work, not launch work.
Why it matters here
If the review test ever runs, without this it cannot honour once per trip and once per version, and the prompt budget gets spent blind.
The dormant post-journey survey would ship a dead linkFix the placeholder before the survey is widened beyond its current scope.
▸ The problem today, and why it matters here
The problem today
The code-sent Avanti survey works by accident: the code builds a survey-link placeholder that has been broken all along, and the deployed template ignores it and hardcodes a working link. The dormant non-Avanti sibling binds the broken placeholder.
Why it matters here
This send is the estate's only travel-anchored survey and a candidate to carry the journey's post-travel anchor; widening it as-is ships a dead link.

Source: the code-sent communications audit and the Braze console pull, both 12 August 2026. Working draft, not signed, and not yet on the sprint board.

Working detailPack version: 15 Oct 2026, 11:47 (London)