Actions

Prev Next

The Tickets SDK provides analytics callbacks so you can track user behavior within the SDK experience. You can observe page views, user actions, and associated metadata to feed into your own analytics systems.

Note: These analytics callbacks are for your own tracking purposes. You can process these how you wish and send them to your own analytics backend


Overview

Both iOS and Android expose analytics for the Tickets SDK and the Authentication SDK. The table below summarizes the key differences in how each platform delivers analytics events.

Aspect

iOS

Android

Tickets analytics API

TMTicketsAnalyticsDelegate protocol

UserAnalyticsDelegate singleton observer

Delivery mechanism

Delegate methods

Kotlin SharedFlow / LiveData

Event structure

Separate Page and Action enums

Single Action enum (screens and actions combined)

Metadata format

Typed MetadataType enum

Bundle with string keys

Auth analytics API

See Authentication Analytics

See Authentication Analytics


Tickets Analytics Setup

Set the analyticsDelegate on the shared TMTickets instance:

TMTickets.shared.analyticsDelegate = self

Then conform to the TMTicketsAnalyticsDelegate protocol, which provides two methods:

  • userDidView(page:metadata:) — called when the user views a page

  • userDidPerform(action:metadata:) — called when the user interacts with a control

Observe analytics events from the UserAnalyticsDelegate singleton. The recommended approach uses a lifecycle-aware observer:

// Recommended: lifecycle-aware observer (handles cleanup automatically)
UserAnalyticsDelegate.handler.observe(lifecycleOwner) { data ->
    data?.let { logAnalytics(it) }
}

Alternative approaches:

// Flow-based (for coroutines)
UserAnalyticsDelegate.handler.getFlow().collect { data -> ... }
// LiveData with observeForever (requires manual cleanup)
UserAnalyticsDelegate.handler.getLiveData().observeForever(userAnalyticsObserver)

Warning: If you use observeForever, you must call removeObserver when the Activity is destroyed to avoid leaking the observer.

Each event is delivered as a UserAnalyticsDelegate.AnalyticsData object containing an actionName string and optional data Bundle.


Page Views

Page view events fire when the user navigates to a screen within the SDK.

Page views are delivered through userDidView(page:metadata:) with a typed Page enum:

func userDidView(page: TMTickets.Analytics.Page, metadata: TMTickets.Analytics.MetadataType) {
    print("userDidViewPage: \(page.rawValue)")
}

Available pages:

Page

Description

events

Purchased events listing ("My Events")

eventTickets

Tickets listing for a specific event ("My Tickets")

eventModules

User scrolled down to view modules on tickets listing page

ticketBarcode

Ticket barcode page

ticketDelivery

Ticket delivery method info (non-barcode)

ticketDetails

Ticket details page ("Back of Ticket")

mfaForTicketOperation

2FA/MFA prompt for a ticket operation

mfaForViewBarcode

2FA/MFA prompt to view a barcode

mfaForWebpage

2FA/MFA prompt for a webpage

eventInfoBanner

Event info banner (health check, tax info, etc.)

On Android, page views are delivered as action events. Screen-related actions use the suffix SCREENSHOWED:

Action

Description

ACTION_MYTICKETSCREENSHOWED

My Tickets screen

ACTION_MANAGETICKETSCREENSHOWED

Manage Tickets screen

ACTION_ADDPAYMENTINFOSCREENSHOWED

Add Payment Info screen

ACTION_REVIEWPOSTINGSCREENSHOWED

Review Posting screen

ACTION_POSTINGCONFIRMATIONSCREENSHOWED

Posting Confirmation screen

ACTION_CANCELPOSTINGSCREENSHOWED

Cancel Posting screen

ACTION_CANCELPOSTINGCONFIRMSCREENSHOWED

Cancel Posting Confirmation screen

ACTION_MYTICKETBARCODESCREENSHOWED

My Ticket Barcode screen

ACTION_TICKETDETAILSSCREENSHOWED

Ticket Details screen

Note: Android actionName strings are prefixed with com.ticketmaster.presencesdk.eventanalytic.action. (e.g., com.ticketmaster.presencesdk.eventanalytic.action.MYTICKETSCREENSHOWED).

User Actions

User action events fire when the user interacts with buttons and controls in the SDK.

Actions are delivered through userDidPerform(action:metadata:) with a typed Action enum:

func userDidPerform(action: TMTickets.Analytics.Action, metadata: TMTickets.Analytics.MetadataType) {
    print("userDidPerformAction: \(action.rawValue)")
}

Available actions:

Action

Description

addTicketToWalletButton

User pressed the Apple "Add To Wallet" button

barcodeScreenshot

User took a screenshot of the barcode

transferSendButton

User pressed the Send Transfer button

transferCancelButton

User pressed the Cancel Transfer button

postingEditButton

User pressed the Edit Resale Posting button

postingCancelButton

