In-Chat Booking Email Collection¶
Overview¶
When a visitor clicks a booking CTA (e.g., "Book a Demo") and their email is not known, the system collects it through conversation before redirecting to the booking page with the email pre-filled.
User Flow¶
flowchart TD
A[User clicks CTA] --> B{Email known?}
B -->|Yes| C[Redirect with ?email=xxx]
B -->|No| D[Bot asks for email]
D --> E[User provides email]
E --> F[Redirect with ?email=xxx]
Key Files¶
Backend¶
| File | Purpose |
|---|---|
ixchat/nodes/booking_handler.py |
Main booking flow handler |
ixchat/nodes/action_router.py |
Routes to booking_handler |
ixchat/utils/email_extraction.py |
Email regex extraction |
ixchat/pydantic_models/booking_state.py |
BookingState model |
ixchat/chatbot.py |
Loads visitor profile from Supabase on session start |
ixdata/clients/conversation_storage.py |
get_visitor_profile_data() for cross-session persistence |
Frontend¶
| File | Purpose |
|---|---|
utils/widget/bookingReducer.ts |
Booking state management |
hooks/widget/useBookingReducer.ts |
Hook wrapping useReducer |
components/ExpandedChatView.tsx |
Booking flow orchestration |
State Management¶
BookingState tracks progress across turns:
is_booking_flow- Active booking flow from CTA clickawaiting_email- Waiting for user to provide emailemail_collected- Email successfully capturedredirect_url- Target URL for redirect
Cross-Session Persistence¶
Email and visitor profile data (company, sector) persist across sessions:
- Saving: When email is captured, it's stored in Supabase
visitorstable - Loading: On new session start,
get_visitor_profile_data()loads saved data - Merging: Loaded data merges into
visitor_profileif current session has no data
This means returning visitors skip email collection if they provided it previously.
Debugging¶
Backend logs use the 📧 [BOOKING HANDLER] prefix:
📧 [BOOKING HANDLER] Extracted email from user input: john@example.com
📧 [BOOKING HANDLER] Email already known, generating confirmation
Cross-session persistence logs:
📋 Loaded visitor profile data from Supabase: fields=['email', 'company_name']
[Visitor Profile] Loaded data for person_id=abc12345...: fields=['email', 'company_name']
Common Issues¶
| Issue | Cause | Solution |
|---|---|---|
| Email not extracted | Invalid format | Check regex pattern accepts the format |
| Stuck in awaiting state | visitor_profile not updating | Check completion event includes visitor_profile |
| Redirect not triggering | useEffect dependencies | Verify visitorProfile changes trigger effect |
Testing¶
poetry run pytest packages/ixchat/tests/test_booking_handler.py -v
poetry run pytest packages/ixchat/tests/test_email_extraction.py -v
Related¶
- Form Field Extraction - Similar dynamic URL pattern
- IXChat Package - LangGraph architecture