# Customize click behaviors (iOS)

The SDK provides behavior delegate methods to customize click behaviors, including those for the video CTA button, product cards, and shopping CTA button.

### Customize video overlay CTA button click behavior

1. Set `FireworkVideoCTADelegate` delegate:

```swift
FireworkVideoSDK.ctaDelegate = <FireworkVideoCTADelegate delegate>
```

2\. Implement `handleCustomCTAClick(_:url:for:)`:

```swift
func handleCustomCTAClick(
    _ viewController: PlayerViewController,
    url: URL,
    for video: VideoDetails
) -> Bool {
    // Here, you could write codes to navigate to the host app page.
    // For best practices on navigating to the host page,
    // please consult "Navigate to the host app page" below.

    // Return true to customize video overlay CTA button click behavior
    return true
}
```

{% hint style="info" %}
You could write codes to navigate to the host app page within the delegate method. For best practices on navigating to the host page, please consult [Navigate to the host app](#navigate-to-the-host-app-page) page below.
{% endhint %}

### Customize click behaviors for shopping

To customize click behaviors for shopping, you need to set `FireworkVideoShoppingDelegate` delegate first:

```swift
FireworkVideoSDK.shopping.delegate = <FireworkVideoShoppingDelegate delegate>
```

#### Customize product card click behavior

Implement `fireworkShopping(_:didTapProductVariant:forVideo:)`:

```swift
func fireworkShopping(
    _ fireworkShopping: FireworkVideoShopping,
    didTapProductVariant item: SelectedProductVariant,
    forVideo video: VideoDetails
) -> Bool {
    // Here, you could write codes to navigate to the host app page.
    // For best practices on navigating to the host page,
    // please consult "Navigate to the host app page" below.

    // Return true to customize product card click behavior
    return true
}
```

{% hint style="info" %}
You could write codes to navigate to the host app page within the delegate method. For best practices on navigating to the host page, please consult [Navigate to the host app](#navigate-to-the-host-app-page) page below.
{% endhint %}

#### Customize shopping CTA click behavior

Implement `fireworkShopping(_:productVariantCTASelected:fromVideo:ctaCompletionHandler:)`:

```swift
func fireworkShopping(
    _ fireworkShopping: FireworkVideoShopping,
    productVariantCTASelected item: SelectedProductVariant,
    fromVideo video: VideoDetails,
    ctaCompletionHandler: @escaping ShoppingCTAHandler
) {
    // Here, you could write codes to navigate to the host app page.
    // For best practices on navigating to the host page,
    // please consult "Navigate to the host app page" below.

    // Calling completion closure with none refer to
    // host app will customize the click behavior
    ctaCompletionHandler(.none)
}
```

{% hint style="info" %}
You could write codes to navigate to the host app page within the delegate method. For best practices on navigating to the host page, please consult [Navigate to the host app](#navigate-to-the-host-app-page) page below.
{% endhint %}

#### Customize product link button click behavior

Implement `fireworkShopping(_:didTapLinkButtonAt:fromVideo:withURL:)`:

```swift
func fireworkShopping(
        _ fireworkShopping: FireworkVideoShopping,
        didTapLinkButtonAt item: SelectedProductVariant,
        fromVideo video: VideoDetails,
        withURL itemURL: String
    ) -> Bool {
        // Here, you could write codes to navigate to the host app page.
        // For best practices on navigating to the host page,
        // please consult "Navigate to the host app page" below.

        // Return true to customize product link button click behavior
        return true
}
```

{% hint style="info" %}
You could write codes to navigate to the host app page within the delegate method. For best practices on navigating to the host page, please consult [Navigate to the host app](#navigate-to-the-host-app-page) page below.
{% endhint %}

#### Customize cart icon click behavior

1. Set `cartAction` to `custom`:

```swift
FireworkVideoSDK.shopping.cartAction = .custom
```

2. Implement `fireworkShopping(_:didTapCartIconForVideo:)`:

```swift

func fireworkShopping(
    _ fireworkShopping: FireworkVideoShopping,
    didTapCartIconForVideo videoDetails: VideoDetails
) {
    // Here, you could write codes to navigate to the host app page.
    // For best practices on navigating to the host page,
    // please consult "Navigate to the host app page" below.
}
```

{% hint style="info" %}
You could write codes to navigate to the host app page within the delegate method. For best practices on navigating to the host page, please consult [Navigate to the host app](#navigate-to-the-host-app-page) page below.
{% endhint %}

### Custom livestream link interaction click behavior

1. Set `FireworkLiveStreamBehaviorDelegate` delegate:

```swift
FireworkVideoSDK.liveStreamBehaviorDelegate = <FireworkLiveStreamBehaviorDelegate delegate>
```

2. Implement `fireworkLiveStream(_:didTapLinkInteraction:)`:

```swift
func fireworkLiveStream(
    _ liveStream: LiveStreamEventDetails,
    didTapLinkInteraction interaction: LiveStreamLinkInteraction
) -> Bool {
    // Here, you could write codes to navigate to the host app page.
    // For best practices on navigating to the host page,
    // please consult "Navigate to the host app page" below.

    // Return true to customize livestream link interaction click behavior
    return true
}
```

{% hint style="info" %}
You could write codes to navigate to the host app page within the delegate method. For best practices on navigating to the host page, please consult [Navigate to the host app](#navigate-to-the-host-app-page) page below.
{% endhint %}

#### Customize social attribution click behavior

1. Set `FireworkVideoSocialDelegate` delegate:

```swift
FireworkVideoSDK.socialDelegate = <FireworkVideoSocialDelegate delegate>
```

2. Implement `handleSocialAttributionClick(_:fromVideo:):`

```swift
func handleSocialAttributionClick(
    _ source: VideoSocialAttributionSource,
    fromVideo video: VideoDetails,
) -> Bool {
    // This delegate method allows the host app to customize the behavior when users tap on
    // social media attribution displayed in videos. If the host app returns `false` or if
    // this delegate is not set, the SDK will open the URL using `UIApplication.shared.open`.
    return false
}
```

#### Customize video feed item click behavior

1. Set VideoFeedViewControllerDelegate delegate:

```swift
videoFeedVC.delegate = <VideoFeedViewControllerDelegate delegate>
```

2. Implement videoFeed`(_:didTapFeedItem:):`

<pre class="language-swift"><code class="lang-swift"><strong>func videoFeed(
</strong>    _ viewController: VideoFeedViewController,
    didTapFeedItem feedItemDetails: FeedEventDetails
) -> Bool {
    /// Called when the user taps a feed item.
    ///
    /// Return `true` to indicate that the tap has been handled externally,
    /// preventing the SDK from opening the full-screen player.
    /// Return `false` to let the SDK proceed with the default behavior.
    return false
}
</code></pre>

### Navigate to the Host App Page

We have three ways to navigate to the host app page when customizing click behaviors.

1. Present the host app page over the SDK player.
2. Push the host app page inside the SDK player.
3. Use the host app navigation controller to push the host app page.

#### Present the Host App Page Over the SDK Player

Use `present` to display the host app PDP page over the SDK player:

```swift
func fireworkShopping(
    _ fireworkShopping: FireworkVideoShopping,
    didTapProductVariant item: SelectedProductVariant,
    forVideo video: VideoDetails
) -> Bool {
    // The following PDP view controller is a sample.
    // Please create your own PDP view controller.
    let pdpVC = UIViewController()
    // As we may have other flows in PDP(such as the checkout page),
    // we could embed the PDP controller with navigation controller.
    let nav = UINavigationController(rootViewController: pdpVC)
    nav.modalPresentationStyle = .fullScreen
    UIViewController.topPresentedVC()?.present(nav, animated: true)
    
    // Return true to customize product card click behavior
    return true
}
```

#### Push the Host App Page Inside the SDK Player

`UIViewController.topNavigationController()` resolves to different navigation controllers depending on the current context:

* **Inside the fullscreen player**: returns the player's own navigation controller, so the page is pushed within the player context.
* **Inside a story block**: falls back to the host app's navigation controller.

Because the fullscreen player hides the navigation bar, the pushed view controller must explicitly show and configure it in `viewWillAppear`. Using `viewWillAppear` (rather than `viewDidLoad`) is important — when the user navigates back, UIKit calls `viewWillAppear` on the player, allowing it to hide the bar again and restore its original state.

```swift
func fireworkShopping(
    _ fireworkShopping: FireworkVideoShopping,
    didTapProductVariant item: SelectedProductVariant,
    forVideo video: VideoDetails
) -> Bool {
    // `topNav` resolves to the fullscreen player's navigation controller when inside
    // the fullscreen player, or to the host app's navigation controller inside a story block.
    if let topNav = UIViewController.topNavigationController() {
        let vc = HostAppProductDetailsController()
        vc.hidesBottomBarWhenPushed = true
        topNav.pushViewController(vc, animated: true)
    }
    
    // Return true to customize product card click behavior
    return true
}

class HostAppProductDetailsController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .red
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // Show and configure the navigation bar here to match your design.
        // Since the navigation bar is shared with the fullscreen player, configuring it in
        // `viewWillAppear` ensures the player's original bar state (hidden, style, etc.)
        // is restored when navigating back.
        navigationController?.setNavigationBarHidden(false, animated: true)
        configNavigationBar()
    }

    private func configNavigationBar() {
        self.title = "PDP"
        guard let navBar = navigationController?.navigationBar else { return }
        let bgColor = UIColor.white
        if #available(iOS 15, *) {
            let navigationBarAppearance = UINavigationBarAppearance()
            navigationBarAppearance.backgroundColor = bgColor

            navBar.scrollEdgeAppearance = navigationBarAppearance
            navBar.standardAppearance = navigationBarAppearance
        } else {
            navBar.barTintColor = bgColor
        }
    }
}
```

#### Use the Host App Navigation Controller to Push the Host App Page

When the fullscreen player is visible, the host app's navigation controller sits beneath it, so any page pushed directly would be obscured by the player.

`FireworkVideoSDK.startPiPOrDismissFullScreenPlayer` handles this by transitioning the player to a floating window (if PiP is enabled) or dismissing it (if PiP is disabled), ensuring the new page is fully visible. To always dismiss the player regardless of PiP, use `FireworkVideoSDK.dismissFullScreenPlayer` instead.

```swift
func fireworkShopping(
    _ fireworkShopping: FireworkVideoShopping,
    didTapProductVariant item: SelectedProductVariant,
    forVideo video: VideoDetails
) -> Bool {
    /*
     When a Firework full-screen player is present, startPiPOrDismissFullScreenPlayer will either
     transition it to a floating player (if PiP is enabled), or dismiss it (if PiP is disabled).
     If you wish to consistently dismiss the full-screen player, regardless of whether PiP is
     enabled or not, you can use the dismissFullScreenPlayer API.
     */
    FireworkVideoSDK.startPiPOrDismissFullScreenPlayer { _ in
        // Use host app navigation controller to push the host app page.
        // But you can also use your own method to push the host app page.
        if let nav = FireworkVideoSDK.getHostAppNavigationController() {
            // The following PDP view controller is a sample.
            // Please create your own PDP view controller.
            let pdpVC = UIViewController()
            nav.pushViewController(pdpVC, animated: true)
        }
    }
    return true
}
```

{% hint style="info" %}
The above code snippets are based on `fireworkShopping(_:didTapProductVariant:forVideo:)`. But they are also applicable to other behavior delegate methods.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.firework.com/firework-for-developers/ios-sdk/integration-guide-for-ios-sdk/customization-ios/customize-click-behaviors-ios.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
