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

# Show Profile Widget

> Display the Gameball customer profile widget in your iOS app

# Display the Profile Widget

The Gameball profile widget shows customer points, tiers, achievements, leaderboards, available rewards, and full loyalty activity—all inside a native in-app experience.

Use this when the customer taps **Rewards**, **My Points**, **Loyalty**, or any entry point that should open their Gameball profile.

***

## Basic Usage

<div className="security-banner">
  <div className="security-banner-icon">🔒</div>

  <div className="security-banner-content">
    <strong>Secure API Access:</strong> To benefit from v4.1 secure API endpoints, pass the <code>sessionToken</code> parameter when showing the profile widget (required in upcoming SDK v4). This enables automatic routing to v4.1 secure endpoints. <a href="/api-reference/introduction-v4.1">Learn more about v4.1 →</a>
  </div>
</div>

<CodeGroup>
  ```swift Swift (Completion Handler) theme={null}
  import Gameball

  let request = ShowProfileRequest(
      customerId: "customer-123"
  )

  GameballApp.getInstance().showProfile(request, presentationStyle: .fullScreen) { success, errorMessage in
      if success {
          print("Profile displayed successfully")
      } else {
          print("Error: \(errorMessage ?? \"\")")
      }
  }
  ```

  ```swift Swift (With Session Token) theme={null}
  let request = ShowProfileRequest(customerId: "customer-123")

  GameballApp.getInstance().showProfile(
      request,
      presentationStyle: .fullScreen,
      sessionToken: "customer-token"
  ) { _, _ in }
  ```

  ```swift Swift (Async/Await) theme={null}
  import Gameball

  Task {
      do {
          let request = ShowProfileRequest(customerId: "customer-123")
          try await GameballApp.getInstance().showProfile(request, presentationStyle: .fullScreen)
      } catch {
          print("Error: \(error.localizedDescription)")
      }
  }
  ```
</CodeGroup>

***

## Request Parameters

<ParamField body="customerId" type="String">
  Unique permanent identifier of the customer whose profile you want to display. Optional in v3.1.1 (omit for guest mode).
</ParamField>

<ParamField body="openDetail" type="String">
  Opens a specific widget section (e.g., `"details_earn"`, `"details_redeem"`).\
  Defaults to the main profile view.
</ParamField>

<ParamField body="hideNavigation" type="Bool">
  Hides the widget's navigation bar. Defaults to `false`.
</ParamField>

<ParamField body="showCloseButton" type="Bool">
  Displays a floating close button. Defaults to `false`.
</ParamField>

<ParamField body="closeButtonColor" type="String">
  Hex value (e.g., `"#FF5733"`) for close button color. Only used when `showCloseButton = true`.
</ParamField>

<ParamField body="sessionToken" type="String">
  Optional per-request session token. Overrides the global SDK token. Required in upcoming SDK v4.
</ParamField>

***

### Validation Rules

* No validation for `customerId` (guest mode is allowed). Provide `customerId` for authenticated profiles.

***

## Advanced Configuration

### Open a Specific Section

```swift theme={null}
let request = ShowProfileRequest(
    customerId: "customer-123",
    openDetail: "details_earn"
)

GameballApp.getInstance().showProfile(request, presentationStyle: .fullScreen) { _, _ in }
```

***

### Guest Mode (v3.1.1+)

```swift theme={null}
// No customerId required
let guestRequest = ShowProfileRequest(
    showCloseButton: true,
    closeButtonColor: "#4CAF50"
)

GameballApp.getInstance().showProfile(guestRequest, presentationStyle: .pageSheet) { _, _ in }
```

***

### Custom Close Button

```swift theme={null}
let request = ShowProfileRequest(
    customerId: "customer-123",
    showCloseButton: true,
    closeButtonColor: "#FF5733"
)

GameballApp.getInstance().showProfile(request, presentationStyle: .fullScreen) { _, _ in }
```

***

### Hide Navigation

