---
title: "React Native Retail SDK - Pre-Purchase"
slug: "react-native-retail-sdk-1"
updated: 2024-10-21T09:06:41Z
published: 2024-10-21T09:06:41Z
canonical: "ignite.ticketmaster.com/react-native-retail-sdk-1"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://ignite.ticketmaster.com/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native Retail SDK - Pre-Purchase

## Retail SDK - Pre-Purchase

#### React Native (iOS)

Create a new **.swift** file, the name in this guide is **"PrePurchaseSDK"** but call it whatever you like. If it is the first time making a **.swift** file, Xcode will prompt you to make a **Bridging-Header.h** file, press "**Create Bridging Header**". A **Bridging-Header.h** will expose Objective-C public headers to Swift.

In **[PROJECT-NAME]-Bridging-Header.h** file add

```objectivec
#import <React/RCTBridgeModule.h>
```

In your **PrePurchaseSDK****.swift** create a class and extend **NSObject** like below:

```swift
@objc(PrePurchaseSDK)
class PrePurchaseSDK: NSObject {

}
```

Import **TicketmasterAuthentication,** **TicketmasterTickets, TicketmasterDiscoveryAPI** and **TicketmasterPrePurchase** which should have been made available after adding the Ticketmaster Frameworks.

```swift
import TicketmasterAuthentication
import TicketmasterTickets
import TicketmasterPrePurchase
import TicketmasterDiscoveryAPI
```

Declare a **loadSDKView** function which will accept the `venueID`:

```swift
@objc public static func loadSDKView(_ venueId: String) {
}
```