User pressed the Cancel Resale Posting button

eventInfoBannerButton

User pressed More Info on the event info banner

moduleActionButton

User pressed a button on a custom module

pullToRefreshEvents

User pulled to refresh the events listing

navbarButtonAction

User pressed the NavBar button

Note: The moduleActionButton callback is for analytics only. To handle module button taps, use TMTicketsModuleDelegate (see iOS Custom Modules). Similarly, the NavBar button is handled via TMTicketsOrderDelegate, not the analytics delegate.

User actions are delivered through the same UserAnalyticsDelegate observer as page views:

Transfer and resale actions:

Action

Description

ACTION_TRANSFERINITIATED

Transfer initiated

ACTION_TRANSFERCANCELLED

Transfer cancelled

ACTION_TRANSFERACCEPTED

Transfer accepted

ACTION_RESALECANCELLED

Resale cancelled

ACTION_SHARE_TRANSFER

Share transfer

Wallet and UI actions:

Action

Description

ACTION_ADD_TO_WALLET_INITIATE

Add to wallet initiated

ACTION_MY_TICKETS_HELP

Help button pressed on My Tickets

Health check actions:

Action

Description

ACTION_HEALTH_CHECK_MORE_INFO_CLICK

More Info clicked on health check

ACTION_HEALTH_CHECK_LEARN_MORE_CLICK

Learn More clicked on health check

ACTION_HEALTH_CHECK_GOT_IT_CLICK

Got It clicked on health check

Federated login actions:

Action

Description

ACTION_FED_LOGIN_LINK_ACCOUNTS_SCREEN_SHOWED

Link accounts screen showed

ACTION_FED_LOGIN_LINK_ACCOUNTS_SCREEN_DISMISSED

Link accounts screen dismissed

ACTION_FED_LOGIN_SCREEN_DISMISSED_AFTER_SUCCESS_LOGIN_NO_LINK

Login screen dismissed after successful login (no link)

ACTION_FED_LOGIN_LINK_ACCOUNTS_BUTTON_PRESSED

Link accounts button pressed

ACTION_FED_LOGIN_NO_THANKS_BUTTON_PRESSED

No thanks button pressed

Game Day actions:

Action

Description

ACTION_GAME_DAY_MODAL_SHOWED

Game Day modal showed

ACTION_GAME_DAY_FLOW_ACCEPTED

Game Day flow accepted

ACTION_GAME_DAY_FLOW_REJECTED

Game Day flow rejected

CMS module visibility:

These events are sent as plain strings (not via the UserAnalyticsActions.Action enum):

actionName

Description

"FIRST MODULE VIEWED"

First CMS module became visible

"MODULE VIEWED: N"

CMS module at index N became visible


Metadata

Each analytics event includes metadata providing context about the event, ticket, or module involved.

Metadata is delivered as a typed MetadataType enum. You can switch on it to extract the relevant data:

switch metadata {
case .events(let events):
    print(" - events: \(events.count)")
case .event(let event):
    print(" - event: \(event.info.identifier)")
case .eventTickets(let event, let tickets):
    print(" - event: \(event.info.identifier) tickets: \(tickets.count)")
case .eventTicket(event: let event, let ticket):
    let ticketSummary = "\(ticket.sectionName ?? "_") \(ticket.rowName ?? "_") \(ticket.seatName ?? "_")"
    print(" - event: \(event.info.identifier) ticket: \(ticketSummary)")
case .module(let event, let identifier):
    print(" - module: \(identifier) event: \(event.info.identifier)")
case .moduleButton(let event, let module, let button):
    print(" - module: \(module.identifier) button: \(button.title)(\(button.callbackValue)) event: \(event.info.identifier)")
case .empty:
    print(" - empty")
@unknown default:
    print(" - empty")
}

Metadata is delivered as a Bundle with string keys defined in the UserAnalyticsActions.ActionData enum.

General event/ticket context:

Key

Description

event_id

Event identifier

event_name

Event name

event_date

Event date

event_image_url

Event image URL

event_order_id

Order identifier

venue_name

Venue name

venu_id

Venue identifier

current_ticket_count

Current ticket count

artist_name

Artist name

artist_id

Artist identifier

Transfer-related:

Key

Description

initiate_transfer_ticket_count

Number of tickets being transferred

initiate_transfer_ticket_facevalue

Face value of tickets being transferred

initiate_transfer_ticket_serializable

Serialized transfer ticket data

cancel_transfer_id

Transfer ID being cancelled

cancel_transfer_order_id

Order ID of cancelled transfer

Resale-related:

Key

Description

initiate_resale_ticket_count

Number of tickets being listed for resale

initiate_resale_price

Listing price

initiate_resale_ticket_serializable

Serialized resale ticket data

update_resale_price

Updated resale price

update_resale_posting_id

Posting ID being updated

resale_buyer_fees

Buyer fees

resale_original_face_value

Original face value

