Why This Matters
House of Legends needs one clear conversion story from ad click to paid booking. The landing website sends browser-safe events once; the backend forwards high-confidence events and server-confirmed paid booking outcomes onward. Operators verify outbound sends in each platform’s own event manager.Platform Pages
| Platform | Page | Status |
|---|---|---|
| PostHog | PostHog Analytics | Active — browser + server |
| Meta | Meta Pixel + CAPI | Active — Pixel + server CAPI |
| GTM | Google Tag Manager | Configured but not mounted |
Architecture Overview
Technical details — file paths and conventions
Technical details — file paths and conventions
- The canonical landing analytics module lives at
apps/landing/lib/analytics/analytics.ts. All browser events originate there. - Server events originate from
apps/hono/src/services/analytics/posthog-analytics.service.ts. - Do not add separate landing analytics modules for individual destinations. New browser events should go through
analytics.tsso all platforms stay aligned.
Event Inventory
Browser Events (46)
Every browser event fires to PostHog. Events marked with Meta also fire to Meta Pixel. Events marked with CAPI are additionally forwarded by the backend to Meta Conversions API.Source file paths
Source file paths
- Browser events originate from the landing analytics module.
- Server events originate from the Hono analytics service.
| # | Event | Meta | CAPI | When it fires |
|---|---|---|---|---|
| 1 | page_view | PageView | — | Every page navigation |
| 2 | view_item | ViewContent | — | Viewing a show/experience detail |
| 3 | add_to_cart | AddToCart | — | Adding an experience to the booking cart |
| 4 | remove_from_cart | — | — | Removing an experience from the cart |
| 5 | addons_update | — | — | Adding, removing, or changing addon quantity |
| 6 | view_cart | — | — | Viewing the booking cart summary |
| 7 | begin_checkout | InitiateCheckout | InitiateCheckout | Guest enters payment checkout |
| 8 | purchase | Purchase | — | Server-confirmed paid booking (payment-result page) |
| 9 | add_payment_info | AddPaymentInfo | AddPaymentInfo | Guest submits payment details |
| 10 | lead | Lead | Lead | Qualified inquiry submitted |
| 11 | inquiry_start | — | — | Guest opens an inquiry form |
| 12 | form_abandonment | — | — | Guest leaves inquiry form without submitting |
| 13 | form_error | — | — | Validation error on a form field |
| 14 | payment_redirect | — | — | Redirect to/from OnePay payment page |
| 15 | payment_error | — | — | Payment redirect failed, timed out, or abandoned |
| 16 | payment_cta_click | — | — | Pay Now / Contact Support CTA clicked |
| 17 | booking_step | — | — | Booking funnel step completed or abandoned |
| 18 | book_now_click | — | — | Book Now CTA clicked (with source and event context) |
| 19 | select_item | — | — | User selects a show/experience from a list |
| 20 | select_content | — | — | User taps a content element |
| 21 | external_link | — | — | User taps an external link |
| 22 | customer_support_widget | — | — | Support widget interaction (open, close, phone, WhatsApp, chat) |
| 23 | search | — | — | Search query submitted with results |
| 24 | search_refinement | — | — | Search query refined |
| 25 | empty_search | — | — | Search submitted with no results |
| 26 | scroll_depth | — | — | User scrolls to a depth threshold |
| 27 | timing | — | — | Performance timing measurement |
| 28 | section_view | — | — | A marked page section becomes visible |
| 29 | section_read | — | — | A marked section viewed for at least 1 second |
| 30 | session_start | — | — | Analytics session begins |
| 31 | session_end | — | — | Analytics session ends |
| 32 | utm_capture | — | — | UTM parameters detected on landing |
| 33 | $exception | — | — | Uncaught frontend error |
| 34 | api_error | — | — | Network, timeout, server, or client API error |
| 35 | 404 | — | — | Page not found |
| 36 | video_play | — | — | Show page video starts playing |
| 37 | video_complete | — | — | Show page video finishes |
| 38 | homepage_video_play | — | — | Homepage hero video starts playing |
| 39 | homepage_video_complete | — | — | Homepage hero video finishes |
| 40 | language_switch | — | — | User switches locale (en/vi) |
| 41 | pdf_download | — | — | User downloads a PDF |
| 42 | email_subscribe | — | — | User subscribes to email (footer, popup, or booking confirmation) |
| 43 | mobile_keyboard | — | — | Mobile keyboard opens or closes (with viewport change) |
| 44 | promo_applied | — | — | Promo code applied successfully |
| 45 | promo_rejected | — | — | Promo code rejected (invalid or expired) |
| 46 | promo_removed | — | — | Promo code removed from booking |
Server Events (8)
All server events fire to PostHog. Thepayment completed event is also sent to Meta CAPI as a server-confirmed Purchase.
| # | Event | Meta CAPI | When it fires |
|---|---|---|---|
| 1 | reservation created | — | New reservation persisted |
| 2 | checkout started | — | Guest enters the payment checkout step |
| 3 | payment completed | Purchase | OnePay confirms a successful payment |
| 4 | payment failed | — | OnePay reports a payment failure |
| 5 | reservation cancelled | — | Reservation status moves to cancelled |
| 6 | refund processed | — | Refund amount recorded against a payment |
| 7 | inquiry submitted | — | New inquiry created from the public form |
| 8 | operator check-in completed | — | Staff checks a guest in through Mission Control |
Platform Distribution
| Platform | Events received | Count |
|---|---|---|
| PostHog | All browser + all server | 54 |
| Meta Pixel | Browser events marked Meta | 7 |
| Meta CAPI | Server Purchase + forwarded browser events | 4 |
| GTM dataLayer | All browser (dormant) | 0 (not mounted) |
PostHog Identity and Replay
Beyond events, PostHog also captures:| Feature | Status | Details |
|---|---|---|
| Person identification | Active | CRM customer ID used as distinctId after early lead capture |
| Session replay | Active | Unmasked form inputs and request/response payloads for booking recovery |
| Autocapture | Disabled | Manual event tracking only |
| Page leave | Active | Captured automatically |
North-Star Conversion Model
The tracking system answers three business questions:- Who is interested?
- Who is seriously considering booking?
- Who actually becomes a paying customer?
| Level | Events | Primary use |
|---|---|---|
| Business outcome | Server-confirmed paid booking (Meta CAPI + PostHog payment completed) | Revenue reporting and campaign optimization |
| Strong intent | begin_checkout, add_payment_info, payment initiated, qualified inquiry | Funnel diagnosis and early campaign learning |
| Interest | view_item, section_view, section_read, gallery/video/review engagement | Retargeting, page decisions, creative insight |
| Diagnostics | Scroll depth, timing, frontend exceptions, API errors | UX and reliability improvement |
Section Reading Time
The landing website tracks how long guests spend reading each page section.| Event | Meaning |
|---|---|
section_view | A marked section became meaningfully visible on screen |
section_read | A marked section accumulated at least one second of visible time |
section_read in PostHog to answer which show-page sections hold attention, where inquiry pages lose readers, and whether booking steps are being reviewed before checkout.
Technical details — components and markers
Technical details — components and markers
SectionReadTrackerpowers section engagement tracking.- Explicit
data-analytics-sectionmarkers are preferred, but the tracker also discovers meaningful unmarkedsectionelements insidemain#main-content. - Shared marketing sections are marked through
SectionWrapper. - Booking flow steps are marked through
BookingSectionBlock.
Assisted Booking Feedback Loop
Some paid bookings start in Messenger, Instagram, WhatsApp, phone, or staff conversations. Those conversions are still marketing outcomes and should be recorded when staff confirms payment.| Field | Why it matters |
|---|---|
| Reservation ID and reference | Stable booking identity |
| Payment status and paid timestamp | Proof the booking became revenue |
| Booking value and currency | Revenue optimization and reporting |
| Show, showEvent, date, guest count | Campaign and operations analysis |
| Channel and campaign reference | Attribution for fanpage-assisted sales |
| Safe customer reference | Customer-level analysis without raw PII |
Paid Social UTM Links
All paid social links should include UTM parameters:Successful Booking URLs
| Route | Purpose | Fires Purchase? |
|---|---|---|
/booking/payment-result | OnePay payment return | Yes (only when payment is confirmed paid) |
/booking/confirmation | Email receipt page | No |
Technical details — purchase gating logic
Technical details — purchase gating logic
- The payment-result page gates the Purchase event with
paymentStatus=PAID— only confirmed payments trigger the event. - The confirmation page has
shouldTrackPurchase=falsebecause it is a static receipt page linked from sent emails. It must stay live for those links to work.
Verification
Each platform has its own verification checklist:Technical verification details
Technical verification details
Verification steps vary by platform but generally include:
- Confirming events appear in each platform’s live event manager or debugger.
- Checking that server-side events reach PostHog and Meta CAPI.
- Validating UTM parameter passthrough from ad link to event payload.
- Confirming session replay captures booking flow correctly.