Configure the Authentication SDK (needed for Tickets and Retails SDK’s) and Ticket’s SDK. Use an API key generated via the [developer account](https://developer-acct.ticketmaster.com/user/login?destination=user).

```swift
  @objc public static func loadSDKView(_ venueId: String) {
    let apiKey = RNCConfig.env(for: "API_KEY") ?? ""
    let tmxServiceSettings = TMAuthentication.TMXSettings(apiKey: apiKey,
                                                          region: .US)

    let defaultBrandColor = UIColor(hexString: "026cdf") // TM blue
    let branding = TMAuthentication.Branding(displayName: "My Team",
                                             backgroundColor: .init(hexString: "#026cdf"), 
                                              theme: .light)
    
    let brandedServiceSettings = TMAuthentication.BrandedServiceSettings(tmxSettings: tmxServiceSettings,
                                                                         branding: branding)
    
    TMPrePurchase.shared.configure(apiKey: apiKey, completion: { isPrePurchaseApiSet in
      print("PrePurchase api key set result: \(isPrePurchaseApiSet)")
      TMDiscoveryAPI.shared.configure(apiKey: apiKey, completion: { isDiscoveryApiSet in
        print("Discovery api key set result: \(isDiscoveryApiSet)")
        TMPrePurchase.shared.brandColor = UIColor(red: 2, green: 108, blue: 223, alpha: 1.00)
        
        print("Authentication SDK Configuring...")
        TMAuthentication.shared.configure(brandedServiceSettings: brandedServiceSettings) {
          backendsConfigured in
          
          print(" - Authentication SDK Configured: \(backendsConfigured.count)")
          
          // TMTickets inherits it's configuration and branding from TMAuthentication
          print("Tickets SDK Configuring...")
          TMTickets.shared.configure {
            
            // Tickets is configured, now we are ready to present TMTicketsViewController or TMTicketsView
            print(" - Tickets SDK Configured")
            var viewController: TMPrePurchaseViewController
            viewController = TMPrePurchaseViewController.venueDetailsViewController(venueIdentifier: venueId, enclosingEnvironment: .modalPresentation)
            viewController.modalPresentationStyle = .fullScreen
            UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.present(viewController, animated: true)

            
            
          } failure: { error in
            // something went wrong, probably TMAuthentication was not configured correctly
            print(" - Tickets SDK Configuration Error: \(error.localizedDescription)")
          }
        } failure: { error in
          // something went wrong, probably the wrong apiKey+region combination
          print(" - Authentication SDK Configuration Error: \(error.localizedDescription)")
        }
      })
    })
  }
```

#### **Presenting the PrePurchase view**

Create a **RetailSDK** class in RetailSDK.swift file at the root of the project and add a function for presenting the prepurchase flow.

```swift
@objc(RetailSDK)
class RetailSDK: NSObject {
  @objc public func presentPrePurchaseVenue(_ venueId: String) {
     PrePurchaseSDK.loadSDKView(venueId)
  }
}
```

The RetailSDK class might also have a function for presenting the purchase flow if needed (check out the Purchase documentation for reference).

#### **Exposing Native View to React Native**

Create a new **.m** file for **RetailSDK - RetailSDK.m.** Paste in the below inside **RetailSDK.m**:

```objectivec
#import "React/RCTBridgeModule.h"

@interface RCT_EXTERN_MODULE(RetailSDK, NSObject)

- (dispatch_queue_t)methodQueue
{
  return dispatch_get_main_queue();
}

+ (BOOL)requiresMainQueueSetup {
  return true;
}

RCT_EXTERN_METHOD(presentPrePurchaseVenue:(NSString *)venueId)

@end
```

#### **Show the Native View in React Native**

For the **Pre-Purchase** and **Purchase** SDK there isn't an **embedded** view like the Ticket's SDK as these SDK's Native header are not configurable as they need back button for users to "go back" during event and venue navigations. In your React Native project, in any file, paste:

```typescript
import {NativeModules} from 'react-native'

const showSDKView = async () => {
  await NativeModules.RetailSDK.presentPrePurchaseVenue(id)
}
```

**Customized Branding**

You can customize branding of the Retail SDK in your ViewController file. Another example can be seen here: [https://ignite.ticketmaster.com/docs/customize-branding](https://ignite.ticketmaster.com/docs/customize-branding)

### Analytics

To setup delegates in React Native iOS see: [https://ignite.ticketmaster.com/docs/react-native-accounts-information](https://ignite.ticketmaster.com/docs/react-native-accounts-information)

After setting up Delegates in your Accounts SDK **NSObject**/**RCTEventEmitter** class you can follow: [https://ignite.ticketmaster.com/v1/docs/analytics-ios-1](https://ignite.ticketmaster.com/v1/docs/analytics-ios-1)

### **React Native Display Venue Detail Page (Android)**

Create a listener that implements **TMPrePurchaseNavigationListener.** You will use this to handle callbacks

```kotlin
class PrePurchaseNavigationListener(
    private val context: Context,
    private val closeScreen: () -> Unit
) :
    TMPrePurchaseNavigationListener {
    override fun openEventDetailsPage(
        abstractEntity: DiscoveryAbstractEntity?,
        event: DiscoveryEvent
    ) {
        context.startActivity(
            Intent(
                context, PurchaseActivity::class.java
            ).apply {
                putExtra("eventId", event.hostID.orEmpty())
            }
        )
    }

    override fun onPrePurchaseClosed() {
        closeScreen.invoke()
    }

    override fun onDidRequestCurrentLocation(
        globalMarketDomain: TMMarketDomain?,
        completion: (CoordinatesWithMarketDomain?) -> Unit
    ) {
    }

    override fun onDidUpdateCurrentLocation(
        globalMarketDomain: TMMarketDomain?,
        location: Location
    ) {}
}
```

Create a PrePurchaseActivity

```kotlin
class PrePurchaseActivity : AppCompatActivity() {
    private lateinit var fragment: Fragment

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.venue_layout)

        val tmPrePurchase = TMPrePurchase(
            discoveryAPIKey = BuildConfig.API_KEY,
            brandColor = ContextCompat.getColor(
                this@PrePurchaseActivity,
                R.color.black
            )
        )
        val eventId = intent.getStringExtra("eventId")

        val discoveryVenue: DiscoveryAbstractEntity = DiscoveryVenue(hostID = eventId)
        val tmPrePurchaseWebsiteConfiguration = TMPrePurchaseWebsiteConfiguration(
            discoveryVenue,
            TMMarketDomain.US,
        )

        val bundle = tmPrePurchase.getPrePurchaseBundle(
            tmPrePurchaseWebsiteConfiguration
        )

        val factory = TMPrePurchaseFragmentFactory(
            tmPrePurchaseNavigationListener = PrePurchaseNavigationListener(
                context = this,
                apiKey = tmPrePurchase.discoveryAPIKey.orEmpty(),
            ) {
                finish()
            }
        ).apply {
            supportFragmentManager.fragmentFactory = this
        }

        fragment = factory.instantiatePrePurchase(ClassLoader.getSystemClassLoader()).apply {
            arguments = bundle
        }

        supportFragmentManager.beginTransaction()
            .add(R.id.venue_container, fragment)
            .commit()
    }
}
```

Create a new ReactMethod in ReactContextBaseJavaModule:

```kotlin
class AccountsSDKModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
    @ReactMethod
    fun navigateToPrePurchase(eventId: String) {
        val context = currentActivity
        val intent = Intent(context, PrePurchaseActivity::class.java)
        intent.putExtra("eventId", eventId)
        context?.startActivity(intent)
    }
}
```

You can invoke the React method in your react native:

```javascript
import {NativeModules} from 'react-native';
const {AccountsSDK} = NativeModules;
AccountsSDK.presentPrePurchase(Config.DEMO_ATTRACTION_ID);
```

Make sure you have PrePurchaseActivity added to your AndroidManifest.xml

```xml
        <activity
            android:name=".retail.PrePurchaseActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
            android:launchMode="singleTask"
            android:windowSoftInputMode="adjustResize"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
```

### PrePurchase to Purchase

The Prepurchase flow requires an events detail page when a user taps one of the events, which opens up the Purchase view. you can edit the **openEventDetailsPage** method in **PrePurchaseNavigationListener** class:

```kotlin
    override fun openEventDetailsPage(
        abstractEntity: DiscoveryAbstractEntity?,
        event: DiscoveryEvent
    ) {
        context.startActivity(
            Intent(
                context, PurchaseActivity::class.java
            ).apply {
                putExtra("eventId", event.hostID.orEmpty())
            }
        )
    }
```

#### **Customized Branding**

You can customize branding of the Retail SDK in your Fragment file. Another example can be seen here: [https://ignite.ticketmaster.com/docs/customize-branding](https://ignite.ticketmaster.com/docs/customize-branding)

#### **Analytics**

To implement user analytics tracking, it is necessary to register an observer with the `observeForever` function. By calling this method, the observer will always receive the analytics events regardless of the current state of the Application / Activity.

To start tracking, call `observeForever` in the `onCreate` method of your Application or Activity.

Example Kotlin Code:

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_tickets_sdk_host)
    ...
    setupAnalytics()
  }

private fun setupAnalytics() {
    //Initialize observer that will handle the analytics events
    //Must be called the observeForever as this will kept alive the observer until
    //the Activity is destroyed
    UserAnalyticsDelegate.handler.getLiveData().observeForever(userAnalyticsObserver)
  }

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

Don't forget to call `removeObserver`, after the Application has been terminated or the Activity destroyed. Example Kotlin Code:

```java
override fun onDestroy() {
 super.onDestroy()
 //Remove the observer in the onDestroy, as it won't be needed to keep traking
 //the analytics events.
  UserAnalyticsDelegate.handler.getLiveData().removeObserver(userAnalyticsObserver)
 }
```
