Doc Status: Current | Direct Hono CAPI documented | Token must stay in Cloudflare Worker secrets | Verify against dashboard audit rows and Meta Events Manager
Why This Matters
Meta Pixel and Conversions API work together to give House of Legends one reliable conversion story from ad click to paid booking. This matters because Meta uses this data to optimize ad delivery — the more accurately Meta can see which clicks turn into paying guests, the better it spends the advertising budget. Here is how it works in plain language:- Browser Pixel tracks what visitors do on the website — browsing shows, starting checkout, submitting inquiries.
- Server CAPI confirms actual payment outcomes directly from House of Legends’ payment system to Meta.
- Both signals share a unique event ID, so Meta automatically deduplicates and never double-counts a single booking.
Current Status
Meta tracking is configured for direct integration. The browser Pixel sends events on landing pages, and Hono is the only server transport for Meta Conversions API. Server CAPI events send only when the Cloudflare Worker has a validMETA_CONVERSIONS_API_ACCESS_TOKEN; otherwise Hono writes a SKIPPED audit row.
| Tracking Layer | Status |
|---|---|
| Browser Pixel | Active — mounted on landing pages |
| Server CAPI | Configured — sends from Hono when token secret is present |
| Deduplication | Active — both layers share event IDs |
| Admin audit log | Visible at /dashboard/integration/meta/events |
Browser Pixel Events
The website tracks these visitor actions and sends them as standard Meta events:| Visitor Action | Meta Event Name |
|---|---|
| Views any page | PageView |
| Views a show detail page | ViewContent |
| Adds tickets to their selection | AddToCart |
| Starts the checkout process | InitiateCheckout |
| Enters payment details | AddPaymentInfo |
| Completes a paid booking | Purchase |
| Submits a booking inquiry | Lead |
Pixel configuration (technical)
Pixel configuration (technical)
Browser Pixel
| Item | Value |
|---|---|
| Environment variable | NEXT_PUBLIC_META_PIXEL_ID |
| Pixel ID | 1686954142433862 |
| Scope | Public (not a secret) |
| Owner | Landing app via apps/landing/lib/analytics/analytics.ts |
Server-Side CAPI
| Item | Value |
|---|---|
| Access token secret | META_CONVERSIONS_API_ACCESS_TOKEN (Hono Worker secret via wrangler secret put) |
| Enabled flag | META_CONVERSIONS_API_ENABLED=true (Hono Worker env) |
| Graph API version | META_GRAPH_API_VERSION=v22.0 |
| Test event code | META_CONVERSIONS_API_TEST_EVENT_CODE (use only during verification) |
| Owner | apps/hono/src/services/analytics/meta-conversions-api.service.ts |
Two-Signal Purchase Tracking
Paid bookings are tracked using two independent signals that Meta combines into one deduplicated conversion. This is important for ad optimization accuracy.How It Works
- Browser signal — When a guest completes payment and lands on the payment result page, the browser fires a
Purchaseevent to Meta. - Server signal — Simultaneously, the House of Legends payment backend independently confirms the payment with Meta’s server API.
- Deduplication — Both signals carry the same unique booking ID. Meta recognizes they represent the same purchase and counts it once.
Two-signal implementation details
Two-signal implementation details
Signal 1 — Browser Pixel Purchase
- Where:
/booking/payment-resultviaBookingConfirmationClientwithshouldTrackPurchase=true - When: Only when backend
paymentStatus === "PAID" - How:
analytics.purchase()->fbq("track", "Purchase", parameters, { eventID }) - Guard: Session storage (
analytics_purchase_sent_<transactionId>) prevents re-fires.useRefprevents double-fires in one component lifecycle.
Signal 2 — Server CAPI Purchase
- Where: Hono
applyReservationHostedPaymentResult()inapps/hono/src/services/reservations/reservation-payment.service.ts - When: After OnePay confirms success and reservation changes to
paymentStatus="PAID" - How:
captureMetaPurchaseConversion()sends Meta CAPIPurchasewith hashed email/phone, VND value, reservation reference, content IDs, and the sharedevent_id
Shared Event ID
Both signals use the same deterministic format:buildPaidBookingEventId() from @hol/shared/analytics/marketing-event-id. Meta deduplicates when both Pixel and CAPI report the same purchase.The
/booking/confirmation page is the email receipt route. It renders booking details but does not fire a browser Purchase event (shouldTrackPurchase=false). It must stay live because sent confirmation emails link to it.Server-Side Events
The payment backend sends these events directly to Meta. Server-sent events carry hashed customer data (not raw data) and confirmed payment amounts, making them more reliable than browser-only tracking.| Event | When It Fires |
|---|---|
Purchase | Guest completes a paid booking (confirmed by payment system) |
InitiateCheckout | Guest enters the payment checkout step |
AddPaymentInfo | Guest submits their payment details |
Lead | Guest submits a qualified booking inquiry |
CAPI endpoint details
CAPI endpoint details
For browser-origin events, landing sends them to
POST /api/analytics/meta/outbound-event. Hono accepts only InitiateCheckout, AddPaymentInfo, and Lead. It creates an audit row only when it performs an outbound send attempt.What Meta Receives
| Signal | Includes |
|---|---|
| Server Purchase | Hashed email/phone, booking value, currency, content IDs, reservation reference, event ID |
| Browser-origin events | Browser cookie data, source URL, IP, user-agent, commerce fields |
Admin Audit Log
Every Meta event sent by the server creates an audit record. Staff can review these in the dashboard to troubleshoot tracking issues and confirm that purchases are being reported correctly.| Audit Field | What It Shows |
|---|---|
| Event status | Sent, Failed, Skipped, Pending |
| Reservation reference | Human-readable booking ID |
| Event ID | Unique deduplication key shared with browser Pixel |
| Pixel ID | Which Meta Pixel was used |
| Value / currency | VND amount of the booking |
| Sanitized payload | What was sent to Meta (access token and raw PII removed) |
| Meta response | What Meta replied |
| Meta trace ID | For debugging in Meta Events Manager |
Audit table name and path
Audit table name and path
Every outbound CAPI attempt creates an audit row in
hol_meta_conversions_api_events. View them at:Meta Custom Conversion (Fallback)
If you need a custom conversion before server CAPI is fully verified, use an event-based rule in Meta Events Manager:Setup and verification steps
Setup and verification steps
Setup
Create the Meta token
In Meta Events Manager, open the Pixel/Dataset, go to Settings, and generate a Conversions API access token. If Meta offers Dataset Quality API with direct integration, use it so Events Manager exposes match-rate and data-quality diagnostics.
Confirm public vars
Keep
META_CONVERSIONS_API_ENABLED=true, META_PIXEL_ID=1686954142433862, and META_GRAPH_API_VERSION=v22.0 in the Hono Worker configuration.Confirm secret presence
Run
wrangler secret list from apps/hono and confirm META_CONVERSIONS_API_ACCESS_TOKEN is listed. The command shows only secret names, not values.Check the admin audit
Open
/dashboard/integration/meta/events and confirm Hono created audit rows for each outbound send attempt.Verification
Confirm browser events
Open landing with the Pixel configured. In Meta Events Manager, confirm
PageView, ViewContent, InitiateCheckout, AddPaymentInfo, Purchase, and Lead appear.Confirm booking conversion
Complete a paid booking flow. Confirm Meta receives the browser
Purchase with a valid event_id.Confirm CAPI Purchase
In Meta Events Manager, verify Hono sends a server
Purchase after paid OnePay booking. Missing token means Hono stores a Skipped audit row.Confirm CAPI intent events
Trigger
begin_checkout, add_payment_info, and a lead submission. Confirm /dashboard/integration/meta/events shows audit rows for InitiateCheckout, AddPaymentInfo, and Lead.