Custom Widget Analytics Integration
TicketingHub V2 Widget Custom Integration
Overview
This document describes the custom JavaScript events that the TicketingHub V2 checkout widget sends to the parent window via the browser's postMessage API. These events allow you to track user interactions throughout the checkout flow and build custom integrations with analytics platforms or your own systems.
All events are prefixed with th: (TicketingHub namespace) and are sent from the widget iframe to the parent window using window.parent.postMessage().
How to Listen to Events
To receive widget events, add a message listener to the parent window:
window.addEventListener('message', function(event) {
// Check if it's a TicketingHub event
if (!event.data || !event.data.event) return;
if (!event.data.event.startsWith('th:')) return;
const eventName = event.data.event;
const eventData = event.data.data;
console.log('Event:', eventName);
console.log('Data:', eventData);
});
Event Message Structure
All events follow this structure:
{
event: "th:event_name", // Event name with th: prefix
data: { // Event-specific data
// ... parameters
}
}
Events Reference
Page View Events
th:page_view
Sent when a user navigates to a checkout step. This is the most common event and fires on every page/step transition.
Data:
{
page_title: "Page Title", // Human-readable page name
page_path: "page_path", // URL-friendly page identifier
start_date: "2024-06-01T00:00:00Z", // (date pages only) ISO8601
selected_date: "2024-06-15T14:00:00Z" // (date pages only) ISO8601
}
Example:
// User navigates to date selection
{
event: "th:page_view",
data: {
page_title: "Date and Time Selection",
page_path: "date_and_time_selection",
start_date: "2024-06-01T00:00:00Z",
selected_date: "2024-06-15T14:00:00Z"
}
}
Selection Events
th:select_item
Sent when a user selects a product, variant, or merchandise item.
Data:
{
item_list_id: "uuid", // Widget ID or Product ID
item_list_name: "Sellable List", // "Sellable List" or "Variant List"
items: [
{
item_id: "uuid", // Product/Variant/Merchandise ID
item_name: "Product Name",
item_category: "Product" // "Product", "Variant", "Merchandise", or "Package"
}
]
}
Example:
// User selects a product
{
event: "th:select_item",
data: {
item_list_id: "widget-123",
item_list_name: "Sellable List",
items: [
{
item_id: "product-456",
item_name: "City Walking Tour",
item_category: "Product"
}
]
}
}
th:tier_selection_selected
Sent when a user selects ticket quantities.
Data:
{
tickets: {
"0": { tier_id: "uuid", quantity: 2 },
"1": { tier_id: "uuid", quantity: 1 }
}
}
Example:
{
event: "th:tier_selection_selected",
data: {
tickets: {
"0": { tier_id: "tier-adult-123", quantity: 2 },
"1": { tier_id: "tier-child-456", quantity: 1 }
}
}
}
th:extras_selection_selected
Sent when a user selects add-on extras.
Data:
{
extras: {
"0": { extra_id: "uuid", quantity: 1 },
"1": { extra_id: "uuid", quantity: 2 }
}
}
th:settings_selected
Sent when a user changes locale or currency settings.
Data:
{
settings: {
locale: "en-GB",
currency: "GBP"
}
}
th:package_tickets_selection_selected
Sent when a user selects ticket quantities for a package booking.
Data:
{
tickets: {
"0": { tier_type: "ADULT", quantity: 2 },
"1": { tier_type: "CHILD", quantity: 1 }
}
}
Form Submission Events
th:add_customer_details_submit
Sent when a user submits customer details.
Data:
{
customer: {
first_name: "John",
last_name: "Doe",
email: "john@example.com",
phone: "+44123456789",
// ... additional form fields
}
}
th:questions_and_answers_submit
Sent when a user submits answers to booking questions.
Data:
{
answers: {
"question-uuid-1": "Answer text",
"question-uuid-2": "Selected option"
}
}
th:package_booking_questions_and_answers_submit
Sent when a user submits answers for a package booking.
Data:
{
booking_index: 0,
answers: {
"question-uuid-1": "Answer text"
}
}
Voucher Redemption Events
th:voucher_booking_code_applied
Sent when a gift voucher code is successfully applied.
Data:
{
voucher_booking_code: "GIFT-ABC123"
}
th:voucher_purchase
Sent when a user initiates a voucher/gift card purchase.
Data: Empty object {}
th:voucher_booking_redemption_cancelled
Sent when a user cancels a voucher redemption.
Data: Empty object {}
th:voucher_booking_redemption_attendee_details_submit
Sent when a user submits attendee details during voucher redemption.
Data:
{
attendee_details: {
first_name: "Jane",
last_name: "Doe",
email: "jane@example.com"
}
}
th:voucher_booking_redemption_questions_and_answers_submit
Sent when a user submits answers during voucher redemption.
Data:
{
answers: {
"question-uuid": "Answer text"
}
}
Basket Events
th:discount_code_applied
Sent when a discount code is successfully applied.
Data:
{
discount_code: "SUMMER20"
}
th:discount_code_removed
Sent when a discount code is removed.
Data: Empty object {}
th:basket_delete_booking
Sent when a booking is removed from the basket.
Data:
{
booking_id: "booking-uuid"
}
th:basket_delete_package_booking
Sent when a package booking is removed from the basket.
Data:
{
bookings_package_id: "package-booking-uuid"
}
Order Events
th:purchase
Sent when an order is successfully completed. This is the main conversion event.
Data:
{
transaction_id: "TH-ABC123XYZ",
value: 150.00,
currency: "GBP",
items: [
{
item_id: "TKT-001",
item_name: "Adult Ticket",
item_brand: "City Walking Tour",
item_category: "standard",
item_variant: "Morning Session",
price: 50.00,
quantity: 1
}
]
}
Session Events
th:order_expired
Sent when the order/session expires due to timeout.
Data: Empty object {}
Integration Examples
Example 1: Track All Events
window.addEventListener('message', function(event) {
if (!event.data || !event.data.event) return;
if (!event.data.event.startsWith('th:')) return;
const eventName = event.data.event;
const eventData = event.data.data || {};
// Log all events
console.log('[TicketingHub]', eventName, eventData);
// Send to your analytics
if (window.analytics) {
window.analytics.track(eventName, eventData);
}
});
Example 2: Send Purchases to Multiple Platforms
window.addEventListener('message', function(event) {
if (!event.data || event.data.event !== 'th:purchase') return;
const data = event.data.data;
// Google Analytics 4
if (window.gtag) {
gtag('event', 'purchase', {
transaction_id: data.transaction_id,
value: data.value,
currency: data.currency,
items: data.items
});
}
// Facebook Pixel
if (window.fbq) {
fbq('track', 'Purchase', {
value: data.value,
currency: data.currency,
content_ids: data.items.map(i => i.item_id),
content_type: 'product',
num_items: data.items.length
});
}
// Google Ads Conversion
if (window.gtag) {
gtag('event', 'conversion', {
send_to: 'AW-XXXXXXXXX/XXXXXXXXXXXXX',
value: data.value,
currency: data.currency,
transaction_id: data.transaction_id
});
}
// TikTok Pixel
if (window.ttq) {
ttq.track('CompletePayment', {
value: data.value,
currency: data.currency,
content_id: data.items.map(i => i.item_id).join(',')
});
}
// Custom Backend
fetch('/api/conversions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
order_id: data.transaction_id,
revenue: data.value,
currency: data.currency,
items: data.items
})
});
});
Event Flow Diagram
User Opens Widget
|
+-- th:page_view (sellable_list)
|
User Selects Product
|
+-- th:select_item
+-- th:page_view (variant_list) [if variants exist]
|
User Selects Variant [if applicable]
|
+-- th:select_item
+-- th:page_view (tier_selection)
|
User Selects Ticket Quantities
|
+-- th:tier_selection_selected
+-- th:page_view (date_and_time_selection)
|
User Selects Date/Time
|
+-- th:page_view (extras_selection) [if extras available]
|
User Selects Extras [if applicable]
|
+-- th:extras_selection_selected
+-- th:page_view (questions_and_answers) [if questions configured]
|
User Answers Questions [if applicable]
|
+-- th:questions_and_answers_submit
+-- th:page_view (basket)
|
User Reviews Basket
|
+-- th:discount_code_applied [if code entered]
+-- th:basket_delete_booking [if item removed]
+-- th:page_view (add_customer_details)
|
User Enters Details
|
+-- th:add_customer_details_submit
+-- th:page_view (payment)
|
User Completes Payment
|
+-- th:purchase
+-- th:conversion
+-- th:page_view (success)
All Events Summary
Event | Trigger | Has Data |
|---|---|---|
th:page_view | Every page navigation | Yes |
th:select_item | Product/variant selection | Yes |
th:tier_selection_selected | Ticket quantity selection | Yes |
th:extras_selection_selected | Extras selection | Yes |
th:settings_selected | Locale/currency change | Yes |
th:package_tickets_selection_selected | Package ticket selection | Yes |
th:add_customer_details_submit | Customer form submission | Yes |
th:questions_and_answers_submit | Q&A form submission | Yes |
th:package_booking_questions_and_answers_submit | Package Q&A submission | Yes |
th:voucher_booking_code_applied | Voucher code applied | Yes |
th:voucher_purchase | Voucher purchase started | No |
th:voucher_booking_redemption_cancelled | Redemption cancelled | No |
th:voucher_booking_redemption_attendee_details_submit | Voucher attendee form | Yes |
th:voucher_booking_redemption_questions_and_answers_submit | Voucher Q&A form | Yes |
th:discount_code_applied | Discount code applied | Yes |
th:discount_code_removed | Discount code removed | No |
th:basket_delete_booking | Booking removed from cart | Yes |
th:basket_delete_package_booking | Package removed from cart | Yes |
th:purchase | Order completed | Yes |
th:conversion | Conversion (purchase/redemption) | Yes |
th:order_expired | Session timeout | No |
Security Considerations
When processing events:
- Validate event origin in production environments
- Sanitize data before inserting into DOM
- Never use eval() on event data
window.addEventListener('message', function(event) {
// Validate origin (optional but recommended for production)
// if (!event.origin.includes('ticketinghub.com')) return;
if (!event.data || !event.data.event) return;
if (!event.data.event.startsWith('th:')) return;
// Safe to process
handleEvent(event.data);
});
Reference
- MDN postMessage: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
Looking for Google Analytics 4 Integration?
- Google Analytics 4 Intergration: https://help.ticketinghub.com/en/article/google-analytics-4-integration-1rnmjl4/
Updated on: 29/01/2026
Thank you!