resale_seller_payout

Seller payout amount

resale_seller_fees

Seller fees

cancel_resale_posting_id

Posting ID being cancelled

Other:

Key

Description

tm_tickets_module

Module identifier

event_orders

Event orders data

app_name

Application name

package_name

Application package name


Complete Examples

iOS

extension TicketsHelper: TMTicketsAnalyticsDelegate {

    func userDidView(page: TMTickets.Analytics.Page, metadata: TMTickets.Analytics.MetadataType) {
        print("userDidViewPage: \(page.rawValue)")

        // different Pages return different types of metadata
        switch metadata {
        case .events(let events):
            print(" - events: \(events.count)")
        case .event(let event):
            print(" - event: \(event.info.identifier)")
        case .eventTickets(let event, let tickets):
            print(" - event: \(event.info.identifier) tickets: \(tickets.count)")
        case .eventTicket(event: let event, let ticket):
            let ticketSummary = "\(ticket.sectionName ?? "_") \(ticket.rowName ?? "_") \(ticket.seatName ?? "_")"
            print(" - event: \(event.info.identifier) ticket: \(ticketSummary)")
        case .module(let event, let identifier):
            print(" - module: \(identifier) event: \(event.info.identifier)")
        case .moduleButton(let event, let module, let button):
            print(" - module: \(module.identifier) button: \(button.title)(\(button.callbackValue)) event: \(event.info.identifier)")
        case .empty:
            print(" - empty")
        @unknown default:
            print(" - empty")
        }
    }

    func userDidPerform(action: TMTickets.Analytics.Action, metadata: TMTickets.Analytics.MetadataType) {
        print("userDidPerformAction: \(action.rawValue)")

        // different Actions return different types of metadata
        switch metadata {
        case .events(let events):
            print(" - events: \(events.count)")
        case .event(let event):
            print(" - event: \(event.info.identifier)")
        case .eventTickets(let event, let tickets):
            print(" - event: \(event.info.identifier) tickets: \(tickets.count)")
        case .eventTicket(event: let event, let ticket):
            let ticketSummary = "\(ticket.sectionName ?? "_") \(ticket.rowName ?? "_") \(ticket.seatName ?? "_")"
            print(" - event: \(event.info.identifier) ticket: \(ticketSummary)")
        case .module(let event, let identifier):
            print(" - module: \(identifier) event: \(event.info.identifier)")
        case .moduleButton(let event, let module, let button):
            print(" - module: \(module.identifier) button: \(button.title)(\(button.callbackValue)) event: \(event.info.identifier)")
        case .empty:
            print(" - empty")
        @unknown default:
            print(" - empty")
        }
    }
}

Android

// Recommended: lifecycle-aware approach
class TicketsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setupAnalytics()
    }

    private fun setupAnalytics() {
        UserAnalyticsDelegate.handler.observe(this) { data ->
            data?.let {
                Log.d("Analytics", "Action: ${it.actionName}")

                it.data?.let { bundle ->
                    bundle.getString("event_id")?.let { eventId ->
                        Log.d("Analytics", " - event_id: $eventId")
                    }
                    bundle.getString("event_name")?.let { eventName ->
                        Log.d("Analytics", " - event_name: $eventName")
                    }
                }
            }
        }
    }
}

If you need to use observeForever (for example, in an Application class), make sure to clean up:

private val userAnalyticsObserver = Observer<UserAnalyticsDelegate.AnalyticsData?> {
    it?.let {
        Log.d("Analytics", "Action name: ${it.actionName}, data: ${it.data}")
    }
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    UserAnalyticsDelegate.handler.getLiveData().observeForever(userAnalyticsObserver)
}

override fun onDestroy() {
    super.onDestroy()
    UserAnalyticsDelegate.handler.getLiveData().removeObserver(userAnalyticsObserver)
}

Webviews

Many ticket operations such as Transfer and Resale have been moved into webviews (internal web pages). Currently, only a limited set of analytics events are returned from these web pages to the SDK.

Additional webpage analytics will be surfaced in future SDK releases.


Secure Entry SDK Analytics (Android Only)

The Secure Entry SDK on Android emits analytics via LocalBroadcastManager. You can register a BroadcastReceiver to listen for these events:

Event Constant

Value

EVENT_NTP_SYNC_FAIL

com.ticketmaster.presence.time.SecureEntryClock.NTP_SYNC_FAIL

EVENT_NTP_SYNC_OFFLINE

com.ticketmaster.presence.time.SecureEntryClock.NTP_SYNC_OFFLINE

EVENT_NTP_SYNC_COMPLETE

com.ticketmaster.presence.time.SecureEntryClock.NTP_SYNC_COMPLETE

EVENT_SECUREVIEW_NOT_SHOWN

com.ticketmaster.presence.time.SecureEntryClock.EVENT_SECUREVIEW_NOT_SHOWN


Related Documentation