Skip to main content
Roku deep linking lets an external source — another channel, a Roku search result, or a voice command — launch GlobalTV directly to a specific piece of content, bypassing the channel grid. GlobalTV supports the mediaType=live deep link type for live channel playback. A deep link payload on Roku is an associative array with at least two fields: Any other mediaType value, or an empty contentId, is silently ignored. All deep link validation is centralised in source/main.brs. The function GTV_IsLiveDeepLink() is the single gate that both entry points pass their payload through before doing anything with it:
The check is deliberately strict: both fields must be present and non-empty, and mediaType must be exactly "live" after lowercasing.

Two entry points

launchDeepLink

Set at cold start from the args passed to Main(). The channel was not running when the link arrived.

inputDeepLink

Set while the app is already running, via an roInput event. The channel handles the link without restarting.
When Roku launches the channel, it passes an args associative array to Main(). If the args represent a valid live deep link, the payload is written to scene.launchDeepLink:
Observing launchDeepLink in MainScene triggers onLaunchDeepLink(), which stores the payload as m.pendingDeepLink. The pending deep link is then resolved once the channel list is available after auth and playlist load:
If the channel is already running when a deep link arrives, Roku fires an roInputEvent. The main message loop reads the event info and, if valid, writes it to scene.inputDeepLink:
Observing inputDeepLink triggers onInputDeepLink(), which calls ProcessDeepLink() immediately rather than queuing it as pending:
ProcessDeepLink() in components/MainScene.brs handles both cases after the initial validation:
1

Validate payload

ProcessDeepLink() re-validates the payload with IsLiveDeepLinkPayload().
2

Check channel list availability

If the channel list is empty (playlist has not loaded yet), the link is stored as m.pendingDeepLink and processed after OnPlaylistDone() completes.
3

Resolve channel index

ResolveDeepLinkChannelIndex() looks up the contentId in the loaded channel list.
4

Open the player

If a matching channel is found, ShowPlayer(idx) is called directly. If the contentId is not found in the list, the app falls back to the main screen.

Manifest requirement

For warm-start deep links to work, the channel manifest must declare input launch support:
Without this field, Roku will not route roInputEvent messages to a running channel, and warm-start deep links will never arrive.
supports_input_launch=1 is already present in the GlobalTV manifest and is one of the fields verified by the make check certification target.
You can send a test deep link to a sideloaded channel using the Roku External Control Protocol (ECP) from any machine on the same network as the Roku device.

Cold start (launch)

This terminates any running instance of the channel and re-launches it with the given args.

Warm start (input)

This sends an roInputEvent to the already-running channel without restarting it.
Replace <ROKU_IP> with your device’s IP address (visible under Settings → Network → About on the Roku) and <CHANNEL_ID> with a contentId value that exists in your playlist.
ECP only works on devices in developer mode. The launch/dev path targets the sideloaded channel specifically.