Living Word Lead-Gen Phase 1B — In-Game CTA Surfaces
Canonical spec. Ships immediately after PR #559 (Phase 1A foundation) merges. All copy is verbatim from the founder-approved strategic spec (
drafts/2026-05-23-living-word-lead-gen-spec.md) and honors decisions B1/B2/B3 locked 2026-05-23. The contemplative tone of the game is the proof; these CTAs are the credits sequence around that proof, never interruptions of it. Every surface honors the AI Bridge Principle — CTAs are clearly authored-by-the-builders messaging, never voiced by an in-character NPC.
§1. Founder-locked decisions (verbatim)
From drafts/2026-05-23-living-word-founder-decisions.md, STATUS table 2026-05-23. Engineering MUST NOT re-litigate.
| # | Decision | Answer | Rationale |
|---|---|---|---|
| B1 | Domain routing for /from-living-word | Route to churchwiseai.com (conversion stays on trust brand) | as recommended |
| B2 | Early-scene CTA prominence | Hide first 2 scenes | as recommended |
| B3 | Legacy Bloom finale CTA panel | Keep the panel | as recommended |
- B1. Every CTA in Phase 1B links to the absolute URL
https://churchwiseai.com/from-living-word?...even when the player is onlivingword.bible. NO mirroring onlivingword.bible. - B2. Scene-completion bloom card is HIDDEN during the player's first 2 scene completions; first appears at the 3rd. Counter is per-browser localStorage (
lw-scene-completions-shown:cta), increments on every completion (including hidden ones), visibility check iscounter >= 3. - B3. Finale panel ships. Fades in AFTER the existing
LegacyBloomCinematicfinishes — cinematic itself is NEVER modified, shortened, or interrupted.
§2. Scope
Three in-game surfaces. Each MUST:
- Log impression + click events to
lw_lead_gen_events(Phase 1A migration2026-05-23c-lw-lead-gen-events.sql). - Use
trackLeadGenEvent()fromsrc/lib/living-word/lead-gen-client.ts(no directfetch). - Route clicks to
https://churchwiseai.com/from-living-wordwith UTM tags per §8. - Be dismissible per-session where applicable (no permanent suppression — Phase 2).
- NEVER interrupt or block gameplay; appear only at natural completion moments.
- Honor the AI Bridge Principle — never NPC-voiced, never imply the AI is recommending a purchase.
Out of scope (do NOT build): founder lead-gen dashboard (Phase 1C); A/B copy testing (Phase 2); landing-page segmentation (Phase 2); in-game email capture (anti-goal).
§3. Surface 1 — Scene-completion bloom card
When. Fires when a scene meets all three: (a) gatekeeper enemy defeated, (b) relic collected, (c) reward_giver NPC visited. Today's LivingWordAdventure.tsx signals scene completion via handleReachExit(); the card mounts in whatever scene-completion UI surface engineering chooses (see §13).
Where. INSIDE the scene-completion experience, BELOW the existing "Walk on" CTA. Never above; never replacing. "Walk on" stays primary.
Visibility (Decision B2). Hidden during first 2 scene completions. Pattern:
const completionCount = Number(localStorage.getItem('lw-scene-completions-shown:cta') ?? '0');
const nextCount = completionCount + 1;
localStorage.setItem('lw-scene-completions-shown:cta', String(nextCount));
const showCard = nextCount >= 3 && !dismissedThisSession;
dismissedThisSession lives in component state (NOT localStorage) so the card returns next session.
Card content (verbatim, strategic spec §T2):
Built by ChurchWiseAI
The narrative AI, the in-character dialogue, the lens-aware tutoring — this is the same engine that answers your congregation's questions 24/7 via voice and chatbot.
[See what it does for ministry →]
CTA URL: https://churchwiseai.com/from-living-word?utm_source=living-word&utm_medium=in-game&utm_campaign=scene-completion-v1&scene_id=<active_scene_id> (scene_id is NOT a utm_* param).
Events.
| Event | When | Metadata |
|---|---|---|
scene_completion_impression | once per render where card visible (NOT scenes 1-2) | scene_id |
scene_completion_click | on CTA click | scene_id |
Dismiss. Small × top-right. Hides for rest of session. Returns next session.
Styling. Light stone bg (NOT the cream parchment of the game world), navy accent border, sacred-gold "Built by" badge top-left, Inter sans (NOT Playfair). NOT animated. Never jarring.
§4. Surface 2 — NPC chat-close CTA line
When. Every NPC chat end-state: turn-cap, user × close, OR crisis deflection — i.e., whenever endConversation flips true in NpcChatModal.tsx. ALL THREE paths.
Where. INSIDE the existing end-state block (NpcChatModal.tsx:456-471), BELOW the existing "Walk on" button. Text-only — no card chrome.
Voice separation (load-bearing for AI Bridge). The two pieces of copy at chat-close MUST read as different voice tiers:
| Voice | Text | Typography |
|---|---|---|
| In-character | "The conversation has ended. Walk on — there is more of the story ahead." | existing — small body text, stone-600 |
| Builder credits | line below | text-xs italic text-stone-500, sans-serif |
Line content (verbatim, strategic spec §T3):
You just had a conversation with an AI character built by ChurchWiseAI. Imagine her answering your congregation's questions, day or night.
(Pronoun "her" tracks spec verbatim; founder may approve a neutral swap for male-coded NPCs, but default ship is verbatim.)
CTA URL: https://churchwiseai.com/from-living-word?utm_source=living-word&utm_medium=in-game&utm_campaign=npc-chat-close-v1&npc_id=<active_npc_id>
Events.
| Event | When | Metadata |
|---|---|---|
npc_chat_close_impression | when end-state renders (every time) | npc_id |
npc_chat_close_click | on CTA click | npc_id |
Hard constraint. The line MUST NOT appear DURING an active conversation. End-state only. Non-negotiable — interrupting mid-dialogue with Scribe Eden breaks the contemplative spell that is the entire strategic point.
§5. Surface 3 — Legacy Bloom finale panel (Decision B3)
When. AFTER LegacyBloomCinematic completes its full 7-second sequence (or its 4-second reduced-motion still). Cinematic's onComplete() callback signals the moment.
Where. Fades in exactly 1500ms after onComplete() fires. The 1500ms silence is intentional — the cinematic's last frame and the "Behold, I make all things new." text get a full beat before the credits panel arrives. Implemented as a SEPARATE component mounted by LivingWordAdventure.tsx after the cinematic unmounts. The cinematic itself is NEVER modified — the 1500ms delay lives in the parent, not the cinematic.
Panel content (verbatim, strategic spec §T4):
Built by ChurchWiseAI
You just walked from Eden to the New Creation. The seed you planted in chapter one bloomed at the end — the same way Scripture's threads carry from Genesis 1 to Revelation 22.
ChurchWiseAI builds AI tools for churches that hold this same story-shaped quality: voice agents, chatbots, and Pro Websites that talk like a pastor who's read the whole book.
[See what it does for your church →]
[Share Living Word with another teacher →]
Primary CTA URL: https://churchwiseai.com/from-living-word?utm_source=living-word&utm_medium=in-game&utm_campaign=legacy-bloom-finale-v1
Secondary CTA — share. Pre-filled mailto: link:
- Subject:
I just finished Living Word - Body:
Hey — I just finished a game called Living Word that walks through the whole biblical narrative from Eden to New Creation. The AI characters teach in tradition-specific voices and it's free. I thought you might appreciate it (or want to share it with your students/youth group). Here: https://livingword.bible/?ref=share
(Refine body to founder voice before ship.)
Events.
| Event | When | Metadata |
|---|---|---|
legacy_bloom_impression | when panel fades in (after +1500ms) | — |
legacy_bloom_click | on EITHER CTA | action: 'cwa_demo' | 'share' |
share_click | on secondary CTA — fires IN ADDITION to legacy_bloom_click | — |
Styling. Full-width panel, navy on cream (bg-[#FEFCF8], text text-[#1B365D]). Prominent — highest-conversion moment in the funnel per strategic spec §"Touchpoints." Playfair Display heading; Inter body and CTAs. Primary CTA = sacred-gold button (bg-[#D4AF37]); secondary = ghost outline. Fades in ~600ms.
Dismiss. Small × top-right returns player to post-game free-roam. Panel does NOT auto-dismiss; player chooses one of three actions.
Hard constraint. Panel MUST NOT replace, shorten, or interrupt the cinematic. Founder review will reject any implementation that overlaps.
§6. Implementation details
| Surface | New/extends | State | Accessibility | Mobile |
|---|---|---|---|---|
| Scene-completion card | new components/SceneCompletionCtaCard.tsx; mounted by LivingWordAdventure.tsx | localStorage counter + parent React dismissedThisSession flag | role="complementary", aria-label="Built by ChurchWiseAI — learn more", × aria-label="Dismiss this notice", focus NOT trapped (non-modal), keyboard-reachable via Tab | 320-640px full-width compact padding; 640+ comfortable padding; ≥768px max-width 32rem |
| NPC chat-close line | extends NpcChatModal.tsx end-state block (lines ~456-471); reads existing npcId/npcName props | none beyond endConversation | semantic <a href>, aria-label describes purpose + new-tab, opens target="_blank" rel="noopener noreferrer" | text-xs at all viewports, wraps naturally |
| Legacy Bloom finale panel | new components/LegacyBloomFinalePanel.tsx; mounted by LivingWordAdventure.tsx 1500ms after cinematic's onComplete() | parent bloomFinaleVisible boolean + setTimeout in parent | role="dialog", aria-modal="true" (post-game; focus trap appropriate here), focus → heading on fade-in, Escape triggers close, both CTAs and × keyboard-reachable | 320-640px full-viewport with stacked CTAs; ≥640px side-by-side, max-width 42rem centered |
Event-logging call sites.
- Impressions fire from
useEffecton mount (only when surface is visible). - Clicks fire from CTA
onClickhandlers. - The share CTA fires BOTH
legacy_bloom_click(withaction: 'share') ANDshare_click— both calls in the same handler.
Shared helper signature (no new event types added in Phase 1B — all 7 types used here are already in the Phase 1A LeadGenEventType union):
trackLeadGenEvent({
eventType: '<event from §3/§4/§5>',
placement: '<surface-specific string>',
utmCampaign: '<scene-completion-v1 | npc-chat-close-v1 | legacy-bloom-finale-v1>',
utmMedium: 'in-game',
metadata: { /* scene_id | npc_id | action */ },
});
§7. Visibility logic state table
| Player state | Scene-completion card | NPC chat-close line | Legacy Bloom panel |
|---|---|---|---|
| Has completed 0 scenes | n/a (no completion yet) | shown if NPC chat ended | n/a |
| Has completed 1 scene | hidden (counter = 1) | shown | n/a |
| Has completed 2 scenes | hidden (counter = 2) | shown | n/a |
| Has completed 3+ scenes | shown (dismissible) | shown | n/a |
| Has reached Legacy Bloom completion | shown | shown | shown ONCE per save, fades in +1500ms |
| Has dismissed scene-completion card this session | hidden until next session | shown | shown |
| Currently DURING NPC chat | n/a | NOT shown — end-state only | n/a |
| Currently DURING Legacy Bloom cinematic | n/a | n/a | NOT shown — only after cinematic completes |
§8. UTM tagging summary
All CTAs route to https://churchwiseai.com/from-living-word (Decision B1) with:
| Param | Value | Notes |
|---|---|---|
utm_source | living-word | constant across all Phase 1 surfaces |
utm_medium | in-game | Phase 1B constant; Phase 1A footer uses utm_medium=footer |
utm_campaign | scene-completion-v1 | npc-chat-close-v1 | legacy-bloom-finale-v1 | per-surface; -v1 suffix lets Phase 2 ship -v2 A/B without losing baseline |
scene_id / npc_id / action | varies | NOT utm_* — extra query params for funnel attribution |
The Phase-1A landing page already logs landing_page_view on render and reads UTM params from URL into event metadata. No landing-page changes required.
§9. Anti-goals (load-bearing)
Non-negotiable. Mirrors strategic spec anti-goals.
- NO CTAs during gameplay or during NPC chat. Completion moments only.
- NO NPC-voiced cross-sell. Scribe Eden never recommends ChurchWiseAI.
- NO popup interstitials or page-blocking lightboxes (modals OK; popups NOT).
- NO "limited time" / "act now" / fake urgency copy. Anywhere. Ever.
- NO third-party tracking pixels. First-party only via
lw_lead_gen_events. - NO persistent banner ads (Phase 1A footer is the only persistent surface).
- NO segmentation by visitor type in Phase 1B (Phase 2).
- NO mid-cinematic interruption for Legacy Bloom — 1500ms post-cinematic silence is the floor.
- NO behavioural / geo / time-of-day targeting. All players see same surfaces under same rules.
- NO A/B testing copy in Phase 1B. Ship v1 as-spec'd; iterate after Phase 1C data.
- NO email capture inside the game. Landing page only.
- NO mirroring of
/from-living-wordonlivingword.bible(Decision B1).
§10. Acceptance criteria
Functional MUSTs
- Scene-completion card appears at 3rd scene completion onward, never at scenes 1-2.
lw-scene-completions-shown:ctalocalStorage counter persists across page reloads and re-entries; resets only on browser data clear.- NPC chat-close CTA line appears at EVERY chat end-state — turn-cap, user × close, OR crisis deflection.
- Legacy Bloom finale panel fades in exactly 1500ms (±100ms) after
LegacyBloomCinematic'sonComplete(); cinematic byte-for-byte unchanged. - All three surfaces log impression + click events to
lw_lead_gen_events. - All CTAs route to
https://churchwiseai.com/from-living-word(absolute, churchwiseai.com host) with UTM params per §8. - Share CTA opens
mailto:with subject + body pre-filled per §5. - All three surfaces render correctly at 320-768px (mobile) and 768-1280px (desktop).
- 1500ms post-cinematic delay survives reduced-motion mode (4s cinematic version still triggers the panel at +1500ms).
Anti-tests (engineering MUST verify explicitly)
- Scene-completion card NEVER blocks "Walk on" or scene-transition action.
- NPC chat-close line NEVER appears DURING active chat — end-state only.
- Legacy Bloom panel NEVER interrupts the cinematic.
- NO CTA routes to a domain other than
churchwiseai.com. - NO CTA copy contains "limited time", "act now", "only X left", or any other urgency cue.
- NO CTA is voiced by an in-character NPC.
- NO
scene_completion_impressionevents fire during scenes 1-2 (counter < 3 = hidden = no impression).
§11. Test plan
Integration tests
- Scene 1: counter "0", mount completion → card NOT in DOM, no impression logged.
- Scene 3: counter "2" (→3 after increment), mount → card rendered, one impression with expected
scene_id. - Scene 3 click: click CTA → click event logged; href is absolute churchwiseai.com URL with
utm_campaign=scene-completion-v1+scene_id. - Dismiss: click ×, card unmounts; re-mount same session → stays hidden; clear session, re-mount → reappears.
- NPC chat-close — turn-cap: play to turn-cap end-state → CTA line in DOM, one impression with
npc_id. - NPC chat-close — user × close: open chat, send one message, click × → end-state renders, CTA line visible.
- NPC chat-close — crisis deflection: trigger deflection → conversation ends AND CTA line still rendered.
- NPC chat-close click: click CTA →
npc_chat_close_clickwithnpc_id; href absolute churchwiseai.com withutm_campaign=npc-chat-close-v1. - NPC chat-close — during chat: any point with
endConversation === false→ CTA line NOT in DOM. - Legacy Bloom panel — delay: complete cinematic → panel mounts at +1500ms (±100ms), NOT before;
legacy_bloom_impressionlogged. - Legacy Bloom primary click: click "See what it does" →
legacy_bloom_clickwithaction: 'cwa_demo'; href absolute churchwiseai.com withutm_campaign=legacy-bloom-finale-v1. - Legacy Bloom share click: click share → BOTH
legacy_bloom_click(action: 'share') ANDshare_clicklog; href startsmailto:, contains subject + body with livingword.bible link.
Playwright E2E
- Happy-path scene-completion: play scenes 1 → 2 → 3; no card at 1, 2; card at scene 3.
- Happy-path NPC chat: chat with Scribe Eden, exchange a few messages, close → CTA line at end-state.
- Crisis chat path: trigger crisis deflection → conversation ends AND CTA line still appears.
- Happy-path Legacy Bloom: walk to Tree of Life in New Creation → observe cinematic → panel fades in +1500ms → click primary → navigate to churchwiseai.com/from-living-word.
- Domain enforcement: intercept all CTA clicks across all 3 surfaces; every navigation target is
https://churchwiseai.com/from-living-word(exact host match).
§12. Founder go/no-go gate (after Phase 1B ships)
Phase 1B is DONE and Phase 1C is cleared when:
- All 3 surfaces live in production.
- 7 days of data captured in
lw_lead_gen_events. - Click-through rate ≥1% on at least 2 of 3 surfaces (clicks/impressions per surface). Strategic spec's full-funnel target was ≥2%; per-surface 1% leaves the landing→demo step headroom.
- Zero brand-misalignment complaints from founder review of user feedback.
- At least 1 demo booking attributed back via UTM (
utm_source=living-wordin Cal.com referrer).
If green: proceed to Phase 1C (founder lead-gen dashboard) + queue Phase 2 planning. If any fail: pause Phase 1C, founder + engineering review failure mode, iterate copy/placement before resuming.
§13. Open questions deferred (NOT Phase 1B scope)
These do NOT block ship. Engineering proceeds with this spec; revisit in their proper phase.
- Segmentation by visitor type (youth pastor / Sunday school teacher / pastor / parent) — Phase 2.
- A/B test infrastructure for CTA copy — Phase 2.
- Email opt-in for non-purchasing visitors on landing — Phase 2.
- Cross-promotion from PewSearch / SermonWise into Living Word — Phase 3.
- Premium-tier upsell from in-game contexts ($4.95/mo Phase 2-5 unlock) — Phase 3, after Phase 1B+1C data validates the funnel.
- Scene-completion UI surface — RESOLVED 2026-05-24 (founder). Engineering introduces a new brief scene-completion modal as the bloom card's host. This is the cleanest UX — "Walk on" stays primary inside the modal (positioned above the bloom card), the scene-completion moment gets a small celebratory beat that the current scene-transition feedback band lacks, and the modal becomes a reusable host for future per-scene UI (e.g., scene-specific scripture reflection, future Phase 2 mechanics). The component lives at
src/app/living-word/components/SceneCompletionModal.tsxand is invoked from the existinghandleReachExit()success path inLivingWordAdventure.tsx(no other scene-completion logic moves into it; it's a presentation-only modal that wraps the existing transition).
End of spec. Engineering may begin Phase 1B implementation immediately after PR #559 merges and the lw_lead_gen_events migration is verified in production. No additional founder decisions required before the first commit.