<Note>
  Best used with `openDetail` to guide users directly to a specific section when navigation is hidden.
</Note>

```swift theme={null}
let request = ShowProfileRequest(
    customerId: "customer-123",
    hideNavigation: true,
    openDetail: "details_earn"
)

GameballApp.getInstance().showProfile(request, presentationStyle: .fullScreen) { _, _ in }
```

***

## Implementation Examples

### UIKit — Button Action

```swift theme={null}
import UIKit
import Gameball

class ProfileViewController: UIViewController {
    
    @IBAction func showProfileTapped(_ sender: UIButton) {
        let request = ShowProfileRequest(
            customerId: "customer-123",
            showCloseButton: true,
            closeButtonColor: "#4CAF50"
        )
        
        GameballApp.getInstance().showProfile(request, presentationStyle: .fullScreen) { success, errorMessage in
            if let errorMessage = errorMessage {
                self.showAlert(message: errorMessage)
            } else if success {
                print("Profile displayed")
            }
        }
    }
    
    func showAlert(message: String) {
        let alert = UIAlertController(
            title: "Error",
            message: message,
            preferredStyle: .alert
        )
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    }
}
```

***

### SwiftUI Integration

```swift theme={null}
import SwiftUI
import Gameball

struct ProfileView: View {
    @State private var showError = false
    @State private var errorMessage = ""
    
    var body: some View {
        VStack {
            Button("View Rewards & Achievements") {
                showWidget()
            }
            .padding()
        }
        .alert("Error", isPresented: $showError) {
            Button("OK", role: .cancel) { }
        } message: {
            Text(errorMessage)
        }
    }
    
    func showWidget() {
        guard let vc = UIApplication.shared.windows.first?.rootViewController else {
            return
        }

        let request = ShowProfileRequest(
            customerId: "customer-123",
            showCloseButton: true
        )

        Task {
            do {
                try await GameballApp.getInstance().showProfile(
                    request,
                    presentationStyle: .fullScreen,
                    presentingViewController: vc
                )
            } catch {
                errorMessage = error.localizedDescription
                showError = true
            }
        }
    }
}
```

***

### Tab Bar Integration

```swift theme={null}
import UIKit
import Gameball

class MainTabBarController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
    }
}

extension MainTabBarController: UITabBarControllerDelegate {
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {

        if viewController.tabBarItem.tag == 2 { // Rewards tab
            let request = ShowProfileRequest(
                customerId: "customer-123"
            )
            
            GameballApp.getInstance().showProfile(request, presentationStyle: .fullScreen) { _, _ in }
            return false
        }
        
        return true
    }
}
```

***

## Widget Content

<CardGroup cols={2}>
  <Card title="Customer Info" icon="user">
    Points balance, tier, progress, and personal details
  </Card>

  <Card title="Reward Campaigns" icon="gift">
    Available rewards, challenges, badges, and earning opportunities
  </Card>

  <Card title="Leaderboard" icon="trophy">
    Ranking, competition, and top performers
  </Card>

  <Card title="Transaction History" icon="clock-rotate-left">
    Full breakdown of points earned and redeemed
  </Card>
</CardGroup>

<Info>
  All widget themes, layout options, and branding styles can be customized from the Gameball Dashboard.
</Info>

***

## Best Practices

<Steps>
  <Step title="Make It Discoverable">
    Add the profile entry point in a visible place (e.g. tab bar, profile screen, side menu).
  </Step>

  <Step title="Use Notification Badges">
    Indicate new rewards or achievements to drive engagement.
  </Step>

  <Step title="Deep Link Intelligently">
    Use `openDetail` to open specific sections after qualifying user actions (e.g., after earning points).
  </Step>

  <Step title="Handle Errors Gracefully">
    Always provide fallback UI or messaging for network interruptions.
  </Step>
</Steps>

<Tip>
  Showing the profile widget right after a reward is earned significantly boosts customer engagement.
</Tip>
