---
agentTools:
  projectIndex: https://docs.storyly.io/llms.txt
---

# Deep Links

This guide shows you how to handle deep links in your application, open a fullscreen content programmatically and share a content link.

# Core Building Block: STRWidgetController

`STRWidgetController` is the base controller for all widgets in the Storyly Placement SDK. It provides access to common methods like opening content via a deep link URI, pausing, and resuming.

Application needs to hold a reference to the controller obtained from the `onWidgetReady` callback of `STRListener` to open content. If you need widget-specific functionality (like opening by ID), you can also obtain a typed controller (e.g., `STRStoryBarController`).

```kotlin StoryBar
private var widgetController: STRWidgetController? = null
private var videoFeedController: STRVideoFeedController? = null

placementView.listener = object : STRListener {
    override fun onWidgetReady(
        widget: STRWidgetController, 
        ratio: Float
    ) {
        // Hold base controller for general methods (e.g., open with URI)
        widgetController = widget

        // Hold typed controller for widget-specific methods (e.g., open with IDs)
        widget.storyBar { storyBarController = it }   
		}
}
```
```kotlin VideoFeed
private var widgetController: STRWidgetController? = null
private var videoFeedController: STRVideoFeedController? = null

placementView.listener = object : STRListener {
    override fun onWidgetReady(
        widget: STRWidgetController, 
        ratio: Float
    ) {
				// Hold base controller for general methods (e.g., open with URI)
        widgetController = widget

        // Hold typed controller for widget-specific methods (e.g., open with IDs)
        widget.videoFeed { videoFeedController = it }
    }
}
```

# Deep Links to Content

This guide shows you how to handle deep links in your application and open a fullscreen content programmatically.

Storyly Dashboard generates a deep link with the application's predefined custom scheme.

> 🚧 Warning
>
> You need to set the URL Scheme in the Storyly Dashboard -> Settings -> Apps & Websites -> URL Scheme in order to get the deep links properly from the dashboard.

> 🚧 Warning
>
> Make sure that the application schema is defined in your application's AndroidManifest.xml file.

> 🚧 Warning
>
> Application needs to handle intent routing, determine from the URL's host whether it is related to Storyly and pass the related URI to the Storyly Placement SDK to open content. The host will be `storyly` for Storyly Dashboard generated deep link URLs.

## Open Fullscreen Content with Deep Link URI

You need to pass the deep link to the `open` method of the controller.

```kotlin Kotlin
widgetController?.open(payload = uri)
```

## Open Fullscreen Content with Content IDs

You need to pass the content ids to the `open` method of the controller.

```kotlin StoryBar
storyBarController?.open(
    storyGroupId = "story_group_id",
    storyId = "story_id",   // optional
    play = STRStoryBarPlayMode.Default
)
```
```kotlin VideoFeed
videoFeedController?.open(
    feedGroupId = "feed_group_id",
    feedId = "feed_id",     // optional
    play = STRVideoFeedPlayMode.Default
)
```

<br />

## Play Modes in Content Links

Play Modes are used to define the behavior of the content when it is opened. StoryBar and VideoFeed follow the same play modes.

* **Playing to the End**

This mode plays the content to the end starting from the specified content and then closes the fullscreen content. This is the default play mode.

* **Playing a Single Content Group**

This mode plays only the specified group starting from the specified content. You need to define the play mode as `StoryGroup for StoryBar` / `FeedGroup for VideoFeed`.

* **Playing a Single Content Item**

This mode plays only the specified item. You need to define the play mode as `Story for StoryBar` / `Feed for VideoFeed`.

# Setup Listeners

You need to set up listeners to handle events from the `open` methods. `StoryShowFailed` is triggered the content could not be opened due to invalid parameters or inactive content for that user.

```kotlin StoryBar
placementView.listener = object : STRListener {
    override fun onFail(
        widget: STRWidgetController, 
        payload: STRErrorPayload
    ) {
        payload.storyBar { barErrorPayload ->
            if (barErrorPayload.error == StoryBarError.StoryShowFailed) {
                // handle story show failure
            }
        }
    }
}
```
```kotlin VideoFeed
placementView.listener = object : STRListener {
    override fun onFail(
        widget: STRWidgetController, 
        payload: STRErrorPayload
    ) {
        payload.videoFeed { feedErrorPayload ->
            if (feedErrorPayload.error == VideoFeedError.FeedShowFailed) {
                // handle video feed show failure
            }
        }
    }
}
```