Table of Contents
Overview of deep linking
Deep linking lets other parts of the system launch a particular piece of video content using parameters passed to the channel at launch time, rather than launching the home page for the channel.
To enable the deep link, you must identify each piece of content in your channel with a unique string, a
contentid. You can define the
contentid with any valid ASCII string, as long as it is less than 255 characters in length.
You must also associate a valid Roku-defined
mediaType with each
contentid. The mediaType value tells the Roku platform how to handle the content item. Once defined, this pair of identifiers,
mediaType, must not be changed or the content item cannot be found by the system.
Constructing a contentid
contentid is a unique identifier associated with a single piece of content. You define the layout of the contentids in your channel. These IDs are required so Roku can confirm that the content associated with a specific
contentid launches the deep link correctly.
A contentid is:
an opaque string - The format of a
contentidis defined by your channel, not Roku, and the
contentidis opaque to the Roku system. You define your own naming convention, but it is important that you maintain absolute consistency with this naming convention.
a single string - The
contentidmust be no more than 255 characters long.
an immutable value to identify a specific piece of content - The ID must identify the same content for all time.
URL encoded - The
contentidmust be URL encoded.
a command-line argument - The
contentidmust be passable as a command-line argument in a cURL command.
contentid could be as simple as a number or a name. It could also be the URL for the specific content item.
contentid can consist of several segments that are used by the channel itself to identify the content item. To separate a
contentid into segments, you can use vertical bars. The bars are also counted in the 255 character limit.
This example of an episode's contentid shows the segments separated by vertical bars:
In this example, each segment, such as
theSeries=XYZ, has a meaning to your channel, but not to Roku, since a
contentid is opaque to Roku's system. You can construct the
contentid to contain whatever you need to identify the episode properly, such as the TV series it is from and the season it is in, as well as the identifier for the specific episode.
If you are participating in Roku Search, the
PlayId in the XML feed must match the
contentid for the same content item. This is because the
PlayId gets passed into your channel as a
Choosing a mediaType
A mediaType is a value used to categorize each type of content available on your channel. See MediaType behavior for more information.
NOTE: To pass certification, you must submit one sample deep link for each
mediaType value used in your channel, along with a matching sample contentid. See Submitting deep linking content for certification.
Roku has defined the
mediaType values as:
- movie - a long-form film or movie
- series - a set of related TV shows consisting of episodes or seasons
- season - as part of a series, a season is a single set of related TV shows consisting of episodes
- episode - a single content item
short-form - a standalone content item of 15 minutes or less
- special - a single content item that does not fit into any other mediaType
- live - a live feed. *NOTE: You are not required to support deep linking to live feeds unless your channel has only live feeds.
Deep linking behavior
To ensure a standard user experience across the Roku platform, Roku has defined a set of behaviors that a channel should exhibit when responding to a deep link request.
Support mediaType values to categorize your content: Your channel must support as many or as few
mediaTypevalues as is necessary to accurately categorize all the content in your channel. If your channel has a mix of TV shows and feature-length films, you must support mediaType values “movie,” “series,” “season,” and “episode”. If instead, your channel has many live feeds available at a time, use the “live”
mediaType. Channels that include only a single live stream have only one possible behavior, but still must implement deep linking.
- Handle invalid deep links: Channels must handle invalid deep links gracefully and must not cause a crash. When deep linking with an invalid
contentid, the link must be set to return to the home screen of the channel.
- Handle unauthenticated users: Your channel must handle unauthenticated users who are deep linking into your channel or launching your channel for the first time. For example, this can happen when a user is deep linking into your channel from an ad or by using Roku Search for the first time. If the channel is uninstalled, Roku OS will prompt the user to install the channel before continuing with the deep link. Your code must route the user to the appropriate screen and then, when the user is authenticated, fulfill the deep link.
- Display paywall if needed: If your channel requires a purchase prior to launching, you are allowed to display a purchase screen before the user sees the content.
- Support a default profile If your service supports profiles, you must set a default profile for a movie, episode or series. Do not force a customer to choose a profile prior to playing a movie or episode. This is because Roku does not allow any screen (except a purchase or authentication screen) to be presented to the customer between choosing a movie or episode and playing it. Which profile you select as the default is your decision, but Roku recommends the last profile the customer used.
- Do not deep link into other channels: Channel must not deep link into 3rd-party channels.
When a deep link is requested, the channel's behavior depends on the mediaType value for the content. When content is launched with a deep link, it should start playing immediately except for the mediaType
season the user should be taken to an episodic picker screen.
|mediaType||contentid to Launch||Required Behavior on Launch|
|movie||movie's contentid||Launch directly into playback.|
|episode||episode's contentid||Launch directly into playback.|
Launch directly into playback, but determining which specific episode to launch or where in the episode to start playback is defined by your channel. See Series behavior for guidance.
*NOTE: There is no "series" contentid. Series is only a mediaType that is identified in the contentid for each episode in the series.
Launch directly into playback.
Launch directly into playback.
episodic picker screen for the season with the selected episode highlighted*
Launch episodic picker screen. Highlight the episode identified by the contentid.
An episodic picker screen displays episodes organized by season.
*NOTE: There is no "season" contentid. Season is only a mediaType that is identified in the contentid for each episode in the season.
|live||live feed's contentid to launch||Launch directly into playback.|
When a channel is passed a
series mediaType, it should receive an episode's contentid that identifies the content to be played and also the series it is in.
Remember: There is no "series" contentid. "series" is only a mediaType.
Once the series is identified from the episode's contentid, you should start playback based on the user's past viewership of the series and on the type of series it is. There are many different types of series: Serialized TV shows usually watched in sequence, sitcoms, nightly news, talk shows, etc., so there are several ways your channel could respond to a
Below are Roku’s recommended deep linking behavior for series:
|Type of Series||Definition||Recommended Behavior|
|Followed TV series|
A series that the user has already started watching in the past.
|Using the user’s bookmarked position, bring the user to the next episode in the series from where they last watched. Or, if they did not watch the last episode to completion, drop them into the moment where they last left off.|
|Unwatched TV series||A cataloged series that the user has not yet watched on your service.||Drop the user directly into video playback at the beginning of Season 1 Episode 1.|
|Daily or weekly shows||A regularly-occurring show that does not necessarily need to be watched in chronological order. News broadcasts, talk shows, sports podcasts, or religious sermons are examples of this type of series.||Play the most recent episode of the series.|
Implementing deep linking in a channel
The basic steps to implement deep linking are:
Step 1: Modify the channel's main.brs file.
Step 3: Add code for launching.
Step 4: For a
series, implement bookmarking.
Step 5: Use roInputEvent.
Step 6: Test using the Deep Linking Tester tool.
Step 1: Modify the channel's main.brs
Modify your channel to handle deep linking by editing your channel's main() or runuserinterface(). Add one argument to the function and name it
Function Main (args as Dynamic) as Void
Parse the associative array passed in to your channel's main entry point — usually main() in the
main.brs file. The two keys in the associate array that will be defined for the content item are the pair of deep link parameters, contentid and mediaType:
|contentid||Unique identifier you define for a specific piece of content.|
Any ASCII String < 255 characters long
|mediaType||Identifies the type of media to give context to the type of contentID passed.|
"series", "season", "episode", "movie", "short-form", "special" and "live"
|correlator||Optional third argument sent by ads when ads launch the channel.||Any ASCII String < 255 characters long|
Main() function for your channel to accept the two deep linking parameters by adding a variable. This variable can be any arbitrary name. In this example, the variable name
args is used. For a complete example, see Example.
contentid] and args[MediaType]
Step 2: Add a test for args[
Add code that tests
args[MediaType] are not invalid. If they have values, the channel is being deep linked to. Otherwise, do a normal channel launch.
Step 3: Add code for launching
Add code to launch the appropriate screen, unless your contentid is invalid. If it is invalid, display an error message and launch the channel normally. See the Example.
Step 4: Implement bookmarking for a series
- Decide which episode to play.
- Go to the appropriate place in that episode and start playback.
Step 5: Use roInputEvent to catch deep links while the channel is running
The roInput component enables deep linking without re-launching your channel. When the firmware resolves a voice input request (for example, “Play Game of Thrones” while your channel is in the foreground), your application can send the deep link parameters through the roInputEvent — instead of re-launching your channel with the parameters.
A message loop that listens for incoming events is typically used. If that event is an roInputEvent, an action is taken based on the input. If the input is a content ID, the channel typically finds the stream URL and metadata for that content ID, and then cues and plays the content.
See Sample channel to download and install a sample channel that demonstrates how to use roInputEvent to handle deep links while your channel is running.
Step 6. Test using Deep Linking Tester
Test the channel meets the requirements listed on this page as well as those listed on Certification. You can use the Deep Linking Tester Tool and the associated Roku Deep Linking Tester channel. See Testing deep linking. Another tool to play content using a deep link is to use the External Control API.
Example main.brs file
This is an example of a m
ain.brs file for a basic channel that requires no authentication:
sub Main() print "in showChannelSGScreen" 'Indicate this is a Roku SceneGraph application' screen = CreateObject("roSGScreen") m.port = CreateObject("roMessagePort") screen.setMessagePort(m.port)
if type(msg) = "roInputEvent"
'Create a scene and load /components/yourchannel.xml' scene = screen.CreateScene("Hello Channel") screen.show()
if (args.mediaType <> invalid) and (args.contentid <> invalid)
else if (args.mediaType = “season”)
if valid_contentid(contentid) ' You define this function in your back-end
while(true) msg = wait(0, m.port) msgType = type(msg) if msgType = "roSGScreenEvent" if msg.isScreenClosed() then return end if
if type(msg) = "roInputEvent"
You can download and install a sample channel that demonstrates how to launch content with deep links. It provides video content items that you can use to test deep linking via cURL commands and the External Control Protocol (ECP). It also shows you how you can design your application to deep link into content when both launching a channel and while the channel is already running.
Testing deep linking
You can test your deep links using cURL or by using the Roku Deep Linking Tester tool.
Using the Roku Deep Linking Tester
The Roku Deep Linking Tester tool allows you to do a test of your deep links prior to it going through the testing certification process.
NOTE: Roku highly recommends you use this tool as deep links must work for your channel to pass certification.
- Use the Roku Deep Linking Tester: https://devtools.web.roku.com/DeepLinkingTester/
- Use the associated Roku Deep Linking Tester channel: https://my.roku.com/account/add?channel=KX3UPK
This tool requires the same deep linking attributes as defined for cURL, but provides a UI plus other features to help, such as saving deep linking parameters to reuse.
- Open the Deep Linking Tester tool in your browser.
- Your Roku device and your PC should be connected to the same sub-network.
- Start the channel on the Roku device.
- Enter all required information in the Deep Linking Tester tool.
- Click "SEND".
- Verify the content plays immediately.
Using cURL for testing
Optionally, deep linking can be tested using cURL and the External Control Protocol (ECP). Using cURL for testing allows you to pass custom keys, such as a "correlator" key, and test them. However, passing a test using cURL does not indicate your deep link has passed; you should still run the Deep Linking Tester tool.
You can trigger deep linking by doing an HTTP post to port 8060 on your Roku device.
The contentid must be URL encoded. The form of the cURL is:
The followingattributes are required:
|IP Address||IP address of the Roku device with the channel sideloaded or installed||192.168.1.114|
|mediaType||the mediaType of the content to deep link to||movie|
|contentid||the contentid of the content to deep link to||1234|
The following example shows the cURL for a side-loaded channel with a mediaType of
movie and a contentid of
Submitting deep linking content for certification
Prior to submitting your channel, ensure all requirements listed on Certification have been met.
You submit your channel for certification using Developer Dashboard. Every type of mediaType value used in your channel requires a sample when submitting the channel for certification. For example, if you have both movies and live feeds, you would need two sample values, "
mediaType=movie" and "
Each sample consists of a pair of deep link parameters, the mediaType value and a matching contentid. These parameter pairs are used by Roku to certify that your channel is responding with the correct behavior for each type of content in your channel. For instance, if your channel has both movies and live feeds, you need to provide two sets of parameter pairs.
This pair should be provided in Developer Dashboard on the Support Information page for the channel in the field "Test Accounts & Deep Linking Parameters". You can enter your deep linking content by pasting in your
contentid, such as this movie's deep linking parameter pair: